7574f9c24c
更新当前状态描述、Phase 7 交付物详情、里程碑 M3 状态、依赖性图谱及下一步行动
636 lines
32 KiB
Markdown
636 lines
32 KiB
Markdown
# AG Core Roadmap
|
||
|
||
> 定稿日期:2026-05-11
|
||
> 最后更新:2026-07-05
|
||
|
||
## 愿景
|
||
|
||
AG Core 定位为构建 AI 智能体的底层工具箱,通过模块化、可插拔的架构,提供大模型调用、提示词工程、工具系统、记忆检索四大核心能力,支持快速组合出符合业务需求的智能体应用。
|
||
|
||
**当前状态**:v0.1.0 已发布(2026-07-04)。Phase 0-7 全部完成,Provider IR 重构 + LlmCycle 简化 + 8 个离线示例 + SqliteStore 持久化已交付。v0.2.0 已细分为 8 个增量 Phase(Phase 5-12),其中 Phase 5(Ollama Provider + `#[non_exhaustive]` 兼容性护栏 + `ProviderConfig::from_env`)、Phase 6(ToolDef IR 正式化)与 Phase 7(SqliteStore 持久化,9 个内联测试 + 持久化 round-trip + 10×10 并发写入)均已完成,下一步进入 Phase 8(MVP 集成出口 / v0.2.0-rc.1)。
|
||
|
||
---
|
||
|
||
## 模块完整性评估
|
||
|
||
| 功能领域 | 方案状态 | 文档位置 | 实现优先级 |
|
||
|---------|---------|---------|-----------|
|
||
| LLM 调用周期 | ✅ 完整 | `specs/llm-call-lifecycle.md` | P0 |
|
||
| 提示词工程 | ✅ 完整 | `docs/4-prompt-engineering.md` | P1 |
|
||
| 工具系统 + 权限 | ✅ 完整 | `docs/5-tool-system.md` | P1 |
|
||
| 记忆检索 | ✅ 完整 | `docs/6-memory-system.md` | P2 |
|
||
| Agent 运行时(4a 胶水层) | ✅ 已实现 | `docs/7-agent-runtime.md` | P2 |
|
||
| 生命周期钩子 | ✅ 完整 | `docs/3-phase0-remaining.md` | P0(LLM Cycle 扩展) |
|
||
| Provider 注册发现 | ✅ 完整 | `docs/3-phase0-remaining.md` | P0(Provider 接口扩展) |
|
||
| 流式事件系统 | ✅ 完整 | `docs/3-phase0-remaining.md` | P0(流式接口前置) |
|
||
|
||
---
|
||
|
||
## 分阶段 Roadmap
|
||
|
||
### Phase 0 — Foundation(基础设施)
|
||
|
||
**目标**:实现 LLM 调用周期的核心功能,作为所有上层模块的基础。
|
||
|
||
**交付物**:
|
||
1. ✅ `llm/types.rs` — 核心数据类型(Message, ContentBlock, ChatRequest/Response, ToolDefinition, StopReason)
|
||
2. ✅ `llm/error.rs` — 错误体系(LlmError 枚举,可重试/不可重试判断)
|
||
3. ✅ `llm/provider.rs` + `llm/provider/openai.rs` — Provider 接口 + OpenAI 兼容实现
|
||
4. ✅ `llm/provider/registry.rs` — ProviderRegistry(多 Provider 注册发现)
|
||
5. ✅ `llm/cycle.rs` + `llm/cycle/{retry,usage}.rs` — 生命周期引擎(重试策略 + 用量追踪)
|
||
6. ✅ `llm/hooks.rs` — HookExecutor 接口(生命周期钩子)
|
||
7. ✅ `llm/stream.rs` — StreamEvents 流式事件系统(AssistantTextDelta, ToolExecutionStarted 等)
|
||
8. ✅ `llm/compact.rs` — Auto-compaction(上下文自动压缩)
|
||
9. ✅ `Cargo.toml` — 添加依赖(tokio, reqwest, serde, thiserror, async-trait, tracing)
|
||
|
||
**依赖**:无
|
||
|
||
**优先级**:Must Have
|
||
|
||
**预估规模**:约 1000 行核心代码
|
||
|
||
**状态**:✅ Phase 0 全部交付物已完成
|
||
|
||
---
|
||
|
||
### Phase 1 — Prompt Engineering(提示词工程)
|
||
|
||
**目标**:提供提示词的组合、模板化与优化能力。
|
||
|
||
**交付物**:
|
||
1. ✅ `prompt.rs` + `prompt/` 模块
|
||
2. ✅ `PromptTemplate` — 模板引擎(支持变量插值、条件渲染)
|
||
3. ✅ `PromptComposer` — 提示词组合器(拼接 system/user/assistant 消息)
|
||
4. ✅ `docs/4-prompt-engineering.md` — 方案文档
|
||
|
||
**依赖**:无(可与 Phase 0 并行)
|
||
|
||
**优先级**:Should Have
|
||
|
||
**预估规模**:约 400 行代码
|
||
|
||
**状态**:✅ Phase 1 全部交付物已完成
|
||
|
||
---
|
||
|
||
### Phase 2 — Tool System(工具系统)
|
||
|
||
**目标**:实现 MCP 协议集成与自定义工具注册、调用、权限控制。
|
||
|
||
**交付物**:
|
||
1. ✅ `tools.rs` + `tools/` 模块(base/registry/permission/mcp/error)
|
||
2. ✅ `ToolRegistry` — 工具注册表(注册、发现、调用、并行执行、超时控制)
|
||
3. ✅ `BaseTool` trait — 工具抽象接口(含 ToolContext 执行上下文)
|
||
4. ✅ `McpClient` — MCP 协议客户端(stdio transport,StreamableHttp 预留)
|
||
5. ✅ `PermissionChecker` — 工具执行权限检查(白名单/黑名单/自定义权限)
|
||
6. ✅ `docs/5-tool-system.md` — 方案设计文档
|
||
7. ✅ 扩展 `llm/cycle.rs` 支持自动 tool 循环(`submit_with_tools()` + `submit_request()` + `maybe_compact()`)
|
||
8. ✅ `ToolError` — 结构化错误体系(含 `is_recoverable()` 分类)
|
||
|
||
**依赖**:Phase 0(LlmProvider 接口传递 tool definitions)、Phase 1(提示词可能需要注入工具描述)
|
||
|
||
**优先级**:Should Have
|
||
|
||
**预估规模**:约 900 行代码(实际约 1500 行)
|
||
|
||
**状态**:✅ Phase 2 全部交付物已完成
|
||
|
||
---
|
||
|
||
### Phase 3 — Memory System(记忆系统)
|
||
|
||
**目标**:提供对话记忆的存储、检索与管理能力。
|
||
|
||
**交付物**:
|
||
1. ✅ `memory.rs` + `memory/` 模块(store / conversation / knowledge / retriever / error / types)
|
||
2. ✅ `MemoryStore` trait + `InMemoryStore` — 记忆存储抽象(可插拔后端)+ 默认实现
|
||
3. ✅ `ConversationMemory` — 对话记忆管理(sliding window / 全量),复用 `llm::compact`
|
||
4. ✅ `KnowledgeStore` — 知识页面存储(具体 struct,非 trait,基于 MemoryStore)
|
||
5. ✅ `MemoryRetriever` — 记忆检索器(TextOverlap Dice 系数评分,单通道)
|
||
6. ✅ `docs/6-memory-system.md` — 方案设计文档
|
||
7. ✅ `docs/note-knowledge-graph-design.md` — KnowledgeGraph 等 Phase 4 备用设计
|
||
8. ✅ `EvictionPolicy` — 支持 None / Ttl / Capacity 三种淘汰策略
|
||
|
||
**依赖**:Phase 0(llm::compact 复用)、Cargo.toml 新增 `time` 依赖
|
||
|
||
**优先级**:Could Have
|
||
|
||
**预估规模**:约 700 行代码(实际约 1242 行,含测试)
|
||
|
||
**状态**:✅ Phase 3 全部交付物已完成
|
||
|
||
---
|
||
|
||
### Phase 4a — Agent Core Glue(核心胶水层)
|
||
|
||
**目标**:提供最小可用的 Agent Runtime——把 Phase 0-3 的能力"装配"成 `AgentSession::submit_turn`。上层可基于 4a 构建多轮对话应用。
|
||
|
||
**交付物**:
|
||
1. ✅ `agent.rs` + `agent/` 模块(7 个文件:agent/error/runtime/builder/session/task + 模块根)
|
||
2. ✅ `Agent` trait — 智能体角色定义(name / system_prompt / tool_definitions)
|
||
3. ✅ `AgentSession` — 会话实例(绑定 `Arc<dyn Agent>` + `RuntimeBundle` + 内联 HashMap session_data)
|
||
4. ✅ `RuntimeBundle` — 显式依赖注入容器(不含 session_memory_backend)
|
||
5. ✅ `AgentBuilder` — 链式构造入口(不含 session_memory_backend)
|
||
6. ✅ `AgentError` — 统一错误类型(7 个变体:Llm / Tool / Memory / HookBlocked / LimitExceeded / Config / Other;不含 PlanParse)
|
||
7. ✅ `Plan` / `Step` / `StepStatus` — 纯数据结构(不含任何解析逻辑)
|
||
8. ✅ Hook 事件扩展:OnTurnStart / OnTurnEnd + turn_index 字段
|
||
9. ✅ `docs/7-agent-runtime.md` — 方案设计文档(含 4a/4b/4c 分阶段计划)
|
||
|
||
**实际新增**:
|
||
- 新增文件 7 个(agent.rs + agent/{agent, error, runtime, builder, session, task}.rs)
|
||
- 修改文件 3 个(lib.rs +1 行;llm/hooks.rs +13 行追加变体/字段;llm/cycle.rs 内部字段 Box→Arc + 新增 `new_with_arc` 公共方法)
|
||
- 实际代码量约 800 行(含测试;纯实现约 470 行——略高于方案预估 440 行,因 AgentSession 的 tests 模块内联 MockProvider/StubAgent 等辅助结构)
|
||
- 新增内联测试 22 个;全量测试 84 → 109(0 失败)
|
||
- clippy 0 警告(agent 模块)
|
||
- 无新增外部依赖
|
||
|
||
**依赖**:Phase 0, 1, 2, 3
|
||
|
||
**优先级**:Could Have
|
||
|
||
**预估规模**:约 440 行代码
|
||
|
||
**状态**:✅ Phase 4a 全部交付物已完成
|
||
|
||
---
|
||
|
||
### Phase 4b — Task Execution(任务执行)
|
||
|
||
**目标**:在 Phase 4a 基础上,赋予智能体"拆解目标 → 逐步执行"的能力。
|
||
|
||
**前置条件**:Phase 4a 已完成。
|
||
|
||
**交付物**:
|
||
1. ✅ `TaskAgent` trait — `run(goal)` 自主式 + `execute_plan(plan)` 外部驱动式
|
||
2. ✅ `PlanParser` trait + `JsonPlanParser` 参考实现
|
||
3. ✅ `AgentError` 追加 PlanParse 变体(共 7 个变体)
|
||
4. ✅ Hook 事件扩展:OnPlanStepComplete + plan_step_index 字段
|
||
|
||
**依赖**:Phase 4a
|
||
|
||
**优先级**:Could Have
|
||
|
||
**预估规模**:约 200 行代码(增量)
|
||
|
||
**实际新增**:
|
||
- 修改文件 2 个(llm/hooks.rs +5 行;agent/error.rs +10 行)
|
||
- 新增代码约 150 行(含测试;纯实现约 90 行)
|
||
- 新增内联测试 4 个;全量测试 109 → 113(0 失败)
|
||
- clippy 0 警告
|
||
- 无新增外部依赖
|
||
|
||
**状态**:✅ Phase 4b 全部交付物已完成
|
||
|
||
---
|
||
|
||
### Phase 4c — Session Memory(会话级记忆)
|
||
|
||
**目标**:提供会话级 key-value 记忆,作为 session 内各 context 之间的信息桥接通道。
|
||
|
||
**前置条件**:Phase 4a 已完成(可与 Phase 4b 并行)。
|
||
|
||
**交付物**:
|
||
1. ✅ `SessionMemory` struct — 基于 `MemoryStore`,按 session_id namespace 隔离
|
||
2. ✅ `RuntimeBundle` + `AgentBuilder` 扩展 `session_memory_backend` 字段
|
||
3. ✅ `AgentSession` 替换内联 HashMap 为完整 `SessionMemory`
|
||
|
||
**依赖**:Phase 4a(Phase 3 MemoryStore)
|
||
|
||
**优先级**:Could Have
|
||
|
||
**预估规模**:约 115 行代码(增量)
|
||
|
||
**实际新增**:
|
||
- 新增文件 1 个(agent/session_memory.rs)
|
||
- 修改文件 4 个(agent/runtime.rs +5 行;agent/builder.rs +10 行;agent/session.rs +30 行;agent.rs +2 行)
|
||
- 新增代码约 180 行(含测试;纯实现约 100 行)
|
||
- 新增内联测试 3 个;全量测试 113 → 116(0 失败)
|
||
- clippy 0 警告
|
||
- 无新增外部依赖
|
||
|
||
**状态**:✅ Phase 4c 全部交付物已完成
|
||
|
||
---
|
||
|
||
## 依赖关系图
|
||
|
||
```mermaid
|
||
graph BT
|
||
P0["<b>Phase 0: Foundation</b><br/>LLM Cycle<br/>ProviderRegistry<br/>HookExecutor<br/>StreamEvents<br/>Auto-compaction"]:::done
|
||
P1["<b>Phase 1: Prompt Engineering</b><br/>PromptTemplate<br/>PromptComposer"]:::done
|
||
P2["<b>Phase 2: Tool System</b><br/>Tool Registry<br/>PermissionChecker<br/>MCP Client"]:::done
|
||
P3["<b>Phase 3: Memory System</b><br/>MemoryStore<br/>ConversationMemory<br/>KnowledgeStore"]:::done
|
||
P4a["<b>Phase 4a: Core Glue</b><br/>AgentSession<br/>RuntimeBundle<br/>Plan/Step 纯数据"]:::done
|
||
P4b["<b>Phase 4b: Task Execution</b><br/>TaskAgent<br/>PlanParser<br/>JsonPlanParser"]:::done
|
||
P4c["<b>Phase 4c: Session Memory</b><br/>SessionMemory"]:::done
|
||
|
||
P1 --> P0
|
||
P2 --> P0
|
||
P3 --> P0
|
||
P2 --> P1
|
||
P4a --> P1
|
||
P4a --> P2
|
||
P4a --> P3
|
||
P4b --> P4a
|
||
P4c --> P4a
|
||
|
||
classDef done fill:#4ade80,stroke:#16a34a,color:#1a1a1a
|
||
classDef pending fill:#fbbf24,stroke:#d97706,color:#1a1a1a
|
||
```
|
||
|
||
---
|
||
|
||
## v0.2.0 — 生产就绪(Production-Ready Core)
|
||
|
||
**目标**:解决 Rust Agent 工具箱从"能跑"到"能被人依赖"的鸿沟。持久化、配置层、上下文管理三大块补齐后,开发者可在 30 分钟内写出生产可用的 Agent 服务。
|
||
|
||
**总体规模**:8 个增量 Phase(Phase 5-12),17 个可验证 Step。
|
||
|
||
### 功能清单
|
||
|
||
#### P0 — 必须交付
|
||
|
||
| # | 功能 | 模块 | 方案要点 |
|
||
|---|------|------|---------|
|
||
| 1 | SqliteStore | `memory` | `rusqlite` + `bundled` feature,`MemoryStore` 的 SQLite 实现,进程重启数据不丢 |
|
||
| 2 | ProviderConfig 扩展 + `from_env()` | `llm` | 补全 `timeout_secs` / `max_retries` 字段;`AG_LLM_*` 环境变量辅助函数 |
|
||
| 3 | ToolDefinition IR 正式化 | `tools` | 移除 deprecated OpenAI wire 格式,替换为自定义 `ToolDef` 结构体 |
|
||
| 4 | API 稳定性管理 | `*` | 公开枚举加 `#[non_exhaustive]`;CHANGELOG 记录 Breaking Changes;废弃 API 用 `#[deprecated]` 标记 |
|
||
| 5 | Quick Start + 端到端示例 | `examples/` | 30 行 `main.rs` 快速开始;一个"SQLite 持久化 + Provider + 工具调用 + 多轮对话"的可运行示例(`cargo run --example`) |
|
||
|
||
#### P1 — 重要但不阻塞
|
||
|
||
| # | 功能 | 模块 | 方案要点 |
|
||
|---|------|------|---------|
|
||
| 6 | Ollama Provider | `llm/provider` | OpenAI Compat,本地 LLM 支持,实现量极小 |
|
||
| 7 | VectorRetriever trait | `memory` | 语义检索 trait 抽象(`index` / `search`),不绑定后端实现 |
|
||
| 8 | 流式 `submit_turn_stream` | `agent` | `AgentSession` 新增 `submit_turn_stream()`,返回 `Stream<Item = StreamEvent>` |
|
||
| 9 | 测试补强 | `*` | wiremock Provider roundtrip 测试;多线程并发写入 MemoryStore 测试 |
|
||
|
||
#### P2 — 有时间再做
|
||
|
||
| # | 功能 | 模块 | 备注 |
|
||
|---|------|------|------|
|
||
| 10 | MCP StreamableHttp | `tools` | 当前仅预留枚举变体 |
|
||
| 11 | Gemini Provider | `llm/provider` | 协议差异大,实现成本较高 |
|
||
| 12 | 文件系统 MemoryStore 后端 | `memory` | JSON/JSONL 轻量持久化 |
|
||
|
||
### ContextSlot 上下文管理
|
||
|
||
**模块归属**:`src/llm/context.rs`(与 `compact.rs` 同级)
|
||
|
||
**核心概念**:`ContextSlot` 是一段带策略配置的消息列表,以 `slot_id` 为 namespace 独立持久化到 `MemoryStore`。支持三种模式、三种来源和派生关联(记录 `parent_id`)。
|
||
|
||
**核心类型**:
|
||
|
||
```rust
|
||
pub struct ContextSlot { id, session_id, config, messages, store }
|
||
pub struct SlotConfig { mode: SlotMode, source: SlotSource, budget, compact }
|
||
pub enum SlotMode {
|
||
Full, // 完整对话历史
|
||
Focused(FocusedConfig), // 聚焦:保持 LLM 注意力
|
||
Readonly, // 只读参考上下文
|
||
}
|
||
pub struct FocusedConfig { keep_system, recent_turns, inject_summary }
|
||
pub enum SlotSource {
|
||
New, // 全新空槽,独立持久化
|
||
Derived { parent_id, strategy: DeriveStrategy }, // 从父 slot 派生
|
||
Static(Vec<Message>), // 预置消息,不持久化
|
||
}
|
||
pub enum DeriveStrategy { Full, Focused(FocusedConfig) }
|
||
pub struct ContextBudget { system, history, tools, tool_results, reserve }
|
||
```
|
||
|
||
**持久化 Key 命名**:
|
||
- `slot_msg:{session_id}:{slot_id}:{index}` → 消息内容
|
||
- `slot_meta:{session_id}:{slot_id}` → `SlotMeta`(含 `parent_id`)
|
||
- `slot_rel:{session_id}:{child_id}:parent` → `"{parent_id}"`
|
||
|
||
**`AgentSession` 扩展**:
|
||
- `create_slot(id, config)` — 创建新 slot
|
||
- `switch_slot(id)` — 切换当前 slot
|
||
- `list_slots()` — 列出所有 slot
|
||
- `derive_slot(id, parent_id, strategy)` — 从父 slot 派生
|
||
|
||
**与 `ConversationMemory` 的关系**:保留不废除。`ConversationMemory` 继续服务传统对话场景。
|
||
|
||
**v0.2 不做**:
|
||
- ❌ `slot.fork()` / `merge()` — 分支方法推迟到 v0.3+
|
||
- ❌ `inject_summary` 自动生成 — v0.2 仅消费端(从 `SessionMemory` 读取),生成在 v0.3+
|
||
- ❌ 血缘关系图遍历 — 只存 `parent_id`,不做查询
|
||
|
||
**依赖**:Phase 0(MemoryStore trait)、Phase 3(MemoryStore 持久化)
|
||
**优先级**:P1
|
||
|
||
---
|
||
|
||
### v0.2.0 实施计划 — 8 个增量 Phase
|
||
|
||
> **编号说明**:Phase 5-12 接续 v0.1 的 Phase 0-4c,按开发顺序排列。
|
||
|
||
#### Phase 5: 热身准备(Warmup)
|
||
|
||
**目标**:快速交付三个互不依赖的独立改动,建立交付节奏。
|
||
|
||
| Step | 内容 | 文件范围 | 验证标准 |
|
||
|------|------|---------|---------|
|
||
| **5.1** ✅ | `ProviderConfig` 扩展:补 `timeout_secs`(def=30) + `max_retries`(def=3);新增 `ProviderConfig::from_env(prefix)` | `llm/provider.rs` + 各 Provider `new()` 构造函数 | `cargo test` + `from_env()` 单元测试 |
|
||
| **5.2** ✅ | `OllamaProvider`:基于 `GenericOpenaiProvider` 包装,改 base_url 为 `http://localhost:11434`;`ProviderType` 新增 `Ollama` | `llm/provider/provider.rs` + `llm/provider/ollama.rs`(新增) | `cargo build` — 纯类型级验证 |
|
||
| **5.3** ✅ | 公开枚举 `#[non_exhaustive]` 前置标记:`ProviderType` / `StopReason` / `FinishReason` / `EvictionPolicy` / `SlotMode`(预置) | 各枚举定义处 | 编译通过 + `cargo clippy` 0 警告 |
|
||
|
||
**实际新增**(2026-07-05 commit `98dfe6c`):
|
||
- 新增文件 1 个(`llm/provider/ollama.rs`,72 行)
|
||
- 修改文件 2 个(`llm/provider.rs` 加 `from_env` + `Default` + 4 个字段;`memory/store.rs` EvictionPolicy 加 `#[non_exhaustive]`)
|
||
- `ProviderType::Ollama` 变体 + `FromStr` 解析("ollama" → Ollama)
|
||
- `OllamaProvider::new(base_url, api_key, model, timeout_secs)` + `with_client()` 构造函数
|
||
- `ProviderConfig::from_env(prefix)` 解析 `{prefix}_API_KEY` / `{prefix}_BASE_URL` / `{prefix}_MODEL` 环境变量
|
||
- 全量测试 182 → 190(+8,phase 5 新增 from_env 与 Ollama 相关单测)
|
||
- clippy 0 警告
|
||
|
||
**依赖**:无(三个 Step 互不冲突)
|
||
**优先级**:P0(5.1)+ P1(5.2)+ P0 前置(5.3)
|
||
**为何独立成 Phase**:三个改动零文件重叠,可以并行推进。它们是后续所有 Phase 的"门把手"——先做完热身再进入核心工作。
|
||
**状态**:✅ Phase 5 全部交付物已完成
|
||
|
||
---
|
||
|
||
#### Phase 6: ToolDefinition IR 正式化
|
||
|
||
**目标**:引入 `ToolDef` 新类型,替换已标记 `#[deprecated]` 的 `ToolDefinition`(`OpenaiToolDefinition` 别名)。
|
||
|
||
**这是 v0.2 技术风险最高的 Phase**,影响 4 个模块约 8 个文件。通过 5 个 Step 逐文件切割确保每步可编译。
|
||
|
||
| Step | 内容 | 验证标准 |
|
||
|------|------|---------|
|
||
| **6.1** ✅ | `types/tool.rs` 新增 `ToolDef` 结构体 + `From<ToolDef> for OpenaiToolDefinition` + 反向 `From` | 单元测试 roundtrip |
|
||
| **6.2** ✅ | `types/mod.rs` 切别名 `pub type ToolDefinition = ToolDef`;`MessageRequest.tools` 改 `Vec<ToolDef>` | `cargo build` 编译断点 |
|
||
| **6.3** ✅ | `cycle.rs` 4 个方法签名 + `registry.rs` `definitions()` 签名更新 | `cargo build` |
|
||
| **6.4** ✅ | Provider 适配层(openai.rs / anthropic.rs / openai_compat.rs):`build_request()` 内做 `ToolDef → wire-format` 转换 | `cargo test` 每个 provider 测试 |
|
||
| **6.5** ✅ | 所有测试/示例中 `ToolDefinition` → `ToolDef` 修复;移除旧 `#[deprecated]` alias | `cargo test --all-targets` 全绿 |
|
||
|
||
**边界切割技巧**:
|
||
- Step 6.1 → 6.2 之间是安全 checkpoint:新类型存在但旧代码照常编译
|
||
- Provider 层不改序列化逻辑,只加一层 `From` 转换
|
||
- 当前代码中 `ToolDefinition` 已是 `#[deprecated(since = "0.1.0")]`,用户已有迁移预期
|
||
|
||
**依赖**:无(仅与 Phase 5.3 有枚举兼容关系)
|
||
**优先级**:P0
|
||
|
||
**实际新增**(2026-07-05 commit `4cf5918` / `9da9b83` / `b187519`,详见 `docs/13-phase6-tooldef-ir.md`):
|
||
- 修改文件 8 个:`llm/types/tool.rs`、`llm/types/mod.rs`、`llm/types/request_v2.rs`、`llm/cycle.rs`、`llm/provider/openai.rs`、`tools/registry.rs`、`tools/mcp.rs`、`agent/agent.rs`
|
||
- `ToolDef` IR(name / description / parameters,无 `strict`)新增于 `types/tool.rs`,配套双向 `From` 转换
|
||
- `OpenaiToolDefinition` 降级为 `#[doc(hidden)]`,仅供 OpenAI 适配层内部消费
|
||
- `MessageRequest.tools` 切换为 `Vec<ToolDef>`
|
||
- `ToolDefinition` 别名最终完全移除(直接使用 `ToolDef`)
|
||
- 4 处 `#[allow(deprecated)]` 抑制点全部清理(cycle/registry/mcp/agent);残留 `#[allow(deprecated)]` 均与 `ChatResponse` / `with_system_prompt` 等其他弃用项无关
|
||
- 新增 roundtrip 测试 `message_request_with_tools_roundtrip`(断言 `strict` 字段不泄漏到序列化输出)
|
||
- Anthropic 适配层字段名一致零改动;openai_compat/ollama 委托 `GenericOpenaiProvider` 零改动
|
||
- 全量测试 190 → 191(+1,Phase 6 新增 roundtrip);clippy 0 警告
|
||
|
||
**状态**:✅ Phase 6 全部交付物已完成
|
||
|
||
---
|
||
|
||
#### Phase 7: SqliteStore 持久化
|
||
|
||
**目标**:实现 `MemoryStore` 的 SQLite 后端,进程重启数据不丢。
|
||
|
||
**与 Phase 6 无耦合,可重叠开发。**
|
||
|
||
| Step | 内容 | 文件 | 验证标准 |
|
||
|------|------|-----|---------|
|
||
| **7.1** ✅ | 新增 `memory/store/sqlite.rs`:`Mutex<Connection>` + `spawn_blocking`,实现 `save/get/delete/list` + prefix 过滤 | `memory/store/sqlite.rs` + `Cargo.toml`(add `rusqlite`) | 单元测试 CRUD + prefix 查询 |
|
||
| **7.2** ✅ | WAL 模式 + 并发安全 + 集成测试(`tokio::spawn` 10 个并发 task) | `sqlite.rs` 扩展 | 并发写入 100 轮无 race |
|
||
|
||
**设计决策**:
|
||
- 用 `Mutex<Connection>` 而非连接池(ponytail:一个连接够用就不加 r2d2)
|
||
- WAL 模式:`PRAGMA journal_mode=WAL` 解决读写锁
|
||
|
||
**依赖**:`MemoryStore` trait(v0.1 Phase 3 已就绪)
|
||
**优先级**:P0
|
||
|
||
**实际新增**(2026-07-05 commit `13edacd` / `c8a91f6` / `c82af60`,详见 `docs/14-phase7-sqlite-store.md`):
|
||
- 方案文档:`docs/14-phase7-sqlite-store.md`(526 行,Phase 7 设计推演与权衡记录)
|
||
- 结构重组:`src/memory/store.rs` 单体文件 → `src/memory/store/{mod.rs(in_memory.rs, sqlite_store.rs)}` 模块目录;外部导入路径 `crate::memory::store::MemoryStore` 不变
|
||
- 新增文件 2 个:`src/memory/store/sqlite_store.rs`(545 行 SqliteStore 实现 + 9 个内联测试)、`src/memory/store/in_memory.rs`(266 行,结构搬移)
|
||
- 核心实现要点:
|
||
- `Arc<Mutex<Connection>>` 串行化所有 IO;`spawn_blocking` 卸载到阻塞线程池
|
||
- WAL 模式 + `synchronous=NORMAL` + `busy_timeout=5s` + `wal_autocheckpoint=1000`
|
||
- `PRAGMA user_version` schema 版本管理(`INITIAL_USER_VERSION = 1`)
|
||
- `created_at` 归一化为 UTC 的 RFC 3339 TEXT,字典序等价时间序
|
||
- 错误精细映射:`SqliteFailure` / `InvalidQuery` → `InvalidInput`;`FromSqlConversionFailure` → `Serialization`;其他 → `Storage`
|
||
- 9 个内联测试覆盖:CRUD、upsert、prefix / since / offset+limit 过滤、10 写者 × 10 次并发写入、持久化 round-trip(重启连接不丢数据)、`InMemoryStore ↔ SqliteStore` trait-box 互换兼容性
|
||
- 依赖:`rusqlite = { version = "0.32", features = ["bundled"] }`;`time` 增补 `parsing` / `formatting` / `macros` features;`dev-dependencies` 新增 `tempfile = "3"`
|
||
- 全量测试 191 → 200(+9,Phase 7 新增 SqliteStore 单测);clippy 0 警告
|
||
|
||
**状态**:✅ Phase 7 全部交付物已完成
|
||
|
||
---
|
||
|
||
#### Phase 8: MVP 集成出口(v0.2.0-rc.1 候选)
|
||
|
||
**目标**:P0 五项全部交付。开发者 clone 仓库后 10 分钟跑起持久化 Agent。
|
||
|
||
| Step | 内容 | 验证标准 |
|
||
|------|------|---------|
|
||
| **8.1** | API 稳定性扫尾:`#[deprecated]` 整理 + CHANGELOG v0.2 + 公开类型回顾 | 人工 review + `cargo doc` 无 warning |
|
||
| **8.2** | Quick Start 示例(30 行 `main.rs`):MockProvider + EchoTool + 一次 `submit_turn` | `cargo run --example quick_start` exit 0 |
|
||
| **8.3** | 端到端示例:SqliteStore + Ollama/OpenAI(from_env) + 自定义 Tool + 多轮对话 | `cargo run --example end_to_end`(Mock fallback,无需 API key)|
|
||
|
||
**Phase 8 完成后可打 `v0.2.0-rc.1` 标签**。
|
||
|
||
**依赖**:Phase 5(ProviderConfig from_env)+ Phase 6(ToolDef)+ Phase 7(SqliteStore)
|
||
**优先级**:P0
|
||
|
||
---
|
||
|
||
#### Phase 9: 流式体验增强
|
||
|
||
**目标**:Agent 会话支持流式输出,开发者看到实时 token。
|
||
|
||
| Step | 内容 | 文件 | 验证标准 |
|
||
|------|------|-----|---------|
|
||
| **9.1** | `AgentSession::submit_turn_stream(user_input) -> impl Stream<Item=StreamEvent>` | `agent/session.rs` | 单元测试验证流事件序列:`TextDelta → ... → MessageComplete` |
|
||
|
||
**注意**:tool 自动循环时流中插入 `ToolExecutionStarted` 事件,用户端 UI 显示"正在调用工具..."。
|
||
|
||
**依赖**:Phase 6(ToolDef)+ `LlmProvider.chat_stream`(v0.1 已有)
|
||
**优先级**:P1
|
||
|
||
---
|
||
|
||
#### Phase 10: ContextSlot 上下文管理
|
||
|
||
**目标**:支持多上下文分区管理,Agent 可在不同 slot 之间切换。
|
||
|
||
| Step | 内容 | 验证标准 |
|
||
|------|------|---------|
|
||
| **10.1** | `src/llm/context.rs`:`ContextSlot` + `SlotConfig` / `SlotMode` / `SlotSource` / `ContextBudget` 核心类型 | `cargo build` |
|
||
| **10.2** | ContextSlot 持久化:基于 `MemoryStore` trait(不绑定 SqliteStore)实现 save/load/list + slot 命名空间 key 策略 | 单元测试:slot 创建/写入/读取/隔离(不串数据) |
|
||
| **10.3** | `AgentSession` 扩展:`create_slot` / `switch_slot` / `list_slots` / `derive_slot` + `AgentBuilder` 默认创建 `"default"` slot | 集成测试 + 新示例 `context_slot_demo` |
|
||
|
||
**如何保证简单场景无感**:`AgentBuilder::build()` 内部检查,如果用户没手动 `create_slot`,自动创建 `"default"` slot → `submit_turn` 默认写到 default slot。
|
||
|
||
**依赖**:Phase 7(SqliteStore 作为推荐持久化后端;`MemoryStore` trait 即可)
|
||
**优先级**:P1
|
||
|
||
---
|
||
|
||
#### Phase 11: 测试与检索补强
|
||
|
||
**目标**:补全测试覆盖 + 语义检索抽象。
|
||
|
||
| Step | 内容 | 验证标准 |
|
||
|------|------|---------|
|
||
| **11.1** | `VectorRetriever` trait:`index(id, embeddings)` + `search(query, k)` | 编译 + mock 测试 |
|
||
| **11.2** | wiremock Provider roundtrip 测试:模拟 OpenAI/Anthropic HTTP 端点 | `cargo test` 新增 10+ roundtrip 测试 |
|
||
| **11.3** | 并发测试补强:InMemoryStore + SqliteStore 多线程写入验证 | 跑 100 轮无 race |
|
||
|
||
**依赖**:无(可随时做)
|
||
**优先级**:P1
|
||
|
||
---
|
||
|
||
#### Phase 12: P2 锦上添花(可选)
|
||
|
||
**目标**:时间允许时按优先级交付。
|
||
|
||
| 优先级 | 功能 | 实现量估计 | 备注 |
|
||
|--------|------|-----------|------|
|
||
| **12.1** | 文件系统 MemoryStore(JSON/JSONL) | ~80 行 | 最简单,适合练手 |
|
||
| **12.2** | MCP StreamableHttp 传输 | ~150 行 | 协议还在演进 |
|
||
| **12.3** | Gemini Provider | ~300 行 | 协议差异大,建议推迟到 v0.3 |
|
||
|
||
**依赖**:无(独立交付)
|
||
|
||
---
|
||
|
||
### v0.2.0 Phase 依赖关系图
|
||
|
||
```mermaid
|
||
graph BT
|
||
P5["<b>Phase 5: 热身准备</b><br/>ProviderConfig::from_env<br/>Ollama Provider<br/>#[non_exhaustive] 标记"]:::done
|
||
P6["<b>Phase 6: ToolDef IR</b><br/>Provider 无关工具定义"]:::done
|
||
P7["<b>Phase 7: SqliteStore</b><br/>rusqlite + WAL<br/>9 个内联测试<br/>持久化 round-trip"]:::done
|
||
P8["Phase 8<br/>MVP 出口 (rc.1)"]:::mvp
|
||
P9["Phase 9<br/>流式体验增强"]:::p1
|
||
P10["Phase 10<br/>ContextSlot"]:::p1
|
||
P11["Phase 11<br/>测试与检索"]:::p1
|
||
P12["Phase 12<br/>P2 锦上添花"]:::p2
|
||
|
||
P8 --> P5
|
||
P8 --> P6
|
||
P8 --> P7
|
||
|
||
P9 --> P6
|
||
|
||
P10 --> P7
|
||
P10 --> P8
|
||
|
||
P11 -.-> P7
|
||
|
||
classDef done fill:#4ade80,stroke:#16a34a,color:#1a1a1a
|
||
classDef warmup fill:#e2e8f0,stroke:#94a3b8
|
||
classDef core fill:#fbbf24,stroke:#d97706
|
||
classDef mvp fill:#4ade80,stroke:#16a34a
|
||
classDef p1 fill:#93c5fd,stroke:#2563eb
|
||
classDef p2 fill:#c4b5fd,stroke:#7c3aed
|
||
```
|
||
|
||
---
|
||
|
||
### 关键里程碑
|
||
|
||
| 里程碑 | Phase 完成条件 | 可验证指标 | 状态 |
|
||
|--------|---------------|-----------|------|
|
||
| **M1** | Phase 5 | 热身三项完成:`from_env()` 可用 / Ollama 类型存在 / `#[non_exhaustive]` 就位 | ✅ 2026-07-05 |
|
||
| **M2** | Phase 6 | `ToolDef` 全量切换,`cargo test --all-targets` 全绿 | ✅ 2026-07-05 |
|
||
| **M3** | Phase 7 | SqliteStore CRUD + 并发测试通过,进程重启数据不丢 | ✅ 2026-07-05 |
|
||
| **M4** | **Phase 8 (rc.1)** | P0 五项全部交付,`cargo run --example quick_start` 跑通 | ⏳ |
|
||
| **M5** | Phase 9 | `submit_turn_stream` 流式事件序列验证通过 | ⏳ |
|
||
| **M6** | Phase 10 | ContextSlot 创建/切换/派生集成测试通过 | ⏳ |
|
||
| **M7** | Phase 11 | wiremock + 并发测试补强,测试总量 200+ | ⏳ |
|
||
| **M8** | Phase 12(可选) | P2 功能按需交付 | ⏳ |
|
||
|
||
---
|
||
|
||
## v0.3+ 展望
|
||
|
||
### 已规划的功能
|
||
|
||
| 功能 | 说明 | 预计版本 |
|
||
|------|------|---------|
|
||
| ContextSlot 分支(fork/merge) | 在决策点 fork 出子上下文,分支独立演进,可合并/丢弃 | v0.3 |
|
||
| 摘要自动生成 | Hook 驱动,`OnTurnEnd` 自动将对话摘要写入 `SessionMemory`,`inject_summary` 消费端已在 v0.2 就绪 | v0.3 |
|
||
| 知识图谱 | 实体-关系图,`docs/note-knowledge-graph-design.md` 已记录设计 | v0.3+ |
|
||
| Multi-Agent 协同(Swarm) | 子 Agent 委派、并行子任务、结果聚合 | v0.4+ |
|
||
| 精确 tokenizer 计数 | 绑定具体模型的 tokenizer 计数,替代当前的字符估算 | v0.3+ |
|
||
| 血缘关系图遍历 | 以 `parent_id` 为基础,提供 slot 血缘链查询 | v0.3+ |
|
||
| Markdown 技能按需加载 | 兼容 `SKILL.md` 格式,按 prompt 上下文动态加载 | v0.3+ |
|
||
| TokenJuice 语义压缩 | 对工具结果做语义压缩而非字节截断 | v0.3+ |
|
||
| Human-in-the-loop 审批 | 高危工具执行前的异步审批回调 | v0.3+ |
|
||
| RL 轨迹导出 | ShareGPT 格式轨迹、Atropos 集成 | v0.4+ |
|
||
|
||
### 明确不做(agcore 范围外)
|
||
|
||
| 功能 | 原因 |
|
||
|------|------|
|
||
| TUI / 多平台 Gateway | 应用层职责(Feishu / Telegram / Discord 桥接) |
|
||
| 配置自动加载(config/figment) | 配置来源策略应由上游应用决定,agcore 不定义配置格式 |
|
||
| 提示词自动优化 | 属于智能层,不应内建于 core 库 |
|
||
|
||
---
|
||
|
||
## 风险与建议
|
||
|
||
1. **持久化依赖**:`rusqlite` + `bundled` 零外部依赖编译,但 SQLite 不适配所有场景(分布式/高并发写)。`MemoryStore` trait 的抽象层允许下游自行实现 Redis / PostgreSQL 后端
|
||
2. **ContextSlot 心智负担**:`ContextSlot` 引入了一等抽象的复杂度。建议通过 `AgentBuilder` 默认创建 `"default"` slot,让简单场景无感使用
|
||
3. **向量检索生态**:`VectorRetriever` trait-only 不绑定实现,需社区贡献或用户自行适配 pgvector / qdrant / lancedb
|
||
4. **Scope 蔓延**:agcore 定位为"支持库"而非"Agent 产品",始终以 trait + reference impl 为边界,业务循环留给上层
|
||
5. **API 稳定性**:v0.2 引入 `#[non_exhaustive]` 和 `#[deprecated]` 机制,但不承诺 SemVer 稳定——仍在快速迭代期
|
||
|
||
---
|
||
|
||
## 下一步行动
|
||
|
||
1. **Phase 8 启动**:MVP 集成出口(API 稳定性扫尾 + CHANGELOG v0.2 + Quick Start 示例 + 端到端示例),P0 五项收尾
|
||
2. **示例先行**:每完成一个 Phase 立即更新对应示例,验证通过后再合入
|
||
3. **里程碑追踪**:以 Phase 8(MVP 出口)为 v0.2.0-rc.1 节点,逐 Phase 验收
|
||
|
||
**已完成 / 进行中阶段**:
|
||
- ✅ Phase 0 Foundation — 全部交付物已完成
|
||
- ✅ Phase 1 Prompt Engineering — 全部交付物已完成
|
||
- ✅ Phase 2 Tool System — 全部交付物已完成
|
||
- ✅ Phase 3 Memory System — 全部交付物已完成
|
||
- ✅ Phase 4a Core Glue — 全部交付物已完成
|
||
- ✅ Phase 4b Task Execution — 全部交付物已完成
|
||
- ✅ Phase 4c Session Memory — 全部交付物已完成
|
||
- ✅ Phase 5 Warmup — ProviderConfig::from_env + OllamaProvider + `#[non_exhaustive]` 前置标记(ProviderType / StopReason / FinishReason / EvictionPolicy)
|
||
- ✅ Phase 6 ToolDefinition IR — `ToolDef` 新类型 + 双向 `From` 转换 + 别名彻底移除 + `#[allow(deprecated)]` 清理(cycle/registry/mcp/agent);Anthropic 零改动;roundtrip 测试覆盖
|
||
- ✅ Phase 7 SqliteStore — `rusqlite 0.32` + WAL 模式 + `Arc<Mutex<Connection>>` + `spawn_blocking`;`memory/store.rs` → `store/{in_memory,sqlite_store}.rs` 模块化;9 个内联测试覆盖 CRUD/upsert/过滤/10×10 并发/持久化 round-trip;`InMemoryStore ↔ SqliteStore` trait-box 互换兼容
|
||
- ✅ Provider IR 重构 — 统一类型系统 + OpenAI/Anthropic/DeepSeek/Qwen/Ollama 适配
|
||
- ✅ LlmCycle 简化 — IR 消息类型切换 + Phase 0 桥接层移除
|
||
- ✅ v0.1 Release — 技术债扫清、MockProvider 公开化、8 个离线示例(含 `simple_visit`)、README + 错误消息友好化、CHANGELOG 初始化
|
||
- 📋 **v0.2 规划细化完成** — 8 个增量 Phase(Phase 5-12),17 个可验证 Step,覆盖 P0-P2 全部 12 项功能 + ContextSlot
|
||
|
||
---
|
||
|
||
## v0.1 发布里程碑(2026-07-04)
|
||
|
||
**质量基线**:
|
||
|
||
| 指标 | 数值 |
|
||
|------|------|
|
||
| `cargo build --all-targets` | ✅ 通过 |
|
||
| `cargo test --all-targets` | ✅ **182 passed / 0 failed** |
|
||
| `cargo clippy --all-targets -- -D warnings` | ✅ 0 警告 |
|
||
| 离线示例(`cargo run --example`) | ✅ 7 个全部 exit 0 |
|
||
|
||
**关键交付**:
|
||
1. **Provider IR 重构** — 统一 `Message` / `ContentBlock` / `MessageRequest` / `MessageResponse` 类型层;4 个 Provider 适配(OpenAI Chat / Anthropic Messages / DeepSeek / Qwen);`LlmProvider` trait 签名同步切换
|
||
2. **LlmCycle 简化** — `LlmCycle` 内部消息类型切到 IR 层;移除 Phase 0 的 `OpenaiChatMessage ↔ Message` 桥接;测试从 116 → 182(含 provider 测试)
|
||
3. **`MockProvider` 公开化** — `agcore::llm::mock::MockProvider` 支持 `chat` + `chat_stream`,无需 API key 即可运行示例
|
||
4. **7 个离线示例** — `prompt_composer` / `custom_tool` / `agent_session_demo` / `task_agent_demo` / `conversation_memory_demo` / `knowledge_search_demo` / `streaming_events_demo`
|
||
5. **错误消息友好化** — `AgentError` / `LlmError` / `ToolError` / `MemoryError` / `PromptError` 全部面向最终用户改写(给出可操作的建议)
|
||
6. **文档完整** — README 完整版(快速上手 + 架构图 + 环境变量)、Apache-2.0 LICENSE
|