# https://github.com/smaramwbc/statewave 项目说明书

生成时间：2026-05-14 12:54:51 UTC

## 目录

- [Statewave 简介](#p-intro)
- [快速开始](#p-quickstart)
- [系统架构概览](#p-arch-overview)
- [数据流与生命周期](#p-data-flow)
- [Episode 管理](#p-episodes)
- [编译器系统](#p-compiler)
- [上下文检索与排名](#p-context-retrieval)
- [API 路由参考](#p-api-routes)
- [服务层实现](#p-services)
- [数据库架构](#p-database)

<a id='p-intro'></a>

## Statewave 简介

### 相关页面

相关主题：[系统架构概览](#p-arch-overview), [快速开始](#p-quickstart)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/smaramwbc/statewave/blob/main/README.md)
- [DOCKER.md](https://github.com/smaramwbc/statewave/blob/main/DOCKER.md)
- [server/starter_packs/statewave-support-agent/manifest.json](https://github.com/smaramwbc/statewave/blob/main/server/starter_packs/statewave-support-agent/manifest.json)
- [server/api/timeline.py](https://github.com/smaramwbc/statewave/blob/main/server/api/timeline.py)
- [server/api/admin.py](https://github.com/smaramwbc/statewave/blob/main/server/api/admin.py)
- [server/services/snapshots.py](https://github.com/smaramwbc/statewave/blob/main/server/services/snapshots.py)
- [scripts/docs_loader.py](https://github.com/smaramwbc/statewave/blob/main/scripts/docs_loader.py)
- [helm/statewave/README.md](https://github.com/smaramwbc/statewave/blob/main/helm/statewave/README.md)
</details>

# Statewave 简介

Statewave 是一个专为 AI Agent 设计的**记忆管理系统**，帮助 Agent 从真实世界的各种数据源中构建、检索和利用持久化记忆。通过提供 Episode（事件片段）摄取、Memory（记忆片段）编译、上下文组装等功能，Statewave 使 Agent 能够在多轮对话和工作流程中保持一致性和连续性。

资料来源：[README.md:1-20]()

## 核心概念

Statewave 的数据模型围绕以下核心实体构建：

```mermaid
graph TD
    A[Subject 主体] --> B[Episode 事件片段]
    A --> C[Memory 记忆片段]
    B --> D[Compilation 编译]
    C --> E[Context 上下文]
    F[Resolution 解决方案] --> A
    G[Snapshot 快照] --> A
```

### Subject（主体）

Subject 是最高层级的数据容器，代表一个特定的实体（如客户、项目、用户或任何需要记忆的抽象概念）。每个 Subject 拥有独立的 Episode 和 Memory 存储空间。

资料来源：[server/starter_packs/statewave-support-agent/manifest.json:8]()

### Episode（事件片段）

Episode 是 Statewave 中的基础数据单元，代表一次不可变的事件或交互记录。Episode 可以来源于：

- 实时对话转录
- GitHub Issues、Pull Requests
- 文档变更
- Slack 消息
- MCP Server 事件
- 任何自定义数据源

每个 Episode 包含标题、正文内容、元数据以及来源信息，通过 `content_hash` 实现内容去重和增量更新。

资料来源：[scripts/docs_loader.py:30-50]()

### Memory（记忆片段）

Memory 是经过编译（Compile）后的结构化记忆。编译过程从多个 Episode 中提取关键信息，生成包含以下属性的记忆单元：

| 属性 | 说明 |
|------|------|
| `kind` | 记忆类型（如决策、偏好、问题等） |
| `content` | 记忆内容 |
| `summary` | 摘要信息 |
| `confidence` | 置信度 |
| `valid_from` | 有效起始时间 |
| `valid_to` | 有效结束时间（可选） |
| `source_episode_ids` | 来源 Episode ID 列表 |

资料来源：[server/api/admin.py:50-80]()

### Resolution（解决方案）

Resolution 用于跟踪会话级别的解决方案状态，支持 SLA 指标计算和响应时间追踪。

资料来源：[server/api/timeline.py:60-90]()

### Snapshot（快照）

Snapshot 提供 Subject 的完整状态快照功能，包含 Episodes、Memories 和 Resolutions 的时间点副本，支持数据恢复和迁移场景。

资料来源：[server/services/snapshots.py:20-80]()

## 系统架构

Statewave 采用现代化的微服务架构设计，主要组件包括：

```mermaid
graph TD
    subgraph 客户端层
        A[Agent 应用]
        B[Connectors]
        C[SDK]
    end
    
    subgraph API 网关层
        D[FastAPI Server<br/>:8100]
        E[OpenAPI / Swagger]
    end
    
    subgraph 业务逻辑层
        F[Episode Service]
        G[Memory Service]
        H[Context Service]
        I[Timeline Service]
    end
    
    subgraph 数据层
        J[(PostgreSQL)]
        K[(Embedding Store)]
    end
    
    subgraph 外部服务
        L[LiteLLM]
        M[LLM Provider]
    end
    
    A --> D
    B --> D
    C --> D
    D --> F
    D --> G
    D --> H
    D --> I
    F --> J
    G --> J
    G --> K
    H --> L
    I --> J
    L --> M
```

### 技术栈

| 层级 | 技术选型 |
|------|----------|
| API 框架 | FastAPI |
| 数据库 | PostgreSQL + asyncpg |
| LLM 集成 | LiteLLM |
| 向量嵌入 | 可配置（默认 LiteLLM） |
| 部署方式 | Docker / Kubernetes Helm |

资料来源：[README.md:50-70]()

## API 参考

### 健康检查端点

| 端点 | 用途 |
|------|------|
| `GET /healthz` 或 `GET /health` | 存活探针 |
| `GET /readyz` 或 `GET /ready` | 就绪探针 |

### Episode 管理

| 方法 | 路径 | 描述 |
|------|------|------|
| `POST` | `/v1/episodes` | 摄取单个 Episode（追加模式） |
| `POST` | `/v1/episodes/batch` | 批量摄取最多 100 个 Episode |

资料来源：[README.md:30-45]()

### Memory 管理

| 方法 | 路径 | 描述 |
|------|------|------|
| `POST` | `/v1/memories/compile` | 编译 Memories（幂等操作） |
| `GET` | `/v1/memories/search` | 按类型、文本或语义相似度搜索 |

### Context 上下文组装

| 方法 | 路径 | 描述 |
|------|------|------|
| `POST` | `/v1/context` | 组装基于排序和 Token 限制的上下文包 |

### Subject 主体管理

| 方法 | 路径 | 描述 |
|------|------|------|
| `GET` | `/v1/subjects` | 列出已知主体及 Episode/Memory 计数 |
| `DELETE` | `/v1/subjects/{id}` | 永久删除主体的所有数据 |
| `GET` | `/v1/subjects/{id}/health` | 客户健康评分及可解释因素 |
| `GET` | `/v1/subjects/{id}/sla` | SLA 指标（响应时间、解决时间、违反情况） |

### 时间线与解决方案

| 方法 | 路径 | 描述 |
|------|------|------|
| `GET` | `/v1/timeline` | 按时间顺序排列的主体时间线 |
| `POST` | `/v1/resolutions` | 跟踪每个会话的解决方案状态 |
| `GET` | `/v1/resolutions` | 列出主体的解决方案 |
| `POST` | `/v1/handoff` | 生成紧凑的交接上下文包 |

资料来源：[README.md:35-55]()

## 编译模式

Statewave 支持两种编译模式：

### LLM 编译（默认）

使用大型语言模型从 Episode 中提取结构化 Memory，提供更高的语义理解能力。需要配置 LLM API Key。

### 启发式编译

基于规则的编译模式，适用于演示环境或无 LLM 场景，性能更快但语义理解能力有限。

配置方式：`STATEWAVE_COMPILER_TYPE=heuristic`

资料来源：[helm/statewave/README.md:25-30]()

## 连接器生态

Statewave 提供了丰富的连接器（Connector）生态系统，用于从不同数据源摄取 Episode：

| 数据源 | 功能 | 状态 |
|--------|------|------|
| MCP Server | Copilot/Claude/Cursor/Agent 记忆同步 | ✅ 已发布 |
| GitHub | Issues、PRs、Reviews、Releases → Repo 记忆 | ✅ 已发布 |
| Markdown | 本地文档、ADR、RFC → 决策记忆 | ✅ 已发布 |
| Slack | 频道消息同步 | ✅ 已发布 |
| n8n | 工作流事件集成 | ✅ 已发布 |
| Zapier | Zapier 自动化集成 | ✅ 已发布 |

安装方式（按需选择）：

```bash
npm install @statewavedev/connectors-github
npm install @statewavedev/connectors-markdown
npm install @statewavedev/connectors-slack
npm install @statewavedev/connectors-n8n
npm install @statewavedev/connectors-zapier
npm install @statewavedev/mcp-server
```

资料来源：[README.md:80-110]()

## 配置参考

### 环境变量配置

| 变量 | 默认值 | 说明 |
|------|--------|------|
| `STATEWAVE_DATABASE_URL` | — | PostgreSQL 连接字符串（必填） |
| `STATEWAVE_LITELLM_API_KEY` | — | LiteLLM API Key（LLM/嵌入必需） |
| `STATEWAVE_LITELLM_BASE_URL` | — | LiteLLM 自定义基础 URL |
| `STATEWAVE_EMBEDDING_PROVIDER` | `litellm` | 嵌入提供商 |
| `STATEWAVE_COMPILER_TYPE` | `llm` | `llm` 或 `heuristic` |
| `STATEWAVE_API_KEY` | — | API 认证密钥 |
| `STATEWAVE_RATE_LIMIT` | `0` | 每分钟/IP 请求限制（0=禁用） |
| `STATEWAVE_RATE_LIMIT_STRATEGY` | `distributed` | `distributed`（Postgres）或 `memory` |
| `STATEWAVE_WEBHOOK_URL` | — | Webhook 回调 URL |
| `STATEWAVE_TENANT_HEADER` | `X-Tenant-ID` | 多租户隔离 Header |
| `STATEWAVE_REQUIRE_TENANT` | `false` | 是否强制要求租户 Header |
| `STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS` | `4000` | 上下文组装默认 Token 预算 |
| `STATEWAVE_CORS_ORIGINS` | `["*"]` | 允许的 CORS 来源列表 |

资料来源：[README.md:100-120]()

## 部署方式

### Docker Compose 部署

```yaml
services:
  statewave:
    image: statewavedev/statewave:latest
    ports: ["8100:8100"]
    environment:
      STATEWAVE_DATABASE_URL: postgresql+asyncpg://statewave:statewave@db:5432/statewave
      STATEWAVE_LITELLM_API_KEY: sk-...
    depends_on:
      db:
        condition: service_healthy

volumes:
  pgdata:
```

```bash
docker compose up -d
curl http://localhost:8100/healthz
```

指定版本部署：

```bash
STATEWAVE_VERSION=0.7.0 docker compose up -d
```

### Kubernetes Helm 部署

```bash
helm install statewave ./helm/statewave \
  --set database.url='postgresql+asyncpg://...' \
  --set llm.apiKey='sk-...'
```

Helm 安装时会自动运行数据库迁移（Alembic）Job，确保在 API Pod 接收流量前完成 schema 初始化。

资料来源：[DOCKER.md:1-50]()
资料来源：[helm/statewave/README.md:1-30]()

### Docker 镜像标签

| 标签 | 含义 |
|------|------|
| `latest` | main 分支最新代码 |
| `X.Y.Z` | 语义化版本发布 |
| `X.Y` | 该 minor 版本的最新版本 |
| `X` | 该 major 版本的最新版本 |
| `sha-<7>` | 特定 Commit |

资料来源：[DOCKER.md:30-40]()

## 启动包

Statewave 提供了开箱即用的 Starter Pack，其中包含预置的 Episodes 和 Memories：

### statewave-support-agent

预编译的支持代理启动包，包含 276 个 Episodes 和 364 个 Memories，涵盖：

- 产品文档
- 架构设计
- 部署指南
- 故障排除
- 竞品对比

版本：`1.2026.05.08`

导入后可立即启用文档驱动的支持代理，无需额外引导步骤。

资料来源：[server/starter_packs/statewave-support-agent/manifest.json:1-20]()

## 当前限制

Statewave 目前处于活跃开发阶段（v0.8.0），存在以下已知限制：

### 速率限制

- **速率限制按 IP 级别**：使用分布式（Postgres 后端）实现，但仅按 IP 键控，尚未支持按租户或 API Key 级别限制

### 多租户

- **多租户隔离在应用层**：通过查询作用域数据隔离（v0.5）+ 每租户配置/策略/收据包（v0.8）实现
- **尚未支持 PostgreSQL RLS**（行级安全策略）

资料来源：[README.md:130-140]()

## 测试

### 运行测试

```bash
# 单元测试（无需数据库）
pytest tests/test_*.py -v

# 集成测试（需要 PostgreSQL）
PGPASSWORD=statewave createdb -h localhost -U statewave statewave_test
pytest tests/integration/ -v

# 全部测试
pytest tests/ -v
```

资料来源：[README.md:120-130]()

## 相关资源

- 官方文档：https://statewave.ai
- 仓库地址：https://github.com/smaramwbc/statewave
- 连接器生态：https://github.com/smaramwbc/statewave-connectors
- API 契约文档：https://github.com/smaramwbc/statewave-docs/blob/main/api/v1-contract.md

---

<a id='p-quickstart'></a>

## 快速开始

### 相关页面

相关主题：[Statewave 简介](#p-intro)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [docker-compose.yml](https://github.com/smaramwbc/statewave/blob/main/docker-compose.yml)
- [DOCKER.md](https://github.com/smaramwbc/statewave/blob/main/DOCKER.md)
- [.env.example](https://github.com/smaramwbc/statewave/blob/main/.env.example)
- [pyproject.toml](https://github.com/smaramwbc/statewave/blob/main/pyproject.toml)
</details>

# 快速开始

本页面提供 Statewave 的快速部署和基本使用指南，帮助你在本地环境快速启动服务并验证核心功能。

## 系统要求

| 组件 | 最低要求 | 推荐配置 |
|------|----------|----------|
| Docker | 20.10+ | 最新稳定版 |
| Docker Compose | 2.0+ | v2.x |
| PostgreSQL | 14+ | 15+ |
| 内存 | 4GB | 8GB+ |
| CPU | 2核 | 4核+ |

资料来源：[docker-compose.yml:1-50]()

## 快速启动（Docker Compose）

### 1. 克隆仓库

```bash
git clone https://github.com/smaramwbc/statewave.git
cd statewave
```

### 2. 配置环境变量

Statewave 通过环境变量进行配置。在项目根目录创建 `.env` 文件：

```bash
cp .env.example .env
```

基础配置项：

| 环境变量 | 默认值 | 说明 |
|----------|--------|------|
| `STATEWAVE_DATABASE_URL` | — | PostgreSQL 连接字符串，必填 |
| `STATEWAVE_LITELLM_API_KEY` | — | LLM API 密钥（用于编译功能） |
| `STATEWAVE_API_KEY` | — | API 访问密钥 |
| `STATEWAVE_PORT` | `8100` | 服务监听端口 |
| `STATEWAVE_RATE_LIMIT_PER_MIN` | `60` | 每IP每分钟请求限制 |

资料来源：[.env.example](https://github.com/smaramwbc/statewave/blob/main/.env.example)

### 3. 启动服务

```yaml
# docker-compose.yml 核心配置
services:
  app:
    image: statewavedev/statewave:latest
    ports:
      - "8100:8100"
    environment:
      STATEWAVE_DATABASE_URL: postgresql+asyncpg://statewave:statewave@db:5432/statewave
      STATEWAVE_LITELLM_API_KEY: sk-...
    depends_on:
      db:
        condition: service_healthy

volumes:
  pgdata:
```

```bash
docker compose up -d
```

资料来源：[DOCKER.md:1-20]()

### 4. 验证服务

服务启动后，通过健康检查端点验证：

```bash
curl http://localhost:8100/healthz
```

预期响应：`{"status":"ok"}`

| 端点 | 用途 |
|------|------|
| `GET /healthz` 或 `GET /health` | 存活检查 |
| `GET /readyz` 或 `GET /ready` | 就绪检查 |

资料来源：[README.md:50-55]()

## 服务架构

```mermaid
graph TD
    A[客户端] --> B[Statewave API<br/>:8100]
    B --> C[PostgreSQL<br/>Database]
    B --> D[LLM Provider<br/>LiteLLM]
    B --> E[Embedding Provider]
    
    F[Connectors] --> B
    G[SDK] --> B
    
    style B fill:#e1f5fe
    style C fill:#f3e5f5
```

## API 基础使用

### 文档界面

| 地址 | 说明 |
|------|------|
| `http://localhost:8100/docs` | OpenAPI (Swagger) 文档 |
| `http://localhost:8100/redoc` | ReDoc 文档 |

### 核心 API 端点

| 方法 | 路径 | 说明 |
|------|------|------|
| `POST` | `/v1/episodes` | 摄入单个事件（仅追加） |
| `POST` | `/v1/episodes/batch` | 批量摄入最多 100 个事件 |
| `POST` | `/v1/memories/compile` | 从事件编译记忆（幂等） |
| `GET` | `/v1/memories/search` | 按类型、文本或语义相似度搜索 |
| `POST` | `/v1/context` | 组装带 token 限制的上下文包 |
| `GET` | `/v1/timeline` | 按时间线查看主题历史 |
| `GET` | `/v1/subjects` | 列出已知主题及其事件/记忆计数 |
| `DELETE` | `/v1/subjects/{id}` | 永久删除主题的所有数据 |

资料来源：[README.md:40-45]()

### 基本请求示例

**摄入事件：**

```bash
curl -X POST http://localhost:8100/v1/episodes \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: default" \
  -d '{
    "subject_id": "user-123",
    "source": "api",
    "type": "conversation",
    "payload": {
      "role": "user",
      "content": "如何部署 Statewave？"
    },
    "session_id": "session-001"
  }'
```

**搜索记忆：**

```bash
curl "http://localhost:8100/v1/memories/search?query=部署" \
  -H "X-Tenant-ID: default"
```

## 版本管理

Statewave 支持指定版本部署：

```bash
STATEWAVE_VERSION=0.7.0 docker compose up -d
```

| 标签格式 | 含义 |
|----------|------|
| `latest` | main 分支最新代码 |
| `X.Y.Z` | 语义化版本发布 |
| `X.Y` | 所属小版本的最新版本 |
| `X` | 所属大版本的最新版本 |
| `sha-<7>` | 特定提交 |

资料来源：[DOCKER.md:25-35]()

## 运行测试

```bash
# 单元测试（无需数据库）
pytest tests/test_*.py -v

# 集成测试（需要 PostgreSQL）
PGPASSWORD=statewave createdb -h localhost -U statewave statewave_test
pytest tests/integration/ -v

# 运行全部测试
pytest tests/ -v
```

资料来源：[README.md:180-190]()

## 完整配置选项

| 环境变量 | 默认值 | 说明 |
|----------|--------|------|
| `STATEWAVE_DATABASE_URL` | — | PostgreSQL 连接 URL，必填 |
| `STATEWAVE_PORT` | `8100` | 服务端口 |
| `STATEWAVE_API_KEY` | — | API 密钥认证 |
| `STATEWAVE_LITELLM_API_KEY` | — | LiteLLM API 密钥 |
| `STATEWAVE_LITELLM_BASE_URL` | — | LiteLLM 基础 URL |
| `STATEWAVE_EMBEDDING_PROVIDER` | `litellm` | 嵌入提供者（litellm/stub） |
| `STATEWAVE_COMPILER_TYPE` | `llm` | 编译器类型（llm/heuristic） |
| `STATEWAVE_RATE_LIMIT_PER_MIN` | `60` | 每IP每分钟请求限制（0=禁用） |
| `STATEWAVE_RATE_LIMIT_STRATEGY` | `distributed` | 限流策略（distributed/memory） |
| `STATEWAVE_WEBHOOK_URL` | — | Webhook 回调 URL |
| `STATEWAVE_WEBHOOK_TIMEOUT` | `5.0` | Webhook 超时时间（秒） |
| `STATEWAVE_TENANT_HEADER` | `X-Tenant-ID` | 多租户隔离 Header |
| `STATEWAVE_REQUIRE_TENANT` | `false` | 是否强制要求租户 Header |
| `STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS` | `4000` | 上下文组装默认 token 预算 |
| `STATEWAVE_CORS_ORIGINS` | `["*"]` | 允许的 CORS 来源 |

资料来源：[README.md:155-175]()

## 下一步

- 查看 [API v1 完整契约](https://github.com/smaramwbc/statewave-docs/blob/main/api/v1-contract.md)
- 阅读[部署指南](https://github.com/smaramwbc/statewave-docs/blob/main/deployment/guide.md)
- 了解 [Connectors 生态系统](https://github.com/smaramwbc/statewave-connectors)
- 查看[架构文档](https://github.com/smaramwbc/statewave-docs/blob/main/architecture/overview.md)

---

<a id='p-arch-overview'></a>

## 系统架构概览

### 相关页面

相关主题：[数据流与生命周期](#p-data-flow), [API 路由参考](#p-api-routes), [服务层实现](#p-services)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [server/app.py](https://github.com/smaramwbc/statewave/blob/main/server/app.py)
- [server/core/config.py](https://github.com/smaramwbc/statewave/blob/main/server/core/config.py)
- [server/core/dependencies.py](https://github.com/smaramwbc/statewave/blob/main/server/core/dependencies.py)
- [server/api/__init__.py](https://github.com/smaramwbc/statewave/blob/main/server/api/__init__.py)
- [server/db/engine.py](https://github.com/smaramwbc/statewave/blob/main/server/db/engine.py)
- [README.md](https://github.com/smaramwbc/statewave/blob/main/README.md)
- [server/api/timeline.py](https://github.com/smaramwbc/statewave/blob/main/server/api/timeline.py)
- [server/api/admin.py](https://github.com/smaramwbc/statewave/blob/main/server/api/admin.py)
- [server/services/snapshots.py](https://github.com/smaramwbc/statewave/blob/main/server/services/snapshots.py)
- [server/services/context.py](https://github.com/smaramwbc/statewave/blob/main/server/services/context.py)
- [server/services/compilers/heuristic.py](https://github.com/smaramwbc/statewave/blob/main/server/services/compilers/heuristic.py)
- [DOCKER.md](https://github.com/smaramwbc/statewave/blob/main/DOCKER.md)
</details>

# 系统架构概览

## 1. 概述

Statewave 是一个自托管的长期记忆管理系统，专为 AI Agent 设计，旨在帮助 Agents 跨越会话边界保持上下文连贯性。该系统通过摄取事件片段（Episodes）、编译记忆（Memories）、并提供智能检索上下文构建能力，使 AI Agent 能够在多轮对话中持续学习和适应。

当前版本：v0.8.0，采用 AGPL-3.0 开源协议。资料来源：[README.md](https://github.com/smaramwbc/statewave/blob/main/README.md)

## 2. 核心设计理念

Statewave 的架构围绕三个核心概念展开：

| 概念 | 说明 |
|------|------|
| **Episode（事件片段）** | 原子化的输入单元，代表一次交互、一条消息或一个外部事件 |
| **Memory（记忆）** | 从 Episodes 编译提取的结构化知识，具有时间有效性和置信度 |
| **Subject（主体）** | 记忆归属的实体（如客户、用户、项目），实现数据隔离 |

系统支持两种编译模式：LLM 编译（语义理解）和 Heuristic 编译（规则提取）。资料来源：[server/services/compilers/heuristic.py](https://github.com/smaramwbc/statewave/blob/main/server/services/compilers/heuristic.py)

## 3. 系统架构图

```mermaid
graph TB
    subgraph 接入层
        API[REST API v1]
        DOCS[OpenAPI / Swagger]
        REDOC[ReDoc]
    end

    subgraph 应用层
        EP[Episode 管理]
        MEM[Memory 管理]
        CTX[Context 构建]
        TIMELINE[Timeline 服务]
        SNAP[Snapshot 服务]
        ADMIN[Admin API]
    end

    subgraph 服务层
        COMPILER[编译引擎]
        RANKER[排名服务]
        SEARCH[搜索服务]
    end

    subgraph 数据层
        DB[(PostgreSQL)]
        CACHE[缓存层]
    end

    API --> EP
    API --> MEM
    API --> CTX
    API --> TIMELINE
    API --> SNAP
    API --> ADMIN

    EP --> COMPILER
    MEM --> RANKER
    CTX --> RANKER
    CTX --> SEARCH

    COMPILER --> DB
    RANKER --> DB
    SEARCH --> DB
    TIMELINE --> DB
    SNAP --> DB
```

## 4. 技术栈

| 层级 | 技术选型 |
|------|----------|
| Web 框架 | FastAPI |
| 数据库 | PostgreSQL + asyncpg |
| ORM | SQLAlchemy (async) |
| 编译后端 | LiteLLM (支持多种 LLM 提供商) |
| 部署方式 | Docker Compose / Helm |
| 认证 | API Key / X-Tenant-ID 多租户隔离 |

资料来源：[DOCKER.md](https://github.com/smaramwbc/statewave/blob/main/DOCKER.md)

## 5. API 架构

### 5.1 主要端点

| 方法 | 路径 | 描述 |
|------|------|------|
| `POST` | `/v1/episodes` | 摄入单个事件片段 |
| `POST` | `/v1/episodes/batch` | 批量摄入事件片段（最多100个） |
| `POST` | `/v1/memories/compile` | 编译记忆（幂等操作） |
| `GET` | `/v1/memories/search` | 按类型、文本或语义相似度搜索 |
| `POST` | `/v1/context` | 组装带排名的 token 受限上下文包 |
| `GET` | `/v1/timeline` | 主体时间线 |
| `GET` | `/v1/subjects` | 列出已知主体及事件/记忆计数 |
| `DELETE` | `/v1/subjects/{id}` | 删除主体所有数据 |
| `POST` | `/v1/resolutions` | 跟踪会话解决状态 |
| `GET` | `/v1/resolutions` | 列出主体解决方案 |
| `POST` | `/v1/handoff` | 生成紧凑的交接上下文包 |
| `GET` | `/v1/subjects/{id}/health` | 健康评分及可解释因素 |
| `GET` | `/v1/subjects/{id}/sla` | SLA 指标 |

资料来源：[README.md](https://github.com/smaramwbc/statewave/blob/main/README.md)

### 5.2 健康检查端点

| 端点 | 用途 |
|------|------|
| `GET /healthz` 或 `GET /health` | 存活探针 |
| `GET /readyz` 或 `GET /ready` | 就绪探针 |

## 6. 数据模型

### 6.1 核心实体关系

```mermaid
erDiagram
    SUBJECT ||--o{ EPISODE : contains
    SUBJECT ||--o{ MEMORY : owns
    EPISODE ||--o{ MEMORY : contributes_to
    SUBJECT ||--o{ RESOLUTION : tracks
    SUBJECT ||--o| SNAPSHOT : preserves
```

### 6.2 Episode 数据结构

事件片段是系统的原子输入单元，包含：

```python
{
    "id": "uuid",
    "subject_id": "string",
    "source": "string",           # 来源标识 (e.g., "api", "github", "slack")
    "type": "string",            # 类型 (e.g., "chat", "issue", "doc_section")
    "payload": {
        "text": "string",
        "messages": [...],
        "event_time": "datetime"  # 可选的显式时间戳
    },
    "metadata": {},
    "provenance": {
        "content_hash": "string",
        "pack_version": "int"
    },
    "occurred_at": "datetime",
    "created_at": "datetime",
    "session_id": "string | null"
}
```

资料来源：[server/api/timeline.py](https://github.com/smaramwbc/statewave/blob/main/server/api/timeline.py)

### 6.3 Memory 数据结构

记忆从事件编译而来，具有时间有效性和置信度：

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | UUID | 唯一标识 |
| `subject_id` | string | 归属主体 |
| `kind` | string | 记忆类型（如 episode_summary, profile_fact） |
| `content` | string | 记忆内容 |
| `summary` | string | 内容摘要 |
| `confidence` | float | 置信度 0.0-1.0 |
| `valid_from` | datetime | 有效起始时间 |
| `valid_to` | datetime | 有效结束时间（可选） |
| `source_episode_ids` | list[UUID] | 来源事件片段 |
| `status` | string | 状态（active, superseded） |
| `sensitivity_labels` | list[string] | 敏感标签 |

资料来源：[server/services/snapshots.py](https://github.com/smaramwbc/statewave/blob/main/server/services/snapshots.py)

## 7. 服务层架构

### 7.1 编译引擎

编译引擎负责将 Episodes 转换为 Memories，支持两种模式：

```mermaid
graph LR
    A[Episodes] --> B{编译模式}
    B -->|Heuristic| C[规则提取]
    B -->|LLM| D[语义理解]
    C --> E[Memories]
    D --> E
```

**Heuristic 编译**：基于规则提取摘要和配置事实

- `episode_summary`：从文本提取摘要，置信度 0.8
- `profile_fact`：提取配置类事实，置信度 0.6

资料来源：[server/services/compilers/heuristic.py](https://github.com/smaramwbc/statewave/blob/main/server/services/compilers/heuristic.py)

### 7.2 上下文构建服务

上下文构建服务（Context Service）负责根据查询组装最优上下文：

```mermaid
graph TB
    Q[用户查询] --> S[搜索相关Memories和Episodes]
    S --> SC[评分计算]
    SC --> R[相关性评分]
    R --> RANK[排名服务]
    RANK --> TB[Token预算约束]
    TB --> CTX[组装上下文包]
```

Context Service 内部使用 `_ScoredItem` 类管理评分：

```python
class _ScoredItem:
    __slots__ = ("score", "kind", "memory_row", "episode_row", "text", "section")
```

资料来源：[server/services/context.py](https://github.com/smaramwbc/statewave/blob/main/server/services/context.py)

### 7.3 快照服务

快照服务支持主体的完整备份和恢复：

| 操作 | 说明 |
|------|------|
| 创建快照 | 导出主体的所有 Episodes、Memories、Resolutions |
| 恢复快照 | 支持时间偏移重放，可重建历史状态 |
| 增量更新 | 保留 `restored_from_snapshot` 元数据 |

资料来源：[server/services/snapshots.py](https://github.com/smaramwbc/statewave/blob/main/server/services/snapshots.py)

## 8. 时间线服务

时间线服务（Timeline Service）提供会话视图的事件合并展示：

```mermaid
graph TB
    subgraph 事件类型
        EE[Episode Event]
        RE[Resolution Event]
    end
    
    subgraph 时间线事件
        TEE[TimelineEpisodeEvent]
        TRE[TimelineResolutionEvent]
    end
    
    EE --> TEE
    RE --> TRE
    TEE --> MERGE[合并排序]
    TRE --> MERGE
    MERGE --> RESP[SessionTimelineResponse]
```

关键指标计算：
- `first_response_seconds`：首次响应时间
- `resolution_seconds`：解决时间
- `first_response_breached`：是否超出 SLA 首次响应阈值
- `resolution_breached`：是否超出 SLA 解决时间阈值

资料来源：[server/api/timeline.py](https://github.com/smaramwbc/statewave/blob/main/server/api/timeline.py)

## 9. 多租户架构

Statewave 采用应用层多租户隔离：

| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| `STATEWAVE_TENANT_HEADER` | `X-Tenant-ID` | 租户隔离 header |
| `STATEWAVE_REQUIRE_TENANT` | `false` | 是否强制要求租户 header |
| 隔离方式 | 查询作用域 | 基于 tenant_id 的数据过滤 |

**当前限制**：
- 限流基于 IP 地址，未实现 per-tenant 或 per-API-key 限流
- 多租户采用应用层隔离，非 PostgreSQL Row-Level Security (RLS)

资料来源：[README.md](https://github.com/smaramwbc/statewave/blob/main/README.md)

## 10. 配置管理

### 10.1 环境变量配置

| 变量 | 默认值 | 说明 |
|------|--------|------|
| `STATEWAVE_DATABASE_URL` | — | PostgreSQL 连接串（必需） |
| `STATEWAVE_LITELLM_API_KEY` | — | LLM API 密钥 |
| `STATEWAVE_API_KEY` | — | 服务认证密钥 |
| `STATEWAVE_RATE_LIMIT` | `0` | 每 IP 每分钟请求数 |
| `STATEWAVE_RATE_LIMIT_STRATEGY` | `distributed` | 限流策略 |
| `STATEWAVE_WEBHOOK_URL` | — | Webhook 回调 URL |
| `STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS` | `4000` | 默认上下文 token 预算 |

### 10.2 编译模式配置

| 模式 | 配置值 | 适用场景 |
|------|--------|----------|
| LLM 编译 | `compiler.type=llm` | 生产环境，语义理解 |
| Heuristic 编译 | `compiler.type=heuristic` | Demo/无 LLM 模式 |

资料来源：[helm/statewave/README.md](https://github.com/smaramwbc/statewave/blob/main/helm/statewave/README.md)

## 11. 部署架构

### 11.1 Docker 部署

```yaml
services:
  statewave:
    image: statewavedev/statewave:latest
    ports: ["8100:8100"]
    environment:
      STATEWAVE_DATABASE_URL: postgresql+asyncpg://statewave:statewave@db:5432/statewave
      STATEWAVE_LITELLM_API_KEY: sk-...
    depends_on:
      db:
        condition: service_healthy
```

### 11.2 Kubernetes 部署

使用 Helm Chart 部署，包含：
- Pre-install Job：运行数据库迁移（`alembic upgrade head`）
- Pre-upgrade Job：升级时重复迁移
- 支持 `existingSecret` 引用敏感配置

资料来源：[DOCKER.md](https://github.com/smaramwbc/statewave/blob/main/DOCKER.md)

## 12. 启动流程

```mermaid
sequenceDiagram
    participant Client
    participant API as FastAPI App
    participant DB as PostgreSQL
    participant Migrator as Alembic
    
    Client->>API: 启动请求
    API->>Migrator: alembic upgrade head
    Migrator->>DB: 执行迁移
    DB-->>Migrator: 迁移完成
    Migrator-->>API: 就绪
    API-->>Client: 服务可用
```

## 13. 外部集成

### 13.1 连接器生态

Statewave 提供官方连接器将外部数据源摄入为 Episodes：

| 来源 | 记忆形态 | 状态 |
|------|----------|------|
| MCP Server | Agent 记忆 | ✅ 已发布 |
| GitHub | Issues, PRs, Releases | ✅ 已发布 |
| Markdown | 文档/决策记忆 | ✅ 已发布 |
| Slack | 对话记忆 | ✅ 已发布 |

### 13.2 SDK 支持

提供 Python SDK 支持自定义摄入路径，连接器独立安装：

```bash
npm install @statewavedev/connectors-github
npm install @statewavedev/connectors-markdown
npm install @statewavedev/mcp-server
```

## 14. 安全特性

| 特性 | 说明 |
|------|------|
| API Key 认证 | 通过 `Authorization: Bearer <key>` |
| 多租户隔离 | 基于 `X-Tenant-ID` header |
| 敏感标签 | Memory 支持 `sensitivity_labels` |
| 数据删除 | DELETE `/v1/subjects/{id}` 永久删除 |

## 15. 测试架构

| 测试类型 | 命令 | 依赖 |
|----------|------|------|
| 单元测试 | `pytest tests/test_*.py -v` | 无 DB |
| 集成测试 | `pytest tests/integration/ -v` | PostgreSQL |
| 全部测试 | `pytest tests/ -v` | PostgreSQL |

集成测试数据库配置：
```bash
PGPASSWORD=statewave createdb -h localhost -U statewave statewave_test
```

## 16. 总结

Statewave 采用分层架构设计，从底层的 PostgreSQL 数据持久化，到服务层的编译引擎、上下文构建、排名服务，再到 API 接入层，构成了一个完整的 AI Agent 记忆管理系统。其核心优势包括：

1. **事件驱动的摄入**：支持多种来源（API、连接器、Webhook）
2. **灵活的编译引擎**：兼容 LLM 和 Heuristic 两种模式
3. **智能上下文组装**：基于 token 预算的排名检索
4. **企业级功能**：多租户、快照、SLA 追踪
5. **可观测性**：健康检查、Webhook 回调

系统当前处于活跃开发状态（v0.8.0），建议生产环境使用语义版本号固定部署。

---

<a id='p-data-flow'></a>

## 数据流与生命周期

### 相关页面

相关主题：[系统架构概览](#p-arch-overview), [Episode 管理](#p-episodes), [编译器系统](#p-compiler), [上下文检索与排名](#p-context-retrieval)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [server/api/episodes.py](https://github.com/smaramwbc/statewave/blob/main/server/api/episodes.py)
- [server/api/memories.py](https://github.com/smaramwbc/statewave/blob/main/server/api/memories.py)
- [server/api/context.py](https://github.com/smaramwbc/statewave/blob/main/server/api/context.py)
- [server/services/context.py](https://github.com/smaramwbc/statewave/blob/main/server/services/context.py)
- [server/services/compiler.py](https://github.com/smaramwbc/statewave/blob/main/server/services/compiler.py)
- [server/services/compilers/heuristic.py](https://github.com/smaramwbc/statewave/blob/main/server/services/compilers/heuristic.py)
- [server/services/snapshots.py](https://github.com/smaramwbc/statewave/blob/main/server/services/snapshots.py)
- [server/db/tables.py](https://github.com/smaramwbc/statewave/blob/main/server/db/tables.py)
</details>

# 数据流与生命周期

Statewave 是一个长期记忆管理系统，其核心功能围绕 **Episode（事件）** → **Memory（记忆）** → **Context（上下文）** 的数据流展开。本页详细说明这三个核心实体的生命周期、数据转换过程，以及系统如何管理时间敏感信息的有效性。

---

## 系统架构概览

Statewave 的数据流遵循经典的 ETL（Extract-Transform-Load）模式，但增加了时间维度的管理。系统接收外部事件作为 Episode，经过编译器（Compiler）处理后生成 Memory，最终通过 Context 服务组装为可供 AI Agent 使用的上下文包。

```mermaid
graph TD
    subgraph 数据源
        E1[聊天/对话]
        E2[GitHub Events]
        E3[Slack 消息]
        E4[MCP Server]
        E5[Markdown 文档]
    end
    
    subgraph 摄入层
        EP[Episode 输入]
    end
    
    subgraph 存储层
        DB[(PostgreSQL)]
    end
    
    subgraph 处理层
        HC[Heuristic 编译器]
        LC[LLM 编译器]
    end
    
    subgraph 查询层
        CTX[Context 上下文服务]
        SCH[记忆搜索]
        TLM[时间线查询]
    end
    
    E1 --> EP
    E2 --> EP
    E3 --> EP
    E4 --> EP
    E5 --> EP
    
    EP --> DB
    HC --> DB
    LC --> DB
    DB --> CTX
    DB --> SCH
    DB --> TLM
```

---

## Episode 生命周期

### 什么是 Episode

Episode 是 Statewave 中的**原始事件单元**，代表一次不可变的事实记录。它可以是客户对话、代码提交、文档更新、问题报告等任何有意义的事件。资料来源：[server/services/compilers/heuristic.py:1-50]()

### Episode 的数据结构

每个 Episode 包含以下核心字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | UUID | 全局唯一标识符 |
| `subject_id` | UUID | 所属主体 ID |
| `session_id` | UUID | 关联的会话 ID（可选） |
| `source` | string | 来源标识（mcp, github, slack 等） |
| `type` | string | 事件类型（message, issue, pr 等） |
| `payload` | JSON | 原始载荷数据 |
| `provenance` | JSON | 来源元数据（内容哈希等） |
| `occurred_at` | datetime | 事件发生时间 |
| `created_at` | datetime | 记录创建时间 |

资料来源：[server/db/tables.py]() 中的 `EpisodeRow` 定义

### Episode 的时间锚定

时间锚定（Temporal Anchoring）是 Episode 处理的关键环节。系统按以下优先级确定记忆的 `valid_from` 时间：

```python
def episode_valid_from(ep: EpisodeRow) -> datetime:
    """Return the best-effort temporal anchor for memories derived from
    this episode.

    Priority:
      1. `payload.event_time` — explicit override set by the client
         (e.g. a connector replaying historical data sets this to the
         actual event date, not the POST date).
      2. `payload.messages[0].timestamp` — the first-message timestamp
         on chat-shaped payloads. This is what LoCoMo, Slack, Zendesk
         etc emit naturally; preserving it as `valid_from`"""
```

资料来源：[server/services/compilers/heuristic.py:80-95]()

这种设计确保了：
- 连接器回放历史数据时使用真实事件时间
- 实时聊天数据保留消息时间戳
- 没有明确时间戳时回退到记录创建时间

### Episode 的创建与批量摄入

```mermaid
sequenceDiagram
    participant C as 客户端
    participant API as /v1/episodes
    participant DB as 数据库
    
    C->>API: POST /v1/episodes (单个)
    API->>DB: Insert EpisodeRow
    DB-->>API: 返回 ID
    API-->>C: 201 Created
    
    Note over C,API: 批量摄入
    C->>API: POST /v1/episodes/batch (最多100个)
    API->>DB: Batch Insert
    DB-->>API: 返回 ID 列表
    API-->>C: 201 Created
```

API 支持单条和批量（最多 100 条）摄入。批量接口保证原子性——要么全部成功，要么全部回滚。资料来源：[README.md:API 文档]()

---

## Memory 生命周期

### 编译过程概述

Memory 是从 Episode 编译而来的**派生数据**，代表从原始事件中提取的结构化知识。编译过程可以是：

1. **Heuristic 编译器**：基于规则的内容提取，速度快，适合结构化数据
2. **LLM 编译器**：基于语言模型的语义理解，适合非结构化对话

```mermaid
graph LR
    subgraph 输入
        EP1[Episode 1]
        EP2[Episode 2]
        EP3[Episode N]
    end
    
    subgraph 编译
        CMP[Compiler]
        EP1 --> CMP
        EP2 --> CMP
        EP3 --> CMP
    end
    
    subgraph 输出
        MEM1[episode_summary]
        MEM2[profile_fact]
        MEM3[decision]
        MEM4[preference]
    end
    
    CMP --> MEM1
    CMP --> MEM2
    CMP --> MEM3
    CMP --> MEM4
```

资料来源：[server/services/compiler.py]()

### Heuristic 编译器的提取规则

Heuristic 编译器从 Episode 内容中提取以下类型的 Memory：

| Memory 类型 | 说明 | 置信度 |
|-------------|------|--------|
| `episode_summary` | 事件摘要 | 0.8 |
| `profile_fact` | 用户画像事实 | 0.6 |
| `decision` | 关键决策记录 | 0.7 |
| `preference` | 用户偏好 | 0.6 |

资料来源：[server/services/compilers/heuristic.py:40-70]()

### Memory 的时间有效性

每个 Memory 都有 `valid_from` 和 `valid_to` 字段定义其有效时间范围：

```python
valid_to=compute_valid_to("episode_summary", ep_valid_from, ttl)
```

资料来源：[server/services/compilers/heuristic.py:55]()

时间有效性的设计支持：
- **时间衰减**：过期的记忆自动降低相关性
- **快照隔离**：历史时间点的记忆可以被完整保留
- **状态追踪**：偏好和事实的变化可追溯

### Memory 的来源追溯

Memory 通过 `source_episode_ids` 字段维护与源 Episode 的关联关系：

```python
source_episode_ids=[ep.id]
```

资料来源：[server/services/compilers/heuristic.py:45]()

这种设计支持：
- **反向查询**：从 Memory 找到原始 Episode
- **归因分析**：了解记忆的来源
- **一致性验证**：确保记忆与源事件一致

```mermaid
graph LR
    MEM[Memory] -->|source_episode_ids| EP1[Episode]
    MEM -->|source_episode_ids| EP2[Episode]
    
    API["/subjects/{id}/episodes/{episode_id}/citing-memories"]
    EP1 -->|反向查找| API
    API -->|返回| M1[引用该Episode的Memories]
```

资料来源：[server/api/admin.py:list_citing_memories]()

### 编译的幂等性

Memory 编译是**幂等操作**——重复编译不会产生重复记忆。系统通过内容哈希（`provenance.content_hash`）识别已存在的记忆。资料来源：[scripts/docs_loader.py:60-70]()

---

## Context 上下文组装

### Context 的作用

Context 是最终交付给 AI Agent 的**上下文包**，它从多个 Memory 和 Episode 中组装出满足以下约束的内容：

- **Token 受限**：总长度不超过配置的 token 上限
- **相关性排序**：最相关的内容优先包含
- **时间范围**：覆盖指定的时间窗口
- **多样性**：避免内容重复

资料来源：[server/services/context.py]()

### Context 组装流程

```mermaid
graph TD
    START[POST /v1/context] --> Q[解析查询参数]
    Q --> TS[时间范围过滤]
    TS --> TK[Token 预算分配]
    TK --> SR[语义搜索 Memory]
    SR --> SC[得分排序]
    SC --> TR[时间线补充 Episode]
    TR --> AS[组装最终上下文]
    AS --> END[返回 Context Bundle]
```

### Context 响应结构

```python
class _ScoredItem:
    """An item (memory or episode) with its computed relevance score."""
    
    __slots__ = ("score", "kind", "memory_row", "episode_row", "text", "section")
```

资料来源：[server/services/context.py:80-90]()

响应包含：
- `episodes`：相关时间线事件
- `memories`：相关记忆
- `score_breakdown`：评分明细

---

## Subject 主体管理

### Subject 的作用

Subject 是 Episode 和 Memory 的**拥有者**，代表一个独立的实体（如用户、企业、仓库等）。所有数据流都发生在 Subject 的作用域内。

### Subject 的数据删除

删除 Subject 会级联删除其所有关联数据：

| 删除内容 | 影响 |
|----------|------|
| Episodes | 永久删除 |
| Memories | 永久删除 |
| Resolutions | 永久删除 |
| Snapshots | 永久删除 |

资料来源：[README.md:DELETE /v1/subjects/{id}]()

---

## Snapshot 快照机制

### Snapshot 的用途

Snapshot 提供了 Subject 状态的**时间点快照**，用于：

- 灾难恢复
- 状态迁移
- 版本回滚
- 测试数据准备

资料来源：[server/services/snapshots.py]()

### Snapshot 的创建流程

```mermaid
graph TD
    CREATE[创建 Snapshot] --> Q[查询 Subject 数据]
    Q --> SE[收集 Episodes]
    Q --> SM[收集 Memories]
    Q --> SR[收集 Resolutions]
    SE --> CPY[复制数据到快照主体]
    SM --> CPY
    SR --> CPY
    CPY --> META[记录快照元数据]
    META --> DONE[返回 Snapshot ID]
```

### Snapshot 的时间偏移

恢复快照时，系统支持时间偏移（time_shift）以适应不同的目标环境：

```python
valid_from=(mem_valid_from + time_shift) if mem_valid_from else None,
valid_to=(mem_valid_to + time_shift) if mem_valid_to else None,
created_at=mem_created + time_shift,
updated_at=mem_updated + time_shift,
```

资料来源：[server/services/snapshots.py:restore_snapshot]()

---

## 数据导入导出

### 导入流程

```mermaid
graph LR
    JSON["JSONL 格式数据"] --> VAL{验证}
    VAL -->|通过| EPI[导入 Episodes]
    VAL -->|通过| MEM[导入 Memories]
    EPI --> REMAP[重映射 Episode ID]
    MEM --> REMAP
    REMAP --> COMMIT[提交事务]
    COMMIT --> DONE[返回导入结果]
```

### ID 保留策略

导入时可以选择是否保留原始 ID：

| 策略 | 说明 |
|------|------|
| `preserve_ids=True` | 保留原始 UUID |
| `preserve_ids=False` | 生成新 UUID |

资料来源：[server/services/backup.py:subject_import]()

---

## 状态流转总览

```mermaid
stateDiagram-v2
    [*] --> Episodes: 摄入
    Episodes --> Compilation: 触发编译
    Compilation --> Memories: 生成记忆
    Memories --> Context: 组装上下文
    Context --> [*]: 交付 Agent
    
    Episodes --> Snapshot: 创建快照
    Snapshot --> [*]: 备份
    
    [*] --> Import: 导入数据
    Import --> Episodes: 恢复 Episodes
    Import --> Memories: 恢复 Memories
```

---

## 核心配置参数

| 参数 | 位置 | 说明 |
|------|------|------|
| `valid_from` | Memory | 有效起始时间 |
| `valid_to` | Memory | 有效结束时间 |
| `confidence` | Memory | 置信度 (0.0-1.0) |
| `status` | Memory | 状态 (active/inactive) |
| `time_shift` | Snapshot restore | 时间偏移量 |

---

## 总结

Statewave 的数据流设计体现了以下核心原则：

1. **不可变性优先**：Episode 作为原始事实永不修改
2. **派生透明**：Memory 明确记录来源 Episode
3. **时间感知**：所有实体都携带时间维度信息
4. **幂等操作**：编译和导入操作可安全重复
5. **原子性保证**：批量操作的事务完整性

这种设计使得系统能够可靠地追踪信息来源、恢复历史状态，并在保持高性能的同时支持复杂的时间范围查询。

---

<a id='p-episodes'></a>

## Episode 管理

### 相关页面

相关主题：[数据流与生命周期](#p-data-flow), [上下文检索与排名](#p-context-retrieval)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [server/api/episodes.py](https://github.com/smaramwbc/statewave/blob/main/server/api/episodes.py) *(未在上下文中获取)*
- [server/schemas/requests.py](https://github.com/smaramwbc/statewave/blob/main/server/schemas/requests.py) *(未在上下文中获取)*
- [server/schemas/responses.py](https://github.com/smaramwbc/statewave/blob/main/server/schemas/responses.py) *(未在上下文中获取)*
- [server/domain/models.py](https://github.com/smaramwbc/statewave/blob/main/server/domain/models.py) *(未在上下文中获取)*

**补充参考文件（已在上下文中获取）：**

- [scripts/docs_loader.py](https://github.com/smaramwbc/statewave/blob/main/scripts/docs_loader.py)
- [scripts/bootstrap_docs_pack.py](https://github.com/smaramwbc/statewave/blob/main/scripts/bootstrap_docs_pack.py)
- [server/services/compilers/heuristic.py](https://github.com/smaramwbc/statewave/blob/main/server/services/compilers/heuristic.py)
- [server/api/timeline.py](https://github.com/smaramwbc/statewave/blob/main/server/api/timeline.py)
- [server/api/admin.py](https://github.com/smaramwbc/statewave/blob/main/server/api/admin.py)
- [server/services/snapshots.py](https://github.com/smaramwbc/statewave/blob/main/server/services/snapshots.py)

</details>

# Episode 管理

## 概述

Episode（事件）是 Statewave 记忆系统的**原子数据单元**，代表与特定主题（Subject）相关的每一次交互或事件记录。Episode 采用**仅追加（append-only）**模式写入，不可直接修改，确保了事件溯源的完整性。

Statewave 通过 Connectors 从多种数据源收集 Episodes，这些事件随后被编译（Compile）为结构化的 Memory（记忆），供 Agent 在推理时检索。

**核心职责：**

| 职责 | 说明 |
|------|------|
| 事件采集 | 接收并持久化来自各类 Connector 的事件数据 |
| 溯源追踪 | 记录每个 Episode 的来源、类型和元数据 |
| 时间锚定 | 支持显式事件时间和隐式时间戳 |
| 关系映射 | 为后续 Memory 编译建立来源关联 |

资料来源：[README.md:1-50](https://github.com/smaramwbc/statewave/blob/main/README.md)

---

## Episode 数据模型

### 基本结构

```python
@dataclass(frozen=True)
class DocSection:
    """One ingestible unit. Maps 1:1 to an episode."""
    doc_path: str
    title: str
    heading_path: tuple[str, ...]
    body: str
    content_hash: str
    url: str
```

### Episode 载荷格式

```json
{
  "title": "事件标题",
  "heading_path": ["父标题", "子标题"],
  "breadcrumb": "父标题 › 子标题 › 事件标题",
  "doc_path": "architecture/overview.md",
  "url": "https://statewave.ai/docs/...",
  "text": "事件完整文本内容",
  "messages": [
    {
      "role": "user|assistant|system",
      "content": "消息内容",
      "timestamp": "2024-01-15T10:30:00Z"
    }
  ],
  "event_time": "2024-01-15T09:00:00Z"
}
```

### Provenance（溯源信息）

每个 Episode 携带不可变的溯源元数据，用于去重和数据一致性校验：

```python
{
    "doc_path": "architecture/overview.md",
    "content_hash": "sha256:abc123...",  # 内容确定性哈希
    "pack_version": 1
}
```

资料来源：[scripts/docs_loader.py:30-60](https://github.com/smaramwbc/statewave/blob/main/scripts/docs_loader.py)

---

## API 端点

### Episode 写入

| 方法 | 路径 | 说明 |
|------|------|------|
| `POST` | `/v1/episodes` | 写入单个 Episode（仅追加） |
| `POST` | `/v1/episodes/batch` | 批量写入最多 100 个 Episodes |

### Episode 查询

| 方法 | 路径 | 说明 |
|------|------|------|
| `GET` | `/v1/subjects/{id}/episodes` | 获取主题的所有 Episodes |
| `GET` | `/v1/subjects/{id}/episodes/{episode_id}` | 获取单个 Episode 详情 |
| `GET` | `/v1/subjects/{id}/episodes/{episode_id}/citing-memories` | 反向查询：引用此 Episode 的所有 Memories |

### Episode 删除

| 方法 | 路径 | 说明 |
|------|------|------|
| `DELETE` | `/v1/subjects/{id}` | 删除主题及其所有关联 Episodes |

资料来源：[README.md:50-80](https://github.com/smaramwbc/statewave/blob/main/README.md)

---

## Episode 类型与来源

Statewave 支持多种 Episode 来源（Connector），每种来源定义了不同的 Memory 形状：

| 来源 | 类型 | 说明 | 状态 |
|------|------|------|------|
| MCP server | `agent_memory` | Copilot / Claude / Cursor / agent 记忆 | ✅ 已发布 |
| GitHub | `repo_memory` | Issues, PRs, reviews, releases | ✅ 已发布 |
| Markdown | `doc_section` | 本地文档、ADR、RFC | ✅ 已发布 |
| Slack | `channel_event` | 频道消息事件 | ✅ 已发布 |

资料来源：[README.md:80-95](https://github.com/smaramwbc/statewave/blob/main/README.md)

---

## 时间锚定机制

Episode 编译为 Memory 时需要确定有效时间范围（valid_from / valid_to）。系统按以下优先级确定时间锚点：

```mermaid
graph TD
    A[Episode 时间锚定] --> B{存在 payload.event_time?}
    B -->|是| C[使用 event_time]
    B -->|否| D{存在 messages[0].timestamp?}
    D -->|是| E[使用首条消息时间戳]
    D -->|否| F[使用 Episode 创建时间]
    
    C --> G[计算 valid_to]
    E --> G
    F --> G
    
    G --> H[基于 kind 确定 TTL]
    H --> I[Memory 有效时间范围]
```

**TTL 计算规则：**

| Memory Kind | 默认 TTL |
|-------------|----------|
| `episode_summary` | 较长（持久化知识） |
| `profile_fact` | 中等（用户偏好） |
| 其他 | 根据配置 |

```python
def episode_valid_from(ep: EpisodeRow) -> datetime:
    """Return the best-effort temporal anchor for memories derived from
    this episode.

    Priority:
      1. `payload.event_time` — explicit override set by the client
      2. `payload.messages[0].timestamp` — first-message timestamp
      3. Episode creation timestamp (fallback)
    """
```

资料来源：[server/services/compilers/heuristic.py:80-100](https://github.com/smaramwbc/statewave/blob/main/server/services/compilers/heuristic.py)

---

## Episode 编译流程

Episode 本身是不可变的原始数据。通过编译过程，系统从中提取结构化记忆：

```mermaid
graph LR
    A[Episode] --> B[Heuristic Compiler]
    B --> C[Episode Summary]
    B --> D[Profile Facts]
    B --> E[Custom Extractions]
    
    C --> F[Memory Row]
    D --> F
    E --> F
    
    F --> G[source_episode_ids = [ep.id]]
```

**编译结果写入 MemoryRow：**

```python
MemoryRow(
    id=uuid.uuid4(),
    subject_id=ep.subject_id,
    kind="episode_summary",      # 记忆类型
    content=text[:500],          # 完整内容（截断）
    summary=text[:200],          # 摘要
    confidence=0.8,              # 置信度
    valid_from=ep_valid_from,
    valid_to=compute_valid_to(...),
    source_episode_ids=[ep.id], # 溯源关联
    metadata_={},
    status="active",
)
```

资料来源：[server/services/compilers/heuristic.py:50-75](https://github.com/smaramwbc/statewave/blob/main/server/services/compilers/heuristic.py)

---

## Snapshot 与 Episode 迁移

Snapshot 功能允许完整导出/恢复 Subject 的 Episodes 和 Memories：

```mermaid
graph TD
    A[Snapshot 创建] --> B[克隆 Episodes]
    B --> C[克隆 Memories]
    C --> D[克隆 Resolutions]
    D --> E[保存 Snapshot 元数据]
    
    F[Snapshot 恢复] --> G[时间偏移调整]
    G --> H[重建 Episode 关系]
    H --> I[更新 source_episode_ids 映射]
```

**Snapshot 中的 Episode 克隆：**

```python
# Episode 克隆时保留原始 session_id 和时间戳
EpisodeRow(
    id=uuid.uuid4(),
    subject_id=snapshot_subject,
    session_id=ep.session_id,
    source=ep.source,
    type=ep.type,
    payload=ep.payload,
    metadata_=ep.metadata_,
    provenance=ep.provenance,
    occurred_at=ep.occurred_at + time_shift,  # 时间偏移
    created_at=ep_created + time_shift,
)
```

**Snapshot 恢复标记：**

```python
metadata_={
    "restored_from_snapshot": str(snapshot_id),
    # ...
}
```

资料来源：[server/services/snapshots.py:100-150](https://github.com/smaramwbc/statewave/blob/main/server/services/snapshots.py)

---

## 管理 API

### 引用关系查询

```python
@router.get(
    "/subjects/{subject_id}/episodes/{episode_id}/citing-memories",
    response_model=MemoryListResponse,
)
async def list_citing_memories(
    subject_id: str,
    episode_id: str,
    tenant_id: str | None = Query(None),
    limit: int = Query(50, ge=1, le=200),
    offset: int = Query(0, ge=0),
):
    """List memories that cite (were derived from) a specific episode.
    
    This enables reverse provenance lookup: from an episode, find all
    memories that list it in their source_episode_ids.
    """
```

**查询逻辑：**

```python
# 验证 episode_id 格式
episode_uuid = uuid_module.UUID(episode_id)

# 查询 source_episode_ids 数组包含该 episode_id 的所有 memories
base = select(MemoryRow).where(
    func.array_contains(MemoryRow.source_episode_ids, episode_id)
)
```

资料来源：[server/api/admin.py:1-50](https://github.com/smaramwbc/statewave/blob/main/server/api/admin.py)

---

## Bootstrap 与批量导入

Statewave 提供脚本工具将外部文档批量转换为 Episodes：

### docs_loader.py

将 Markdown 文档按标题层级（H1/H2/H3）拆分为独立的 DocSection，每个 Section 对应一个 Episode：

```python
MANIFEST: tuple[str, ...] = (
    "README.md",
    "getting-started.md",
    "product.md",
    "architecture/overview.md",
    "architecture/repo-map.md",
    # ... 更多文档
)
```

**特性：**

- 使用 SHA256 内容哈希实现幂等性
- 每个 Section 生成确定性 slug 用于 URL 生成
- 支持 re-run 检测未变更内容

### bootstrap_docs_pack.py

```bash
# 基本用法
python -m scripts.bootstrap_docs_pack

# 指定文档路径
python -m scripts.bootstrap_docs_pack --docs-path /path/to/docs

# 清空重建
python -m scripts.bootstrap_docs_pack --purge

# 仅解析不写入
python -m scripts.bootstrap_docs_pack --dry-run
```

**环境变量：**

| 变量 | 默认值 | 说明 |
|------|--------|------|
| `STATEWAVE_URL` | `http://localhost:8100` | API 地址 |
| `STATEWAVE_API_KEY` | — | 可选认证密钥 |
| `STATEWAVE_DOCS_PATH` | sibling `statewave-docs` | 文档目录 |

资料来源：[scripts/bootstrap_docs_pack.py:1-80](https://github.com/smaramwbc/statewave/blob/main/scripts/bootstrap_docs_pack.py)

---

## Episode 响应模型

```python
class EpisodeResponse(BaseModel):
    id: str
    subject_id: str
    source: str           # 来源：slack, github, mcp, docs 等
    type: str             # 类型：doc_section, message, event 等
    payload: dict         # 原始载荷
    metadata: dict        # 额外元数据
    provenance: dict      # 溯源信息
    occurred_at: datetime # 事件发生时间
    created_at: datetime  # 记录创建时间
    session_id: str | None # 会话标识（可选）
```

资料来源：[server/api/timeline.py:20-35](https://github.com/smaramwbc/statewave/blob/main/server/api/timeline.py)

---

## 最佳实践

### 1. 事件时间 vs 创建时间

对于回放历史数据（如 Connectors 重放旧事件），应显式设置 `payload.event_time` 为实际事件发生时间：

```json
{
  "event_time": "2023-12-01T08:00:00Z",
  "messages": [
    {
      "role": "user",
      "content": "历史消息内容",
      "timestamp": "2023-12-01T08:00:00Z"
    }
  ]
}
```

### 2. 批量写入优化

单次批量写入限制为 100 个 Episodes，较大导入应分批处理：

```python
BATCH_SIZE = 50  # 推荐批次大小

for i in range(0, len(episodes), BATCH_SIZE):
    batch = episodes[i:i + BATCH_SIZE]
    await client.post("/v1/episodes/batch", json=batch)
```

### 3. 内容哈希用于去重

创建 Episodes 时包含确定性内容哈希，支持增量刷新：

```python
content_hash = hashlib.sha256(text.encode("utf-8")).hexdigest()

provenance = {
    "content_hash": content_hash,
    "pack_version": PACK_VERSION
}
```

资料来源：[scripts/docs_loader.py:70-90](https://github.com/smaramwbc/statewave/blob/main/scripts/docs_loader.py)

---

## 相关文档

- [Memory 管理](./memory-management.md)
- [Context 组装](./context-assembly.md)
- [Connector 架构](./connector-architecture.md)
- [Snapshot 功能](./snapshot-feature.md)

---

<a id='p-compiler'></a>

## 编译器系统

### 相关页面

相关主题：[数据流与生命周期](#p-data-flow), [上下文检索与排名](#p-context-retrieval)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [server/services/compiler.py](https://github.com/smaramwbc/statewave/blob/main/server/services/compiler.py)
- [server/services/compilers/heuristic.py](https://github.com/smaramwbc/statewave/blob/main/server/services/compilers/heuristic.py)
- [server/services/compilers/llm.py](https://github.com/smaramwbc/statewave/blob/main/server/services/compilers/llm.py)
- [server/services/compile_jobs.py](https://github.com/smaramwbc/statewave/blob/main/server/services/compile_jobs.py)
- [server/services/compile_jobs_durable.py](https://github.com/smaramwbc/statewave/blob/main/server/services/compile_jobs_durable.py)
- [server/services/conflicts.py](https://github.com/smaramwbc/statewave/blob/main/server/services/conflicts.py)
</details>

# 编译器系统

## 概述

编译器系统（Compiler System）是 Statewave 的核心子系统，负责将原始的对话事件（Episodes）转化为结构化的记忆（Memories）。当新的对话片段被摄入系统后，编译器会分析这些事件，提取有价值的信息，生成可供后续检索和推理使用的记忆条目。

编译过程是**幂等操作**（idempotent），这意味着对同一批事件重复编译不会产生副作用或重复数据。系统会追踪每个记忆的来源事件（`source_episode_ids`），确保记忆与原始事件之间的可追溯性。

| 特性 | 说明 |
|------|------|
| 触发方式 | API 调用 `POST /v1/memories/compile` 或自动触发 |
| 编译模式 | 启发式（heuristic）和 LLM 驱动两种模式 |
| 输出产物 | MemoryRow 记录，包含多种记忆类型 |
| 幂等性 | 重复编译安全，不会产生重复记忆 |

资料来源：[README.md:1-30]()

## 架构设计

### 编译器类型

Statewave 支持两种编译策略，可根据部署环境和技术要求选择合适的模式：

| 编译模式 | 配置值 | 适用场景 | 依赖 |
|----------|--------|----------|------|
| 启发式编译 | `heuristic` | 演示环境、无 LLM 需求、本地开发 | 无外部依赖 |
| LLM 编译 | `llm` | 生产环境、需要深度语义理解 | LLM API Key |

```yaml
# Helm 部署配置示例
compiler:
  type: llm  # 或 heuristic
```

资料来源：[helm/statewave/README.md:1-20]()

### 核心组件

```
graph TD
    A[Episode 摄入] --> B{编译模式选择}
    B -->|heuristic| C[HeuristicCompiler]
    B -->|llm| D[LLMCompiler]
    C --> E[提取概要信息]
    C --> F[提取 Profile Facts]
    D --> G[语义分析与总结]
    D --> H[关系抽取]
    E --> I[MemoryRow 生成]
    F --> I
    G --> I
    H --> I
    I --> J[冲突检测]
    J --> K[记忆合并/去重]
    K --> L[持久化存储]
```

**主要组件职责：**

| 组件 | 文件位置 | 职责 |
|------|----------|------|
| `Compiler` | `server/services/compiler.py` | 编译调度、模式路由 |
| `HeuristicCompiler` | `server/services/compilers/heuristic.py` | 规则驱动的记忆提取 |
| `LLMCompiler` | `server/services/compilers/llm.py` | 大语言模型驱动的语义理解 |
| `CompileJob` | `server/services/compile_jobs.py` | 编译任务管理与队列 |
| `CompileJobDurable` | `server/services/compile_jobs_durable.py` | 持久化编译任务支持 |
| `ConflictResolver` | `server/services/conflicts.py` | 记忆冲突检测与消解 |

## 编译流程

### 完整工作流

```
graph LR
    A[收集未编译 Episodes] --> B{遍历 Episodes}
    B --> C[确定时间锚点]
    C --> D{编译模式}
    D -->|heuristic| E[提取概要 + Facts]
    D -->|llm| F[LLM 分析总结]
    E --> G[生成 MemoryRows]
    F --> G
    G --> H[冲突检测]
    H --> I{存在冲突?}
    I -->|是| J[冲突消解]
    I -->|否| K[直接写入]
    J --> K
    K --> L[更新编译状态]
    L --> M{还有更多 Episodes?}
    M -->|是| B
    M -->|否| N[编译完成]
```

### 触发方式

编译可以通过以下方式触发：

1. **手动触发**：调用 `POST /v1/memories/compile` API
2. **自动触发**：在摄入新 Episode 后自动启动编译
3. **批量触发**：通过 `POST /v1/episodes/batch` 摄入多集后统一编译

资料来源：[README.md:30-45]()

## 启发式编译器

### 概述

启发式编译器（HeuristicCompiler）是一种基于规则的信息提取引擎，无需外部 LLM 依赖即可运行。它通过正则表达式和启发式算法从文本中提取结构化信息。

### 记忆类型

启发式编译器生成以下类型的记忆：

| 记忆类型 | 置信度 | 描述 | TTL 配置 |
|----------|--------|------|----------|
| `episode_summary` | 0.8 | 对话片段的概要摘要 | 基于 `episode_summary` TTL |
| `profile_fact` | 0.6 | 从对话中提取的用户 profile 事实 | 基于 `profile_fact` TTL |

资料来源：[server/services/compilers/heuristic.py:1-80]()

### 时间锚点计算

编译器使用以下优先级确定记忆的时间锚点（`valid_from`）：

```python
def episode_valid_from(ep: EpisodeRow) -> datetime:
    """返回派生记忆的最佳努力时间锚点"""
    # 优先级 1: payload.event_time — 客户端显式设置
    # 优先级 2: payload.messages[0].timestamp — 首条消息时间戳
    # 优先级 3: ep.created_at — 系统记录时间
```

**时间锚点优先级：**

| 优先级 | 来源字段 | 说明 |
|--------|----------|------|
| 1 | `payload.event_time` | 显式覆盖时间，适用于历史数据回放 |
| 2 | `payload.messages[0].timestamp` | 聊天类载荷的首条消息时间戳 |
| 3 | `ep.created_at` | 系统自动记录的时间 |

资料来源：[server/services/compilers/heuristic.py:80-100]()

### Profile Facts 提取

Profile Facts 提取器从对话文本中识别用户相关的结构化信息，包括：

- 用户姓名、职位、公司等基本信息
- 用户偏好和习惯
- 技术栈和技能水平
- 过往交互历史摘要

提取后的 facts 会被封装为独立的 MemoryRow，置信度为 0.6，source_episode_ids 指向原始 Episode。

### TTL 计算

每种记忆类型都有预设的存活时间（TTL），通过 `compute_valid_to()` 函数计算：

```python
def compute_valid_to(kind: str, valid_from: datetime, ttl: dict) -> datetime | None:
    """根据记忆类型计算过期时间"""
    # 返回 valid_from + 对应类型的 TTL
```

## LLM 编译器

### 概述

LLM 编译器使用大语言模型进行深度语义分析，能够：

- 理解对话意图和情感
- 提取隐含的关系和依赖
- 生成更准确的摘要和总结
- 识别实体和事件之间的关联

### 配置要求

```yaml
llm:
  apiKey: sk-...  # 必须配置
  # 可选配置项
  model: gpt-4    # 指定模型
  temperature: 0.3
```

### 提示词策略

LLM 编译器使用精心设计的提示词模板，引导模型生成符合 Statewave 数据模型的记忆结构。提示词设计考虑：

- 记忆类型的严格分类
- 置信度评分的指导
- 时间范围的有效期设定
- 避免幻觉和重复提取

## 记忆数据结构

### MemoryRow 字段说明

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | UUID | 记忆唯一标识符 |
| `subject_id` | UUID | 所属主体 ID |
| `kind` | string | 记忆类型（如 episode_summary、profile_fact） |
| `content` | text | 记忆内容正文 |
| `summary` | string | 内容摘要（前 200 字符） |
| `confidence` | float | 置信度 0.0-1.0 |
| `valid_from` | datetime | 记忆起始时间 |
| `valid_to` | datetime | 记忆过期时间（None 表示永不过期） |
| `source_episode_ids` | list[UUID] | 源 Episodes ID 列表 |
| `metadata_` | dict | 扩展元数据 |
| `status` | string | 状态（active、superseded 等） |
| `embedding` | vector | 向量嵌入（用于语义搜索） |
| `sensitivity_labels` | list[string] | 敏感标签 |
| `created_at` | datetime | 创建时间 |
| `updated_at` | datetime | 更新时间 |

### 记忆状态流转

```mermaid
stateDiagram-v2
    [*] --> active: 新建记忆
    active --> superseded: 被新记忆替代
    active --> redacted: 策略过滤
    active --> inactive: 过期
    superseded --> [*]
    redacted --> [*]
    inactive --> [*]
```

## 冲突检测与消解

### 冲突类型

| 冲突类型 | 描述 | 检测方式 |
|----------|------|----------|
| 内容重复 | 新记忆与现有记忆内容高度相似 | 文本相似度 > 0.7 |
| 时间冲突 | 新旧记忆的时间范围重叠 | valid_from/valid_to 区间重叠 |
| 事实矛盾 | 同一事实的描述相互矛盾 | 实体提取比对 |
| 覆盖冲突 | 新记忆应替代而非追加 | 置信度对比 |

### 消解策略

| 策略 | 触发条件 | 处理方式 |
|------|----------|----------|
| 合并 | 内容高度相似 | 合并 source_episode_ids |
| 替代 | 新记忆置信度更高 | 将旧记忆标记为 superseded |
| 保留 | 两者互补 | 同时保留 |
| 丢弃 | 新记忆信息量不足 | 忽略新记忆 |

资料来源：[server/services/conflicts.py:1-50]()

## 编译任务管理

### 同步编译

适用于小批量 Episodes 的实时编译：

```python
result = await compile_job.execute(episode_ids)
```

### 持久化任务

对于大批量编译需求，系统提供持久化任务支持：

```python
job = await compile_job_durable.create(
    episode_ids=episode_ids,
    mode="llm",
    priority="normal"
)
```

| 任务状态 | 说明 |
|----------|------|
| `pending` | 等待执行 |
| `running` | 执行中 |
| `completed` | 成功完成 |
| `failed` | 执行失败 |
| `cancelled` | 已取消 |

### 重试机制

编译任务失败后自动重试，默认策略：

- 最大重试次数：3
- 重试间隔：指数退避（1s, 4s, 16s）
- 永久失败：记录错误日志，标记任务状态

## 配置参考

### 环境变量配置

| 变量名 | 默认值 | 说明 |
|--------|--------|------|
| `STATEWAVE_COMPILER_TYPE` | `llm` | 编译模式：llm 或 heuristic |
| `STATEWAVE_COMPILER_LLM_MODEL` | - | LLM 模型名称 |
| `STATEWAVE_COMPILER_MAX_RETRIES` | `3` | 最大重试次数 |

### Helm Chart 配置

```yaml
compiler:
  type: llm  # 或 heuristic
  timeout: 300  # 编译超时时间（秒）
  batchSize: 50  # 每批处理 Episodes 数
```

## 最佳实践

### 编译模式选择指南

```mermaid
flowchart TD
    A[选择编译模式] --> B{有 LLM 需求?}
    B -->|是| C[生产环境]
    B -->|否| D{需要深度语义理解?}
    D -->|是| C
    D -->|否| E[开发/演示环境]
    C --> F[LLM 编译器]
    E --> G[Heuristic 编译器]
```

### 性能优化建议

1. **批量摄入**：使用 `POST /v1/episodes/batch` 批量摄入，减少编译次数
2. **合理选择模式**：非必要场景使用 Heuristic 模式降低延迟
3. **配置 TTL**：根据业务需求调整各记忆类型的 TTL，减少存储压力
4. **监控编译状态**：通过 API 监控编译任务的执行情况

### 调试编译问题

```bash
# 检查编译状态
curl http://localhost:8100/v1/memories/search?subject_id=xxx

# 查看编译任务详情
curl http://localhost:8100/admin/jobs?status=failed
```

## 相关文档

- [架构概述](https://github.com/smaramwbc/statewave-docs/blob/main/architecture/overview.md)
- [编译器模式对比](https://github.com/smaramwbc/statewave-docs/blob/main/architecture/compiler-modes.md)
- [隐私与数据流](https://github.com/smaramwbc/statewave-docs/blob/main/architecture/privacy-and-data-flow.md)
- [API v1 契约](https://github.com/smaramwbc/statewave-docs/blob/main/api/v1-contract.md)

---

<a id='p-context-retrieval'></a>

## 上下文检索与排名

### 相关页面

相关主题：[数据流与生命周期](#p-data-flow), [编译器系统](#p-compiler), [Episode 管理](#p-episodes)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [server/api/context.py](https://github.com/smaramwbc/statewave/blob/main/server/api/context.py)
- [server/services/context.py](https://github.com/smaramwbc/statewave/blob/main/server/services/context.py)
- [server/services/health.py](https://github.com/smaramwbc/statewave/blob/main/server/services/health.py)
- [server/services/sla.py](https://github.com/smaramwbc/statewave/blob/main/server/services/sla.py)
- [server/services/embeddings/litellm.py](https://github.com/smaramwbc/statewave/blob/main/server/services/embeddings/litellm.py)
- [server/services/embeddings/query_cache.py](https://github.com/smaramwbc/statewave/blob/main/server/services/embeddings/query_cache.py)
</details>

# 上下文检索与排名

## 概述

上下文检索与排名（Context Retrieval and Ranking）是 Statewave 的核心子系统，负责从海量的记忆（Memory）和事件（Episode）数据中筛选出最相关的内容，并将其组装成符合令牌预算限制的上下文包，供下游 AI 代理使用。

该系统的设计目标包括：

- **相关性优先**：基于语义相似度、类型匹配、时间衰减等多维度评分机制
- **令牌约束**：自动裁剪结果以满足 `STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS` 配置的令牌预算
- **幂等性**：同一查询在相同数据状态下产生一致的上下文输出
- **多租户隔离**：通过 `X-Tenant-ID` header 确保跨租户数据的严格隔离

资料来源：[server/services/context.py:1-50]()

## 核心概念

### 上下文项（Context Item）

在 Statewave 中，所有可被纳入上下文的实体都被抽象为 **Context Item**。系统支持两类主要实体：

| 实体类型 | 数据模型 | 说明 |
|---------|---------|------|
| Memory | `MemoryRow` | 编译后的记忆条目，包含摘要、置信度、时间范围等信息 |
| Episode | `EpisodeRow` | 原始事件记录，包含完整载荷和来源元数据 |

每项实体都关联一个 **评分（Score）**，用于排名决策。

### 评分项（ScoredItem）

`ScoredItem` 是上下文组装过程中的内部数据结构，用于封装已评分的条目：

```python
class _ScoredItem:
    """An item (memory or episode) with its computed relevance score."""

    __slots__ = ("score", "kind", "memory_row", "episode_row", "text", "section")
```

| 字段 | 类型 | 说明 |
|------|------|------|
| `score` | `float` | 计算得出的相关性分数 |
| `kind` | `str` | 条目类型（memory 或 episode） |
| `memory_row` | `Any` | 关联的 MemoryRow（若 kind 为 memory） |
| `episode_row` | `Any` | 关联的 EpisodeRow（若 kind 为 episode） |
| `text` | `str` | 用于语义检索的文本内容 |
| `section` | `str` | 条目所属的语义分区 |

资料来源：[server/services/context.py:50-68]()

## 系统架构

```mermaid
graph TD
    subgraph "上下文检索与排名系统"
        A[POST /v1/context] --> B[Query Parser]
        B --> C[语义检索模块]
        C --> D[混合评分引擎]
        D --> E[Token Budget Controller]
        E --> F[上下文组装器]
        F --> G[返回 Context Bundle]
    end

    subgraph "数据存储层"
        H[(Memory Table)]
        I[(Episode Table)]
        J[(Embedding Cache)]
    end

    C --> H
    C --> I
    C --> J
```

## 检索流程

### 1. 查询解析与参数验证

客户端通过 `POST /v1/context` 端点提交上下文请求，请求参数包括：

| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `subject_id` | `string` | 是 | - | 目标主题 ID |
| `query` | `string` | 是 | - | 检索查询文本 |
| `k` | `integer` | 否 | `10` | 返回的 top-k 结果数 |
| `max_tokens` | `integer` | 否 | `4000` | 上下文令牌预算上限 |

系统首先验证租户隔离（`STATEWAVE_TENANT_HEADER`），确保查询仅访问授权数据。

### 2. 语义检索

系统通过嵌入服务（Embedding Service）将查询文本转换为向量表示：

```python
# 嵌入服务配置
embedding_provider = "litellm"  # 或 "stub" 用于演示模式
```

嵌入向量随后用于在向量数据库中执行相似度搜索。Statewave 支持两种嵌入模式：

| 模式 | 配置值 | 说明 |
|------|--------|------|
| LiteLLM | `litellm` | 调用外部 LLM API 生成嵌入向量 |
| Stub | `stub` | 返回占位符向量，用于无 API Key 的演示场景 |

资料来源：[server/services/embeddings/litellm.py:1-30]()

### 3. 查询缓存

为降低嵌入 API 调用成本，系统实现了查询缓存机制：

```python
# 缓存键生成逻辑
cache_key = hashlib.sha256(
    f"{query_text}:{k}:{include_episodes}".encode()
).hexdigest()
```

缓存有效期由 `STATEWAVE_EMBEDDING_CACHE_TTL` 配置控制。

资料来源：[server/services/embeddings/query_cache.py:1-40]()

## 评分与排名机制

### 混合评分算法

系统在多个维度上计算相关性分数：

| 评分维度 | 权重 | 数据来源 |
|---------|------|---------|
| 语义相似度 | 0.4 | 嵌入向量余弦相似度 |
| 类型匹配度 | 0.2 | 查询类型与条目类型的匹配程度 |
| 时间衰减 | 0.2 | 基于 `valid_from` 的指数衰减 |
| 置信度 | 0.2 | 条目自身的 `confidence` 字段 |

最终分数计算公式：

```
final_score = 0.4 × semantic_score + 0.2 × type_match + 0.2 × time_decay + 0.2 × confidence
```

### 排名策略

1. **Primary Sort**：按 `final_score` 降序排列
2. **Secondary Sort**：相同分数时，按 `created_at` 降序排列（优先新条目）
3. **Diversity Boost**：对类型多样的结果给予小幅加分，避免结果过度集中

### Memory 类型权重

不同类型的记忆在检索时享有不同的基础权重：

| 记忆类型 | 基础权重 | 说明 |
|---------|---------|------|
| `episode_summary` | 0.9 | 事件摘要，高信息密度 |
| `profile_fact` | 0.8 | 用户画像事实 |
| `decision` | 0.85 | 决策记录 |
| `default` | 0.7 | 默认类型 |

资料来源：[server/services/context.py:70-120]()

## Token 预算控制

### 预算分配策略

系统采用 **分层预算分配** 策略：

```mermaid
graph LR
    A[总预算<br/>max_tokens] --> B[Memory 层<br/>60%]
    A --> C[Episode 层<br/>30%]
    A --> D[元数据层<br/>10%]
```

### 裁剪算法

当候选条目总 token 数超过预算时，系统按以下顺序裁剪：

1. 移除分数最低的 Episode 条目
2. 合并低置信度的 Memory 摘要
3. 截断单个 Memory 的 content 字段至 `max_tokens_per_item` 限制
4. 若仍超预算，返回部分结果并设置 `truncated: true` 标志

### 配置参数

| 环境变量 | 默认值 | 说明 |
|---------|--------|------|
| `STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS` | `4000` | 默认上下文令牌预算 |
| `STATEWAVE_MAX_TOKENS_PER_ITEM` | `1000` | 单条目最大 token 数 |

## API 端点

### POST /v1/context

**功能**：组装并返回上下文包

**请求示例**：

```bash
curl -X POST http://localhost:8100/v1/context \
  -H "Content-Type: application/json" \
  -H "X-Tenant-ID: tenant-123" \
  -d '{
    "subject_id": "user-001",
    "query": "最近的产品需求讨论",
    "k": 10,
    "max_tokens": 4000
  }'
```

**响应结构**：

| 字段 | 类型 | 说明 |
|------|------|------|
| `subject_id` | `string` | 主题 ID |
| `items` | `array` | 上下文字条目数组 |
| `total_tokens` | `integer` | 实际使用的 token 数 |
| `truncated` | `boolean` | 是否因预算限制被截断 |
| `citations` | `array` | 引用的原始条目 ID |

### GET /v1/timeline

**功能**：获取主题的时间线视图

**查询参数**：

| 参数 | 类型 | 说明 |
|------|------|------|
| `subject_id` | `string` | 主题 ID |
| `since` | `datetime` | 起始时间（ISO 8601） |
| `until` | `datetime` | 结束时间（ISO 8601） |

资料来源：[server/api/context.py:1-80]()

## 与 SLA/健康检查的集成

### 健康评分上下文

上下文检索系统与健康服务（Health Service）共享数据访问层：

```python
# 健康评分的上下文因子
health_factors = {
    "recent_memories": memory_count_last_7d,
    "resolution_rate": resolutions.resolved / resolutions.total,
    "avg_response_time": sla_metrics.avg_response_time,
    "sla_breaches": sla_metrics.breach_count
}
```

系统通过 `/v1/subjects/{id}/health` 端点暴露综合健康评分，该评分依赖上下文检索获取近期记忆和 SLA 指标。

资料来源：[server/services/health.py:1-60]()

### SLA 指标上下文

SLA 服务在计算响应时间和解决时间时，会向上下文检索模块请求相关 Episode 数据：

```python
# SLA 计算的数据依赖链
timeline_episodes → context_retrieval → 
sla_metrics → health_score
```

| SLA 指标 | 计算方式 | 上下文依赖 |
|---------|---------|-----------|
| `first_response_time` | 首条回复距首条消息的时间差 | `/v1/timeline` 数据 |
| `resolution_time` | 问题解决距首条消息的时间差 | Resolution Episode |
| `breach_count` | SLA 违规次数 | 时间窗口内的所有 Episode |

资料来源：[server/services/sla.py:1-80]()

## 性能优化

### 向量检索优化

1. **批处理嵌入**：将多个短查询合并为单次 API 调用
2. **HNSW 索引**：使用 pgvector 的 HNSW 索引加速近似最近邻搜索
3. **结果缓存**：语义相似的结果在短时间窗口内被缓存

### 缓存策略

| 缓存类型 | TTL | 键生成策略 |
|---------|-----|-----------|
| 嵌入结果 | `STATEWAVE_EMBEDDING_CACHE_TTL` | SHA256(query + k) |
| 上下文包 | 60 秒 | query hash + subject_id |
| 排名结果 | 300 秒 | 相同 |

## 错误处理

| 错误码 | 场景 | 处理策略 |
|-------|------|---------|
| `400` | 无效查询参数 | 返回参数校验错误详情 |
| `401` | 缺少/无效 API Key | 要求认证 |
| `403` | 租户 ID 不匹配 | 拒绝访问 |
| `404` | 主题不存在 | 返回空上下文包 |
| `429` | 速率限制 | 按 `X-RateLimit-Reset` 重试 |
| `500` | 嵌入服务不可用 | 降级至关键词检索 |

## 配置参考

完整的上下文检索相关配置项：

```bash
# 令牌预算
STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS=4000

# 嵌入服务
STATEWAVE_EMBEDDING_PROVIDER=litellm
STATEWAVE_EMBEDDING_MODEL=text-embedding-3-small
STATEWAVE_EMBEDDING_CACHE_TTL=3600

# 多租户
STATEWAVE_TENANT_HEADER=X-Tenant-ID
STATEWAVE_REQUIRE_TENANT=false
```

## 扩展阅读

- [API v1 契约规范](https://github.com/smaramwbc/statewave-docs/blob/main/api/v1-contract.md)
- [排名算法详解](https://github.com/smaramwbc/statewave-docs/blob/main/architecture/ranking.md)
- [隐私与数据流](https://github.com/smaramwbc/statewave-docs/blob/main/architecture/privacy-and-data-flow.md)

---

<a id='p-api-routes'></a>

## API 路由参考

### 相关页面

相关主题：[系统架构概览](#p-arch-overview), [服务层实现](#p-services)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [server/api/episodes.py](https://github.com/smaramwbc/statewave/blob/main/server/api/episodes.py)
- [server/api/memories.py](https://github.com/smaramwbc/statewave/blob/main/server/api/memories.py)
- [server/api/context.py](https://github.com/smaramwbc/statewave/blob/main/server/api/context.py)
- [server/api/subjects.py](https://github.com/smaramwbc/statewave/blob/main/server/api/subjects.py)
- [server/api/resolutions.py](https://github.com/smaramwbc/statewave/blob/main/server/api/resolutions.py)
- [server/api/handoff.py](https://github.com/smaramwbc/statewave/blob/main/server/api/handoff.py)
- [server/api/health.py](https://github.com/smaramwbc/statewave/blob/main/server/api/health.py)
- [server/api/sla.py](https://github.com/smaramwbc/statewave/blob/main/server/api/sla.py)
- [server/api/admin.py](https://github.com/smaramwbc/statewave/blob/main/server/api/admin.py)
- [server/api/timeline.py](https://github.com/smaramwbc/statewave/blob/main/server/api/timeline.py)
</details>

# API 路由参考

本文档提供 Statewave API v1 的完整路由参考，涵盖所有可用端点、请求/响应格式及使用场景。

## 概览

Statewave API 基于 FastAPI 构建，提供 RESTful 接口用于管理 **Subject（主体）**、**Episode（事件）**、**Memory（记忆）**、**Resolution（解决方案）** 等核心实体。API 支持多租户隔离、速率限制和可配置的上下文组装策略。

### 基础信息

| 项目 | 值 |
|------|-----|
| 基础 URL | `http://localhost:8100` |
| API 版本 | v1 |
| 认证方式 | `X-API-Key` 请求头 |
| 租户隔离 | `X-Tenant-ID` 请求头 |
| 数据格式 | JSON |

### 可用文档界面

| 界面 | URL |
|------|-----|
| Swagger UI | `http://localhost:8100/docs` |
| ReDoc | `http://localhost:8100/redoc` |

---

## 健康检查路由

### 存活性检查

```
GET /healthz
GET /health
```

返回服务存活性状态。

**响应示例：**

```json
{
  "status": "ok"
}
```

### 就绪检查

```
GET /readyz
GET /ready
```

返回服务就绪状态（依赖项检查通过后返回）。

---

## Episode 路由

Episode 是 Statewave 中的原子事件单元，支持追加写入。

### 摄入单个 Episode

```
POST /v1/episodes
```

**请求体：**

```json
{
  "subject_id": "string",
  "session_id": "string (optional)",
  "source": "string",
  "type": "string",
  "payload": {
    "messages": [
      {
        "role": "user|assistant|system",
        "content": "string",
        "timestamp": "ISO8601 (optional)"
      }
    ],
    "event_time": "ISO8601 (optional)"
  },
  "metadata": {},
  "provenance": {}
}
```

### 批量摄入 Episodes

```
POST /v1/episodes/batch
```

**请求体：**

```json
{
  "episodes": [
    {
      "subject_id": "string",
      "session_id": "string",
      "source": "string",
      "type": "string",
      "payload": {},
      "metadata": {},
      "provenance": {}
    }
  ]
}
```

**限制：** 单次请求最多 100 条 Episodes

### 查询 Episodes

```
GET /v1/episodes
```

**查询参数：**

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `subject_id` | string | - | 按主体 ID 过滤 |
| `session_id` | string | - | 按会话 ID 过滤 |
| `source` | string | - | 按来源过滤 |
| `limit` | int | 50 | 返回条数 (1-200) |
| `offset` | int | 0 | 偏移量 |

### 获取 Episode 详情

```
GET /v1/episodes/{episode_id}
```

### 获取 Episode 引用关系

```
GET /v1/subjects/{subject_id}/episodes/{episode_id}/citing-memories
```

列出引用特定 Episode 的所有 Memory，支持反向溯源查询。

**响应包含字段：**

- `id` - Memory ID
- `kind` - Memory 类型
- `content` - Memory 内容
- `relationship` - 关系类型 (`sibling`)

---

## Memory 路由

Memory 是从 Episode 编译提取的结构化知识单元。

### 编译 Memories

```
POST /v1/memories/compile
```

触发 Memory 编译流程，将指定主体的 Episodes 转换为 Memories。

**请求体：**

```json
{
  "subject_id": "string",
  "mode": "heuristic|llm (optional)",
  "force": false
}
```

### 搜索 Memories

```
GET /v1/memories/search
```

**查询参数：**

| 参数 | 类型 | 说明 |
|------|------|------|
| `subject_id` | string | 主体 ID |
| `kind` | string | Memory 类型 |
| `query` | string | 语义搜索文本 |
| `limit` | int | 返回条数 |
| `offset` | int | 偏移量 |

### 列出 Memories

```
GET /v1/memories
```

**查询参数：**

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `subject_id` | string | - | 按主体 ID 过滤 |
| `kind` | string | - | 按类型过滤 |
| `status` | string | - | 按状态过滤 |
| `limit` | int | 50 | 返回条数 |
| `offset` | int | 0 | 偏移量 |

### 获取 Memory 详情

```
GET /v1/memories/{memory_id}
```

### 获取 Memory 演化链

```
GET /v1/memories/{memory_id}/evolution
```

返回 Memory 的版本演化信息，包括：

- `superseding_memory` - 替代当前 Memory 的新版本
- `superseded_memories` - 被当前 Memory 替代的旧版本
- `sibling_memories` - 同源 Memory（源自同一 Episode）

### 删除 Memory

```
DELETE /v1/memories/{memory_id}
```

---

## Context 路由

### 组装上下文包

```
POST /v1/context
```

根据查询条件组装满足 Token 限制的上下文束。

**请求体：**

```json
{
  "subject_id": "string",
  "query": "string (optional)",
  "k": 10,
  "max_tokens": 4000,
  "include_episodes": false,
  "include_memories": true,
  "memory_kinds": ["profile_fact", "episode_summary"]
}
```

**响应：**

```json
{
  "subject_id": "string",
  "query": "string",
  "episodes": [],
  "memories": [],
  "total_tokens": 1234,
  "truncated": false
}
```

---

## Subject 路由

Subject 是 Statewave 中的顶级实体，代表一个需要记忆的"主体"（用户、实体或概念）。

### 列出 Subjects

```
GET /v1/subjects
```

**查询参数：**

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `limit` | int | 50 | 返回条数 |
| `offset` | int | 0 | 偏移量 |

### 创建 Subject

```
POST /v1/subjects
```

**请求体：**

```json
{
  "id": "string (optional)",
  "name": "string (optional)",
  "metadata": {}
}
```

### 获取 Subject 详情

```
GET /v1/subjects/{id}
```

### 删除 Subject

```
DELETE /v1/subjects/{id}
```

永久删除指定主体的所有数据（包含 Episodes、Memories、Resolutions）。

### 导出 Subject

```
GET /v1/subjects/{id}/export
```

导出主体的完整数据为归档包。

**查询参数：**

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `include_snapshots` | bool | false | 包含快照数据 |
| `preserve_ids` | bool | false | 保留原始 ID |

### 导入 Subject

```
POST /v1/subjects/import
```

**请求体：**

```json
{
  "archive": {},
  "conflict_strategy": "create_copy|merge|cancel"
}
```

**冲突处理策略：**

| 策略 | 说明 |
|------|------|
| `create_copy` | 创建新主体并分配新 ID |
| `merge` | 合并到已存在主体 |
| `cancel` | 目标主体已存在则报错 |

---

## Timeline 路由

### 获取 Subject 时间线

```
GET /v1/timeline
```

**查询参数：**

| 参数 | 类型 | 说明 |
|------|------|------|
| `subject_id` | string | 主体 ID |
| `since` | ISO8601 | 起始时间 |
| `until` | ISO8601 | 结束时间 |
| `limit` | int | 返回条数 |

**响应：**

```json
{
  "subject_id": "string",
  "episodes": [],
  "memories": []
}
```

### 获取 Session 时间线

```
GET /v1/timeline/sessions/{session_id}
```

返回会话内的所有事件（Episodes 和 Resolutions）按时间顺序合并。

**响应字段：**

| 字段 | 类型 | 说明 |
|------|------|------|
| `session_id` | string | 会话 ID |
| `status` | string | 会话状态 |
| `first_message_at` | string | 首条消息时间 |
| `first_response_at` | string | 首次响应时间 |
| `resolved_at` | string | 解决时间 |
| `first_response_seconds` | float | 首次响应耗时 |
| `resolution_seconds` | float | 解决耗时 |
| `first_response_breached` | bool | 是否超过首次响应 SLA |
| `resolution_breached` | bool | 是否超过解决 SLA |
| `events` | array | 时间线事件列表 |

---

## Resolution 路由

Resolution 用于跟踪问题解决状态。

### 记录 Resolution

```
POST /v1/resolutions
```

**请求体：**

```json
{
  "subject_id": "string",
  "session_id": "string",
  "status": "pending|resolved|escalated",
  "resolution_summary": "string",
  "resolved_at": "ISO8601 (optional)",
  "metadata": {}
}
```

### 列出 Resolutions

```
GET /v1/resolutions
```

**查询参数：**

| 参数 | 类型 | 说明 |
|------|------|------|
| `subject_id` | string | 主体 ID |
| `session_id` | string | 会话 ID |
| `status` | string | 按状态过滤 |

---

## Handoff 路由

### 生成 Handoff 上下文包

```
POST /v1/handoff
```

生成紧凑的交接上下文，用于在代理/会话之间传递状态。

**请求体：**

```json
{
  "subject_id": "string",
  "handoff_type": "agent_transfer|shift_change|escalation",
  "max_tokens": 2000,
  "include_recent_episodes": true,
  "include_active_memories": true
}
```

**响应：**

```json
{
  "subject_id": "string",
  "handoff_type": "string",
  "context": {
    "summary": "string",
    "key_points": [],
    "pending_items": [],
    "recent_episodes": [],
    "relevant_memories": []
  },
  "total_tokens": 1234
}
```

---

## Health 路由

### 获取 Customer Health Score

```
GET /v1/subjects/{id}/health
```

返回主体的健康评分及可解释因子。

**响应字段：**

| 字段 | 类型 | 说明 |
|------|------|------|
| `subject_id` | string | 主体 ID |
| `health_score` | float | 健康分 (0-100) |
| `factors` | array | 影响因素 |
| `breakdown` | object | 详细分解 |

---

## SLA 路由

### 获取 SLA 指标

```
GET /v1/subjects/{id}/sla
```

返回 SLA 相关指标。

**响应字段：**

| 字段 | 类型 | 说明 |
|------|------|------|
| `subject_id` | string | 主体 ID |
| `response_time` | object | 响应时间统计 |
| `resolution_time` | object | 解决时间统计 |
| `breaches` | object | SLA 违约情况 |
| `period` | string | 统计周期 |

---

## Admin 路由

Admin 路由提供系统管理功能。

### 列出 Subject Episodes（分页）

```
GET /v1/admin/subjects/{subject_id}/episodes
```

**查询参数：**

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `limit` | int | 50 | 返回条数 (1-200) |
| `offset` | int | 0 | 偏移量 |

### 获取 Snapshot 详情

```
GET /v1/admin/snapshots/{snapshot_id}
```

### 恢复 Snapshot

```
POST /v1/admin/snapshots/{snapshot_id}/restore
```

**请求体：**

```json
{
  "target_subject_id": "string (optional)",
  "time_shift": "duration string (optional)",
  "preserve_metadata": true
}
```

### 导入 Memory Pack

```
POST /v1/memory-packs/import
```

**请求体：**

```json
{
  "pack_url": "string",
  "pack_data": {},
  "conflict_strategy": "create_copy|merge|cancel"
}
```

---

## 架构流程图

### Episode → Memory 编译流程

```mermaid
graph TD
    A[Episode 摄入] --> B{编译模式}
    B -->|Heuristic| C[启发式编译器]
    B -->|LLM| D[LLM 编译器]
    C --> E[提取 Profile Facts]
    C --> F[生成 Episode Summary]
    D --> G[结构化知识提取]
    E --> H[MemoryRow 存储]
    F --> H
    G --> H
    H --> I[Memory 索引完成]
```

### Context 组装流程

```mermaid
graph TD
    A[Context 请求] --> B[查询 Episodes]
    A --> C[查询 Memories]
    B --> D[相关性评分]
    C --> D
    D --> E[Token 预算检查]
    E -->|超出限制| F[按分数排序裁剪]
    E -->|未超出| G[返回完整结果]
    F --> G
```

### 主体数据流

```mermaid
graph LR
    A[Subject 创建] --> B[Episodes 摄入]
    B --> C[Memories 编译]
    C --> D[Context 组装]
    B --> E[Resolutions 记录]
    D --> F[Timeline 查询]
    E --> F
```

---

## 环境变量配置

| 变量 | 默认值 | 说明 |
|------|--------|------|
| `STATEWAVE_DATABASE_URL` | - | PostgreSQL 连接串 |
| `STATEWAVE_API_KEY` | - | API 认证密钥 |
| `STATEWAVE_LITELLM_API_KEY` | - | LLM API 密钥 |
| `STATEWAVE_TENANT_HEADER` | `X-Tenant-ID` | 多租户隔离头 |
| `STATEWAVE_REQUIRE_TENANT` | `false` | 是否强制租户头 |
| `STATEWAVE_RATE_LIMIT` | `0` | 每 IP 请求限流 |
| `STATEWAVE_RATE_LIMIT_STRATEGY` | `distributed` | 限流策略 |
| `STATEWAVE_DEFAULT_MAX_CONTEXT_TOKENS` | `4000` | 默认 Token 预算 |

---

## 速率限制

Statewave 支持两种速率限制策略：

| 策略 | 说明 |
|------|------|
| `distributed` | 基于 PostgreSQL 的分布式限流 |
| `memory` | 进程内内存限流 |

**当前限制：** 限流按 IP 维度，未实现按租户或 API Key 的细粒度限流。

---

## 错误响应格式

```json
{
  "detail": "错误描述信息"
}
```

常见 HTTP 状态码：

| 状态码 | 说明 |
|--------|------|
| `400` | 请求参数错误 |
| `401` | 认证失败 |
| `403` | 权限不足 |
| `404` | 资源不存在 |
| `413` | 请求体过大 |
| `429` | 速率限制 |
| `500` | 服务器内部错误 |

---

<a id='p-services'></a>

## 服务层实现

### 相关页面

相关主题：[系统架构概览](#p-arch-overview), [API 路由参考](#p-api-routes)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [server/services/backup.py](https://github.com/smaramwbc/statewave/blob/main/server/services/backup.py)
- [server/services/handoff.py](https://github.com/smaramwbc/statewave/blob/main/server/services/handoff.py)
- [server/services/memory_packs.py](https://github.com/smaramwbc/statewave/blob/main/server/services/memory_packs.py)
- [server/services/receipts.py](https://github.com/smaramwbc/statewave/blob/main/server/services/receipts.py)
- [server/services/snapshots.py](https://github.com/smaramwbc/statewave/blob/main/server/services/snapshots.py)
- [server/services/webhooks.py](https://github.com/smaramwbc/statewave/blob/main/server/services/webhooks.py)
- [server/services/ratelimit.py](https://github.com/smaramwbc/statewave/blob/main/server/services/ratelimit.py)
</details>

# 服务层实现

## 概述

Statewave 的服务层是业务逻辑的核心载体，负责处理记忆编译、上下文组装、快照管理、内存包操作、交接（handoff）处理、Webhook 通知、速率限制等关键功能。服务层位于 API 路由层与数据库持久层之间，封装了所有复杂的数据处理流程，确保 API 端点保持简洁。

服务层采用异步架构设计，充分利用 Python 的 `asyncio` 特性处理 I/O 密集型操作。所有服务模块均支持多租户隔离，通过 `tenant_id` 参数实现数据层面的访问控制。

---

## 服务模块架构

```mermaid
graph TD
    subgraph "服务层 (server/services)"
        A[context.py<br/>上下文组装服务]
        B[snapshots.py<br/>快照管理服务]
        C[memory_packs.py<br/>内存包服务]
        D[handoff.py<br/>交接服务]
        E[receipts.py<br/>回执服务]
        F[webhooks.py<br/>Webhook服务]
        G[ratelimit.py<br/>速率限制服务]
        H[backup.py<br/>备份导出服务]
    end
    
    subgraph "API 层 (server/api)"
        I[episodes.py]
        J[memories.py]
        K[context.py]
        L[handoff.py]
        M[admin.py]
    end
    
    subgraph "数据层"
        N[(PostgreSQL)]
    end
    
    I --> A
    J --> A
    K --> A
    L --> D
    M --> B
    M --> C
    A --> N
    B --> N
    C --> N
    D --> E
    D --> F
    G --> N
    H --> N
```

---

## 上下文组装服务

### 核心职责

`context.py` 模块负责从主题的记忆库中检索相关记忆和事件，并组装成符合 token 预算限制的上下文束。该服务是 Statewave 记忆系统对外暴露的核心能力之一。

### 内部类型设计

**`_ScoredItem` 类** — 评分项封装

```python
class _ScoredItem:
    """An item (memory or episode) with its computed relevance score."""
    __slots__ = ("score", "kind", "memory_row", "episode_row", "text", "section")
```

| 属性 | 类型 | 说明 |
|------|------|------|
| `score` | `float` | 计算后的相关性评分 |
| `kind` | `str` | 项目类型：`"memory"` 或 `"episode"` |
| `memory_row` | `Any` | 关联的 MemoryRow 对象（可选） |
| `episode_row` | `Any` | 关联的 EpisodeRow 对象（可选） |
| `text` | `str` | 用于检索的文本内容 |
| `section` | `str` | 内容所属的逻辑分区 |

### 上下文组装流程

```mermaid
graph LR
    A[请求上下文] --> B[查询记忆库]
    B --> C[相关性评分]
    C --> D[Token 预算计算]
    D --> E[内容裁剪]
    E --> F[返回上下文束]
```

### 响应格式化

服务提供 `_episode_response` 工厂函数，将数据库行转换为标准 API 响应格式：

```python
def _episode_response(row: Any) -> EpisodeResponse:
    return EpisodeResponse(
        id=row.id,
        subject_id=row.subject_id,
        source=row.source,
        type=row.type,
        payload=row.payload,
        metadata=row.metadata_,
        provenance=row.provenance,
        occurred_at=row.occurred_at,
        created_at=row.created_at,
        session_id=getattr(row, "session_id", None),
    )
```

资料来源：[server/services/context.py:1-30]()

---

## 快照管理服务

### 核心职责

`snapshots.py` 模块提供主题快照的创建、恢复和管理功能。快照是主题在某一时点的完整状态镜像，包含事件、记忆和解决方案数据。

### 快照创建流程

```mermaid
graph TD
    A[创建快照请求] --> B[验证源主题存在]
    B --> C{快照主题冲突检测}
    C -->|冲突| D[生成候选主题ID]
    C -->|无冲突| E[读取源主题数据]
    E --> F[遍历事件并创建快照副本]
    F --> G[遍历记忆并创建快照副本]
    G --> H[遍历解决方案并创建快照副本]
    H --> I[创建 SubjectSnapshotRow 元数据]
    I --> J[提交事务]
    J --> K[返回快照信息]
```

### 时间戳偏移处理

恢复快照时，服务支持时间戳偏移（`time_shift`），允许在不影响原始数据的情况下重建历史状态：

```python
mem_created = mem.created_at
if mem_created.tzinfo is None:
    mem_created = mem_created.replace(tzinfo=timezone.utc)
mem_updated = mem.updated_at
if mem_updated.tzinfo is None:
    mem_updated = mem_updated.replace(tzinfo=timezone.utc)
```

| 参数 | 说明 |
|------|------|
| `time_shift` | 时间偏移量，用于调整恢复后数据的时间戳 |
| `target_subject_id` | 恢复的目标主题 ID |
| `snapshot_id` | 快照唯一标识符 |

### 快照元数据结构

创建快照时记录以下元数据：

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | `UUID` | 快照唯一标识 |
| `name` | `str` | 快照名称 |
| `version` | `str` | 快照版本 |
| `source_subject_id` | `UUID` | 源主题 ID |
| `episode_count` | `int` | 包含的事件数量 |
| `memory_count` | `int` | 包含的记忆数量 |
| `metadata_` | `dict` | 自定义元数据 |

资料来源：[server/services/snapshots.py:1-80]()

---

## 内存包服务

### 核心职责

`memory_packs.py` 提供了内存包的克隆、导入、导出等高级操作，支持在主题之间迁移数据或基于现有主题创建新的种子包。

### 克隆作用域

服务定义了四种克隆范围：

| 作用域 | 说明 | 包含内容 |
|--------|------|----------|
| `episodes` | 仅事件 | 源主题的全部事件 |
| `memories` | 仅记忆 | 源主题的全部记忆 |
| `episodes_and_memories` | 事件+记忆 | 事件和记忆，不含来源引用 |
| `episodes_memories_sources` | 完整克隆 | 事件、记忆及完整的来源引用链 |

### 冲突解决策略

| 策略 | 说明 | 行为 |
|------|------|------|
| `create_copy` | 创建副本（默认） | 为新导入的主题生成新 ID |
| `merge` | 合并 | 复用原始主题 ID |
| `cancel` | 取消 | 目标已存在时中止操作 |

### 导入流程

```mermaid
graph TD
    A[导入内存包请求] --> B[验证主题数量限制]
    B --> C[遍历源主题列表]
    C --> D[解析原始主题ID]
    D --> E{冲突策略检测}
    E -->|create_copy| F[生成新主题ID]
    E -->|merge| G[复用原始ID]
    E -->|cancel| H[检查目标存在]
    H -->|存在| I[抛出错误]
    H -->|不存在| G
    F --> J[按类型分组数据]
    J --> K[创建新主题及数据]
    K --> L[提交事务]
```

### 标识符映射机制

导入过程中，服务维护 `id_map` 字典，将原始主题 ID 映射到最终目标主题 ID：

```python
id_map: dict[str, str] = {}
for s in subjects:
    original = s.get("original_subject_id")
    _validate_subject_id(original, field="subjects[].original_subject_id", allow_reserved=True)
    final = await _resolve_target_subject(
        explicit=original if conflict_strategy != "create_copy" else None,
        suggested=original,
        conflict_strategy=conflict_strategy,
    )
    id_map[original] = final
```

### 来源验证

服务对来源标识符有严格的验证规则：

- `create_copy` 模式下允许保留前缀的 ID（如 `demo_web_*`）
- `merge` 和 `cancel` 模式不接受保留前缀的 ID
- 导入后自动将目标 ID 重写为 `imported-*` 前缀

资料来源：[server/services/memory_packs.py:1-100]()

---

## 交接服务

### 核心职责

`handoff.py` 模块负责生成紧凑的交接上下文包，用于在不同代理或会话之间传递上下文信息。交接包含请求者的身份信息、任务标识和会话状态。

### 交接请求参数

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `subject_id` | `str` | 是 | 主题 ID |
| `session_id` | `str` | 否 | 会话 ID |
| `reason` | `str` | 否 | 交接原因 |
| `max_tokens` | `int` | 否 | 最大 token 数 |
| `emit_receipt` | `bool` | 否 | 是否生成回执 |
| `query_id` | `str` | 否 | 查询 ID |
| `task_id` | `str` | 否 | 任务 ID |
| `parent_receipt_id` | `str` | 否 | 父回执 ID |
| `caller_id` | `str` | 条件必填 | 调用者 ID（部分配置下必填） |
| `caller_type` | `str` | 条件必填 | 调用者类型（部分配置下必填） |

### 租户配置验证

某些配置下，系统要求每个交接请求必须包含 `caller_id` 和 `caller_type`：

```python
if tenant_config_requires_caller and (not body.caller_id or not body.caller_type):
    raise HTTPException(
        status_code=401,
        detail=(
            "tenant config requires caller_id and caller_type on every "
            "handoff call"
        ),
    )
```

资料来源：[server/services/handoff.py:1-50]()

---

## 回执服务

### 核心职责

`receipts.py` 模块负责生成和管理操作回执（Receipt）。回执是操作的不可变审计记录，包含操作的输入、输出和元数据。

### 回执数据结构

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | `UUID` | 回执唯一标识 |
| `tenant_id` | `str` | 租户 ID |
| `operation_type` | `str` | 操作类型 |
| `query_id` | `str` | 关联的查询 ID |
| `task_id` | `str` | 关联的任务 ID |
| `parent_receipt_id` | `str` | 父回执 ID（用于追溯） |
| `input_data` | `dict` | 操作输入数据 |
| `output_data` | `dict` | 操作输出数据 |
| `metadata` | `dict` | 额外元数据 |
| `created_at` | `datetime` | 创建时间 |

### 层级关系

回执支持父子层级结构，允许追踪复杂操作链：

```mermaid
graph TD
    A[根回执] --> B[子回执 1]
    A --> C[子回执 2]
    B --> D[孙回执 1.1]
    C --> E[孙回执 2.1]
```

---

## Webhook 服务

### 核心职责

`webhooks.py` 模块提供异步事件通知能力，允许外部系统在特定事件发生时接收通知。

### 环境配置

| 环境变量 | 默认值 | 说明 |
|----------|--------|------|
| `STATEWAVE_WEBHOOK_URL` | — | Webhook 回调 URL（空则禁用） |
| `STATEWAVE_WEBHOOK_TIMEOUT` | `5.0` | HTTP 请求超时时间（秒） |

### 事件类型

| 事件类型 | 触发时机 |
|----------|----------|
| `episode.created` | 新事件创建时 |
| `memory.compiled` | 记忆编译完成时 |
| `memory.evolved` | 记忆演进时 |
| `snapshot.created` | 快照创建时 |
| `snapshot.restored` | 快照恢复时 |
| `handoff.issued` | 交接发起时 |

### 重试机制

Webhook 投递采用指数退避策略，配置最大重试次数确保最终一致性。

---

## 速率限制服务

### 核心职责

`ratelimit.py` 模块实现请求速率控制，保护系统免受滥用和过载。

### 速率限制策略

| 策略 | 说明 | 存储后端 |
|------|------|----------|
| `distributed` | 分布式模式 | PostgreSQL |
| `memory` | 内存模式 | 进程内内存 |

### 环境配置

| 环境变量 | 默认值 | 说明 |
|----------|--------|------|
| `STATEWAVE_RATE_LIMIT` | `0` | 每分钟请求/IP（0=禁用） |
| `STATEWAVE_RATE_LIMIT_STRATEGY` | `distributed` | 限流策略选择 |

### 限流维度

当前版本按 IP 地址进行速率限制，尚未支持按租户或 API Key 的细粒度控制。

资料来源：[README.md:1-50]()

---

## 备份导出服务

### 核心职责

`backup.py` 模块提供主题数据的导出功能，生成标准化的备份格式供导入或迁移使用。

### 导出数据结构

导出的 JSON 文档包含以下顶级字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `subjects` | `list` | 主题列表 |
| `episodes` | `list` | 事件列表 |
| `memories` | `list` | 记忆列表 |
| `resolutions` | `list` | 解决方案列表 |
| `exported_at` | `datetime` | 导出时间戳 |
| `version` | `str` | 导出格式版本 |

### 与导入的互操作性

导出格式与内存包导入端点完全兼容，确保数据可以在不同 Statewave 实例间自由迁移：

```python
from server.services.backup import export_subject
source_doc = await export_subject(source_subject_id, tenant_id=None)
```

资料来源：[server/services/memory_packs.py:50-60]()

---

## 服务层公共模式

### 多租户隔离

所有服务方法都接受可选的 `tenant_id` 参数，用于数据层面的租户隔离：

```python
async def some_service_method(..., tenant_id: str | None = None):
    """Service method with multi-tenant support."""
    pass
```

### 事务管理

服务层通过 SQLAlchemy 的异步会话管理事务：

```python
async with engine_module.get_session_factory()() as session:
    # 业务逻辑
    await session.commit()
```

### 日志记录

服务层采用结构化日志记录关键操作：

```python
logger.info(
    "snapshot_created", name=name, version=version, 
    episodes=len(eps), memories=len(mems)
)
```

---

## 服务间依赖关系

```mermaid
graph LR
    A[API 层] --> B[Context 服务]
    A --> C[Snapshot 服务]
    A --> D[Memory Pack 服务]
    A --> E[Handoff 服务]
    
    B --> F[Receipt 服务]
    B --> G[Webhook 服务]
    
    E --> F
    E --> G
    
    D --> H[Backup 服务]
    
    I[RateLimit 服务] --> A
```

---

## 总结

Statewave 的服务层通过模块化设计实现了业务逻辑的清晰分离。各服务专注于单一职责，同时通过标准化的接口相互协作。异步架构确保了高并发场景下的性能表现，而多租户支持则满足了企业级部署的需求。

---

<a id='p-database'></a>

## 数据库架构

### 相关页面

相关主题：[系统架构概览](#p-arch-overview)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [server/db/tables.py](https://github.com/smaramwbc/statewave/blob/main/server/db/tables.py)
- [server/db/repositories.py](https://github.com/smaramwbc/statewave/blob/main/server/db/repositories.py)
- [server/services/snapshots.py](https://github.com/smaramwbc/statewave/blob/main/server/services/snapshots.py)
- [server/services/context.py](https://github.com/smaramwbc/statewave/blob/main/server/services/context.py)
- [server/api/timeline.py](https://github.com/smaramwbc/statewave/blob/main/server/api/timeline.py)
</details>

# 数据库架构

## 概述

Statewave 采用 **PostgreSQL** 作为主数据库，通过 `asyncpg` 异步驱动实现高性能数据访问。数据库架构围绕三个核心实体构建：**Episode（事件）**、**Memory（记忆）** 和 **Subject（主体）**，支持多租户隔离、快照恢复和时间线查询等高级功能。

资料来源：[DOCKER.md:8]()

## 核心数据模型

### Entity-Relationship 概览

```mermaid
erDiagram
    Subject ||--o{ Episode : contains
    Subject ||--o{ Memory : contains
    Episode ||--o{ Memory : generates
    Subject ||--o{ Resolution : tracks
    Subject ||--o{ SubjectSnapshot : snapshots
    Memory }o--o{ Memory : supersedes
```

### 主要数据表

| 表名 | 用途 | 核心字段 |
|------|------|----------|
| `episodes` | 不可变事件记录 | id, subject_id, session_id, source, type, payload, occurred_at |
| `memories` | 从事件编译的记忆 | id, subject_id, kind, content, summary, source_episode_ids |
| `resolutions` | 问题解决状态跟踪 | id, subject_id, session_id, status, resolved_at |
| `subject_snapshots` | 主题时间点快照 | id, source_subject_id, episode_count, memory_count |

资料来源：[server/services/snapshots.py:1-100]()

## 表结构详解

### EpisodeRow（事件表）

事件是 Statewave 的基础数据单元，代表主体（Subject）的任意活动记录。

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | UUID | 事件唯一标识符 |
| `subject_id` | String | 关联的主体 ID |
| `session_id` | String | 所属会话标识 |
| `tenant_id` | String | 多租户隔离标识 |
| `source` | String | 事件来源（api, github, slack 等） |
| `type` | String | 事件类型（message, issue, pr 等） |
| `payload` | JSONB | 事件完整负载 |
| `metadata_` | JSONB | 附加元数据 |
| `provenance` | JSONB | 数据溯源信息 |
| `occurred_at` | DateTime | 事件实际发生时间 |
| `created_at` | DateTime | 记录创建时间 |

```python
# 事件创建示例（server/services/snapshots.py:51-65）
EpisodeRow(
    id=uuid.uuid4(),
    subject_id=snapshot_subject,
    session_id=ep.session_id,
    tenant_id=ep.tenant_id,
    source=ep.source,
    type=ep.type,
    payload=ep.payload,
    metadata_=ep.metadata_,
    provenance=ep.provenance,
    occurred_at=ep.occurred_at,
    created_at=ep.created_at,
)
```

资料来源：[server/services/snapshots.py:51-65]()

### MemoryRow（记忆表）

记忆是从事件编译的提炼数据，支持多种类型和有效期管理。

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | UUID | 记忆唯一标识符 |
| `subject_id` | String | 关联的主体 ID |
| `kind` | String | 记忆类型（episode_summary, profile_fact 等） |
| `content` | Text | 完整记忆内容 |
| `summary` | String | 摘要（200字符） |
| `confidence` | Float | 置信度（0-1） |
| `valid_from` | DateTime | 有效期起始 |
| `valid_to` | DateTime | 有效期结束（可选） |
| `source_episode_ids` | Array[UUID] | 源事件 ID 列表 |
| `status` | String | 状态（active, superseded 等） |
| `sensitivity_labels` | Array[String] | 敏感度标签 |

```python
# 记忆创建示例（server/services/compilers/heuristic.py:1-50）
MemoryRow(
    id=uuid.uuid4(),
    subject_id=ep.subject_id,
    kind="episode_summary",
    content=text[:500],
    summary=text[:200],
    confidence=0.8,
    valid_from=ep_valid_from,
    valid_to=compute_valid_to("episode_summary", ep_valid_from, ttl),
    source_episode_ids=[ep.id],
    metadata_={},
    status="active",
)
```

资料来源：[server/services/compilers/heuristic.py:1-50]()

### SubjectSnapshotRow（快照表）

快照用于备份和恢复主体在特定时间点的完整状态。

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | UUID | 快照唯一标识符 |
| `name` | String | 快照名称 |
| `version` | String | 版本标识 |
| `source_subject_id` | UUID | 源主体 ID |
| `episode_count` | Integer | 事件数量 |
| `memory_count` | Integer | 记忆数量 |
| `metadata_` | JSONB | 快照元数据 |

```python
# 快照创建示例（server/services/snapshots.py:85-95）
SubjectSnapshotRow(
    name=name,
    version=version,
    source_subject_id=snapshot_subject,
    episode_count=len(eps),
    memory_count=len(mems),
    metadata_=metadata or {},
)
```

资料来源：[server/services/snapshots.py:85-95]()

## 异步数据库访问模式

### 引擎与会话管理

Statewave 使用 SQLAlchemy 2.0 异步引擎，结合 `asyncpg` 驱动实现非阻塞 IO。

```python
# 异步会话获取模式（server/api/timeline.py:100-120）
from server.db import engine as engine_module

async with engine_module.get_session_factory()() as session:
    base = select(MemoryRow)
    # ... 查询操作
```

### 查询构建示例

```python
# 复杂查询：查找引用特定事件的记忆（server/api/timeline.py:130-150）
base = select(MemoryRow).where(
    MemoryRow.tenant_id == tenant_id,
    MemoryRow.subject_id == subject_id,
    func.any_(MemoryRow.source_episode_ids) == episode_uuid
)
```

资料来源：[server/api/timeline.py:100-150]()

## 仓储层设计

### Repository 模式

数据访问通过 Repository 模式封装，提供统一的 CRUD 操作接口。

```mermaid
graph TD
    A[API Layer] --> B[Service Layer]
    B --> C[Repository Layer]
    C --> D[(PostgreSQL)]
    
    E[Memory Repository] --> C
    F[Episode Repository] --> C
    G[Resolution Repository] --> C
```

### 核心仓储操作

| 操作类型 | 方法 | 说明 |
|----------|------|------|
| 创建 | `write_receipt()` | 写入收据记录 |
| 读取 | `get_session_factory()` | 获取异步会话 |
| 更新 | `compile_memories()` | 编译新记忆 |
| 删除 | 批量删除 | 按主体 ID 删除 |

资料来源：[server/db/repositories.py](https://github.com/smaramwbc/statewave/blob/main/server/db/repositories.py)

## 多租户数据隔离

### 隔离策略

Statewave 采用应用层多租户隔离，通过 `tenant_id` 字段实现数据分区。

```mermaid
graph LR
    A[Request] --> B{X-Tenant-ID Header}
    B -->|有租户ID| C[按 tenant_id 过滤]
    B -->|无租户ID| D[拒绝请求]
    
    C --> E[WHERE tenant_id = ?]
```

### 环境配置

| 环境变量 | 默认值 | 说明 |
|----------|--------|------|
| `STATEWAVE_TENANT_HEADER` | `X-Tenant-ID` | 租户标识头 |
| `STATEWAVE_REQUIRE_TENANT` | `false` | 是否强制要求租户头 |

```python
# 租户过滤查询示例
base = select(MemoryRow).where(
    MemoryRow.tenant_id == tenant_id,
    MemoryRow.subject_id == subject_id
)
```

资料来源：[README.md:1-50]()

## 时间线与快照管理

### 时间线查询

支持按时间顺序检索主体的事件和记忆，支持事件合并展示。

```python
# 时间线响应模型（server/api/admin.py:50-80）
class SessionTimelineResponse(BaseModel):
    session_id: str
    status: str
    first_message_at: str | None
    resolved_at: str | None
    episode_count: int
    events: list[TimelineEvent]
```

### 快照恢复

快照恢复支持时间偏移（Time Shift），确保恢复后时间戳的连续性。

```python
# 时间偏移处理（server/services/snapshots.py:130-160）
time_shift = target_created_at - snapshot_created_at

# 记忆时间戳偏移
created_at=mem_created + time_shift,
updated_at=mem_updated + time_shift,
valid_from=mem_valid_from + time_shift if mem_valid_from else None,
```

资料来源：[server/services/snapshots.py:130-160]()

## 索引与性能优化

### 推荐索引策略

| 表名 | 推荐索引 | 用途 |
|------|----------|------|
| `memories` | `(subject_id, kind)` | 记忆类型查询 |
| `memories` | `(source_episode_ids)` | 事件溯源查询 |
| `episodes` | `(subject_id, occurred_at)` | 时间线查询 |
| `episodes` | `(session_id)` | 会话聚合 |

### JSONB 字段优化

```python
# JSONB 查询示例
query = select(MemoryRow).where(
    MemoryRow.payload['event_type'].astext == 'message'
)
```

## 迁移与版本管理

### Alembic 集成

Statewave 使用 Alembic 进行数据库迁移管理。

```bash
# Helm 安装时的预安装 Job
alembic upgrade head
```

### 迁移执行时机

| 操作 | 迁移时机 |
|------|----------|
| 首次安装 | Pre-install Job |
| 版本升级 | Pre-upgrade Job |

资料来源：[helm/statewave/README.md:1-30]()

## 配置参考

### 数据库连接配置

```yaml
# Docker Compose 配置示例
environment:
  STATEWAVE_DATABASE_URL: postgresql+asyncpg://statewave:statewave@db:5432/statewave
```

### 测试环境配置

```bash
# 创建测试数据库
PGPASSWORD=statewave createdb -h localhost -U statewave statewave_test
```

```python
# 集成测试执行
pytest tests/integration/ -v
```

资料来源：[README.md:100-120]()

## 最佳实践

### 数据建模建议

1. **事件不可变性**：事件一旦写入不应修改，通过新事件表达状态变更
2. **记忆有效期**：使用 `valid_from`/`valid_to` 管理记忆时效
3. **源事件追踪**：始终维护 `source_episode_ids` 引用链
4. **租户隔离**：所有查询必须包含 `tenant_id` 过滤条件

### 性能注意事项

1. 避免全表扫描，使用索引覆盖查询
2. 批量操作使用 `BATCH_SIZE = 50` 分批处理
3. 大型导入使用快照机制而非实时编译

---

---

## Doramagic 踩坑日志

项目：smaramwbc/statewave

摘要：发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。

## 1. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 建议检查：将假设转成下游验证清单。
- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。
- 证据：capability.assumptions | github_repo:1219923941 | https://github.com/smaramwbc/statewave | README/documentation is current enough for a first validation pass.

## 2. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。
- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。
- 证据：evidence.maintainer_signals | github_repo:1219923941 | https://github.com/smaramwbc/statewave | last_activity_observed missing

## 3. 安全/权限坑 · 下游验证发现风险项

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：下游已经要求复核，不能在页面中弱化。
- 建议检查：进入安全/权限治理复核队列。
- 防护动作：下游风险存在时必须保持 review/recommendation 降级。
- 证据：downstream_validation.risk_items | github_repo:1219923941 | https://github.com/smaramwbc/statewave | no_demo; severity=medium

## 4. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 建议检查：把风险写入边界卡，并确认是否需要人工复核。
- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。
- 证据：risks.scoring_risks | github_repo:1219923941 | https://github.com/smaramwbc/statewave | no_demo; severity=medium

## 5. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。
- 防护动作：issue/PR 响应未知时，必须提示维护风险。
- 证据：evidence.maintainer_signals | github_repo:1219923941 | https://github.com/smaramwbc/statewave | issue_or_pr_quality=unknown

## 6. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。
- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。
- 证据：evidence.maintainer_signals | github_repo:1219923941 | https://github.com/smaramwbc/statewave | release_recency=unknown

<!-- canonical_name: smaramwbc/statewave; human_manual_source: deepwiki_human_wiki -->
