28ca43ccb2
将 note、pdd、prd、roadmap 四类文档分别归入 `design/` 下对应子目录中,并新增 `.gitkeep` 占位文件
425 lines
24 KiB
Markdown
425 lines
24 KiB
Markdown
# AG Core v0.3.2 Step 3(Phase 26–27)— 验证固化 + 文档更新实施方案
|
||
|
||
## 1. 背景与目标
|
||
|
||
**背景**:agcore v0.3.2 Step 1(Phase 20–25)已交付 —— Cargo features 拆分基础设施改造全部完成,所有模块 `#[cfg]` 门控注入完毕,依赖全部 optional 化,`default = ["full"]` 保持向后兼容。当前项目处于已改造完成但未经 CI 固化、无文档指引的状态。
|
||
|
||
**当前状态快照**:
|
||
- v0.3.0 → v0.3.2 Step 1:68 个源文件,23,765 行
|
||
- 16 个 features(10 模块级 + 5 provider + 1 工具)+ 4 个快捷组合
|
||
- `cargo test --features "full"`:427 passed
|
||
- 7 种 feature 组合的 `cargo test --lib` 已全部通过(full / light / chat / chat+mcp / multi / multi+mcp / clippy),无需修复 cfg 遗漏
|
||
- 但 `cargo test`(不带 `--lib`)会因 18 个 example 缺少 `required-features` 而失败
|
||
- 项目无 CI/CD 配置
|
||
|
||
**目标**:通过 Step 3 将 features 体系验证固化到 CI 中,消除编译死代码警告,完成文档指引,使 v0.3.2 达到可发布状态。
|
||
|
||
**预期效果**:
|
||
- 每次提交自动验证 7 种 feature 组合的编译 + 测试(零 warning)
|
||
- 18 个 example 各自标注准确的 `required-features`,外树用户可一键运行
|
||
- `cargo clippy --all-features -- -D warnings` 零告警
|
||
- README 含完整 feature 表 + `Cargo.toml` 配置示例 + 升级指南,新用户 5 分钟内可选定组合
|
||
- roadmap 同步更新
|
||
|
||
## 2. 需求分析
|
||
|
||
### 2.1 功能需求
|
||
|
||
| # | 需求 | 说明 | 对应工作 |
|
||
|---|------|------|---------|
|
||
| F1 | LlmProvider trait 不应依赖具体 provider feature | trait 自身不依赖 reqwest 或任何 provider 实现,纯 Mock 场景也应可用 | 工作 0 |
|
||
| F2 | 每个 example 通过 `cargo run --example xxx` 正确编译 | 18 个 example 各有精确的最小 features 声明 | 工作 1 |
|
||
| F3 | CI 自动验证 7 种特征组合的编译与测试 | push / PR 触发 | 工作 2 |
|
||
| F4 | 所有 feature 组合下 0 个编译器警告 | 消除 dead_code 等警告 | 工作 3 |
|
||
| F5 | README 提供完整的 feature 选择指引 | 表格 + 场景推荐 + Cargo.toml 示例 | 工作 5(Phase 27) |
|
||
| F6 | example 文件顶部标注所需 features | 用户可一键复制运行命令 | 工作 5(Phase 27) |
|
||
| F7 | roadmap 状态同步 | 总入口 + v0.3.2 子文档 | 工作 5(Phase 27) |
|
||
|
||
### 2.2 非功能需求
|
||
|
||
| # | 需求 | 指标 | 对应工作 |
|
||
|---|------|------|---------|
|
||
| N1 | 向后兼容 | `default = ["full"]` 行为与 v0.3.0 一致,427 tests passed | 全部 |
|
||
| N2 | CI 时效 | 全矩阵 ≤ 10 分钟 | 工作 2 |
|
||
| N3 | 最少侵入 | 不改动功能逻辑,仅 cfg / 配置 / 文档变更 | 全部 |
|
||
|
||
### 2.3 推演概要
|
||
|
||
**需求拆解**:从当前编译验证结果出发,发现三类待解决问题:
|
||
1. **架构归属问题**——`LlmProvider` trait 定义在 provider 模块门控下,语义上应归属 `llm` 基础设施。同时其返回类型 `ProviderCapabilities` / `ProviderFeatures` 也必须一并移出
|
||
2. **example 可编译性问题**——18 个 example 无 `required-features`,多组合下 `cargo test` 失败
|
||
3. **代码质量问题**——`session.rs` 中 `bundle()` 方法在 `chat` 组合下 dead_code
|
||
4. **工程缺失**——无 CI、README 无 features 说明、roadmap 未同步
|
||
|
||
**边界识别**:
|
||
- 工作 0 仅移动 trait 及关联类型定义,不改变公开 API 签名
|
||
- 工作 1 的 required-features 是最小集合,不添加冗余 feature
|
||
- 工作 2 的 CI 仅验证编译 + 单元测试,不包含集成测试
|
||
- 工作 5 的文档更新不涉及新的功能描述
|
||
|
||
**非目标声明**:
|
||
- 不新增 feature 组合(保持现有的 4 个快捷组合不变)
|
||
- 不重构 `ProviderConfig` / `ProviderType` / `create_provider()` 等 provider 模块创建逻辑(仅移出 trait 和元数据结构体)
|
||
- 不集成集成测试(CI 仅验证 `--lib` 单元测试 + example 编译验证)
|
||
- 不改动 `Cargo.toml` 的 `[dependencies]` 声明
|
||
- 不改变 `default = ["full"]` 的默认行为
|
||
|
||
### 2.4 需求映射矩阵
|
||
|
||
| 功能需求 | 非功能需求 | 对应工作 | 验收项 |
|
||
|---------|-----------|---------|-------|
|
||
| F1 + N1 + N3 | — | 工作 0 | A1, A2, A9 |
|
||
| F2 | — | 工作 1 | A10 |
|
||
| F3 | N2 | 工作 2 | A5, A11 |
|
||
| F4 | — | 工作 3 | A4 |
|
||
| F5 | N1 | 工作 5 | A6 |
|
||
| F6 | — | 工作 5 | A7 |
|
||
| F7 | — | 工作 5 | A8 |
|
||
| — | N3 | 全部 | A1 |
|
||
| — | R2 缓解 | 全部 | A10 |
|
||
|
||
## 3. 方案设计
|
||
|
||
### 3.1 总体架构调整
|
||
|
||
```
|
||
工作 0 — 架构修正(LlmProvider trait 及关联类型归属调整)
|
||
|
||
当前:
|
||
src/llm/provider.rs #[cfg(any(feature = "provider-openai", ...))]
|
||
├─ pub trait LlmProvider { ... }
|
||
├─ pub struct ProviderCapabilities { ... }
|
||
├─ pub struct ProviderFeatures { ... }
|
||
└─ pub fn capabilities(&self) -> ProviderCapabilities;
|
||
|
||
目标:
|
||
src/llm/provider_trait.rs #[cfg(feature = "llm")]
|
||
├─ pub trait LlmProvider { ... }
|
||
├─ pub struct ProviderCapabilities { ... }
|
||
├─ pub struct ProviderFeatures { ... }
|
||
└─ pub fn capabilities(&self) -> ProviderCapabilities;
|
||
src/llm/provider.rs #[cfg(any(feature = "provider-openai", ...))]
|
||
└─ 各 provider 实现 + ProviderConfig / ProviderType / create_provider()
|
||
src/llm.rs
|
||
└─ pub use provider_trait::{LlmProvider, ProviderCapabilities, ProviderFeatures};
|
||
|
||
影响文件(6 个源文件 + 1 个新建):
|
||
- src/llm.rs — 添加 mod provider_trait 声明 + pub use 重导出
|
||
- src/llm/provider_trait.rs — 新文件,trait + 关联类型定义移入
|
||
- src/llm/provider.rs — 移出 trait + 关联类型
|
||
- src/llm/provider/openai.rs — use super:: → use crate::llm::
|
||
- src/llm/provider/anthropic.rs — 同上
|
||
- src/llm/provider/ollama.rs — 同上
|
||
- src/llm/provider/openai_compat.rs — 同上(两个 import 合并)
|
||
```
|
||
|
||
### 3.2 各子项设计方案
|
||
|
||
#### 工作 0 — LlmProvider trait 归属修正
|
||
|
||
**设计方案**:
|
||
1. 在 `src/llm/` 下新建 `provider_trait.rs`,门控为 `#[cfg(feature = "llm")]`
|
||
2. 从 `src/llm/provider.rs` 中提取以下定义到新文件:
|
||
- `pub trait LlmProvider`(含关联方法 `chat` / `chat_stream` / `capabilities`)
|
||
- `pub struct ProviderCapabilities`(含字段 `features: ProviderFeatures`)
|
||
- `pub struct ProviderFeatures`(含 8 个功能开关字段)
|
||
3. `src/llm.rs` 中声明 `mod provider_trait;`,并 `pub use provider_trait::{LlmProvider, ProviderCapabilities, ProviderFeatures};`
|
||
4. `src/llm/provider.rs` 移除上述定义,保留 `ProviderConfig` / `ProviderType` / `create_provider()` 等运行时代码
|
||
5. 更新所有 import 路径(详见下方清单)
|
||
|
||
**Import 路径调整清单**:
|
||
|
||
现有写法 → 目标写法
|
||
|
||
| # | 文件 | 现有 import | 目标 import |
|
||
|---|------|------------|------------|
|
||
| 1 | `agent/builder.rs:16` | `use crate::llm::provider::LlmProvider;` | `use crate::llm::LlmProvider;` |
|
||
| 2 | `agent/builder.rs:135`(test) | `use crate::llm::provider::{LlmProvider, ProviderCapabilities, ProviderFeatures};` | `use crate::llm::{LlmProvider, ProviderCapabilities, ProviderFeatures};` |
|
||
| 3 | `agent/session.rs:35` | `use crate::llm::provider::LlmProvider;` | `use crate::llm::LlmProvider;` |
|
||
| 4 | `agent/runtime.rs:21` | `use crate::llm::provider::LlmProvider;` | `use crate::llm::LlmProvider;` |
|
||
| 5 | `llm/mock.rs:46` | `use crate::llm::provider::{LlmProvider, ProviderCapabilities, ProviderFeatures};` | `use crate::llm::{LlmProvider, ProviderCapabilities, ProviderFeatures};` |
|
||
| 6 | `llm/cycle.rs:22` | `use crate::llm::provider::LlmProvider;` | `use crate::llm::LlmProvider;` |
|
||
| 7 | `llm/cycle.rs:940,1401`(test) | `use crate::llm::provider::{ProviderCapabilities, ProviderFeatures};` | `use crate::llm::{ProviderCapabilities, ProviderFeatures};` |
|
||
| 8 | `llm/provider/openai.rs:24` | `use super::{LlmProvider, ProviderCapabilities, ProviderFeatures};` | `use crate::llm::{LlmProvider, ProviderCapabilities, ProviderFeatures};` |
|
||
| 9 | `llm/provider/anthropic.rs:21` | `use super::{LlmProvider, ProviderCapabilities, ProviderFeatures};` | `use crate::llm::{LlmProvider, ProviderCapabilities, ProviderFeatures};` |
|
||
| 10 | `llm/provider/ollama.rs:14` | `use super::{LlmProvider, ProviderCapabilities};` | `use crate::llm::{LlmProvider, ProviderCapabilities};` |
|
||
| 11 | `llm/provider/openai_compat.rs:18,21` | `use super::ProviderCapabilities;` + `use crate::llm::provider::LlmProvider;` | `use crate::llm::{LlmProvider, ProviderCapabilities};`(合并为一行) |
|
||
| 12 | `llm/provider/registry.rs:6` | `use crate::llm::provider::{LlmProvider, ProviderConfig, ProviderType, create_provider};` | `use crate::llm::LlmProvider;` + `use crate::llm::provider::{ProviderConfig, ProviderType, create_provider};`(拆分) |
|
||
|
||
**示例文件 import 调整**:
|
||
|
||
| # | 文件 | 现有 import | 目标 import |
|
||
|---|------|------------|------------|
|
||
| 13 | `examples/end_to_end.rs:21` | `use agcore::llm::provider::{create_provider, LlmProvider, ProviderConfig, ProviderType};` | `use agcore::llm::LlmProvider;` + `use agcore::llm::provider::{create_provider, ProviderConfig, ProviderType};` |
|
||
| 14 | `examples/context_slot_demo.rs:18` | `use agcore::llm::provider::LlmProvider;` | `use agcore::llm::LlmProvider;` |
|
||
| 15 | `examples/streaming_events_demo.rs:19` | `use agcore::llm::provider::LlmProvider;` | `use agcore::llm::LlmProvider;` |
|
||
| 16 | `examples/quick_start.rs:9` | `use agcore::llm::provider::LlmProvider;` | `use agcore::llm::LlmProvider;` |
|
||
|
||
**Breaking Change 声明**:
|
||
|
||
工作 0 是**非兼容性变更**,现有用户可能通过以下路径引用 `LlmProvider`:
|
||
|
||
| 旧路径(v0.3.0–v0.3.2 Step 1) | 新路径(v0.3.2 Step 3 后) |
|
||
|--------------------------------|---------------------------|
|
||
| `agcore::llm::provider::LlmProvider` | `agcore::llm::LlmProvider` |
|
||
| `agcore::llm::provider::ProviderCapabilities` | `agcore::llm::ProviderCapabilities` |
|
||
| `agcore::llm::provider::ProviderFeatures` | `agcore::llm::ProviderFeatures` |
|
||
|
||
**向后兼容方案(可选)**:在 `src/llm/provider.rs` 中添加 `#[cfg(feature = "llm")]` 门控的类型别名,让老路径仍然可用:
|
||
```rust
|
||
#[cfg(feature = "llm")]
|
||
pub use super::provider_trait::LlmProvider;
|
||
#[cfg(feature = "llm")]
|
||
pub use super::provider_trait::ProviderCapabilities;
|
||
#[cfg(feature = "llm")]
|
||
pub use super::provider_trait::ProviderFeatures;
|
||
```
|
||
**推荐**:用户应迁移到新路径 `agcore::llm::LlmProvider`,`provider` 模块仅保留 `ProviderConfig` / `ProviderType` / `create_provider()` 等创建逻辑。
|
||
|
||
**验证**:
|
||
- `cargo test --features "full"` 仍 427 passed
|
||
- `cargo test --no-default-features --features "llm,llm-types" --lib` 编译通过(无需任何 provider feature)
|
||
- 所有 12 个内部文件 + 4 个示例文件的 import 路径正确
|
||
|
||
#### 工作 1 — examples required-features 标注
|
||
|
||
**设计方案**:在 `Cargo.toml` 中为每个 example 添加 `[[example]]` + `required-features`,精确到最小 features 集合。
|
||
|
||
```
|
||
上下文 slot 示例(context_slot_demo):
|
||
工作 0 后仅需 ["agent"](修正前需 ["agent", "provider-openai"])
|
||
因为 agent 的测试无需真实 provider,mock 即可
|
||
|
||
推理不变的 example(simple_visit):
|
||
真正调用 LLM,需要 ["llm", "provider-openai", "tracing-init"]
|
||
```
|
||
|
||
完整映射关系见实施计划 §4.2。
|
||
|
||
#### 工作 2 — CI 配置
|
||
|
||
**设计方案**:GitHub Actions 矩阵策略,7 个并行测试 job + 1 clippy + 1 format + 1 example 验证。
|
||
|
||
| Job | Command | 作用域 |
|
||
|-----|---------|--------|
|
||
| full | `RUSTFLAGS="-D warnings" cargo test --features "full" --lib` | 全量回归,零警告 |
|
||
| light | `RUSTFLAGS="-D warnings" cargo test --no-default-features --features "light" --lib` | 生产常用,零警告 |
|
||
| chat | `RUSTFLAGS="-D warnings" cargo test --no-default-features --features "chat,provider-openai" --lib` | 纯对话,零警告 |
|
||
| chat+mcp | `RUSTFLAGS="-D warnings" cargo test --no-default-features --features "chat,provider-openai,tools-mcp" --lib` | 对话 + 工具,零警告 |
|
||
| multi | `RUSTFLAGS="-D warnings" cargo test --no-default-features --features "multi,provider-openai" --lib` | 多 Agent,零警告 |
|
||
| multi+mcp | `RUSTFLAGS="-D warnings" cargo test --no-default-features --features "multi,provider-openai,tools-mcp" --lib` | 多 Agent + 工具,零警告 |
|
||
| clippy | `cargo clippy --all-features --lib -- -D warnings` | lint 检查 |
|
||
| format | `cargo fmt --check`(stable toolchain) | 格式检查 |
|
||
| examples | `cargo test --features "full"`(不加 `--lib`,编译并运行所有 example) | example 编译验证 |
|
||
|
||
**关键决策**:
|
||
- 矩阵中统一使用 `--lib` 而非 `--all-targets`。理由:examples 的编译由 `required-features` 独立管理,若混入矩阵会因 feature 组合不匹配导致 example 编译失败,干扰模块测试结果验证。
|
||
- 使用 `RUSTFLAGS="-D warnings"` 将警告升级为编译错误,确保 `F4(0 编译器警告)`被矩阵中所有 6 个测试 job 强制执行。
|
||
- format job 使用 stable toolchain(`cargo fmt --check` 不需要 nightly)。
|
||
- 独立 `examples` job 使用 `cargo test --features "full"`(不加 `--lib`),验证所有 example 在完整 features 下编译并运行通过。
|
||
|
||
#### 工作 3 — bundle() 死代码警告修复
|
||
|
||
**设计方案**:在 `src/agent/session.rs:154` 的 `pub(crate) fn bundle()` 方法上添加 `#[cfg(feature = "engine")]` 条件编译。
|
||
|
||
背景:`bundle()` 仅被 `engine/session_manager.rs:219` 调用,当启用 `chat` 组合(agent 但非 engine)时产生 dead_code 警告。
|
||
|
||
**验证**:`cargo test --no-default-features --features "chat,provider-openai" --lib` 0 warnings。
|
||
|
||
#### 工作 4(可选)— 编译时间基线
|
||
|
||
记录但不沉淀到代码或 CI 中,仅供性能参考:
|
||
```bash
|
||
time cargo build --features "full"
|
||
time cargo build --no-default-features --features "light"
|
||
```
|
||
|
||
注:此工作在 v0.3.2 发布前为手动执行,不纳入 CI 或验收标准。若后续版本需要编译时间回归检测,可将其提升为正式工作项。
|
||
|
||
#### 工作 5 — 文档更新
|
||
|
||
三处并行更新:
|
||
|
||
**README.md 新增 features 表格**:
|
||
- 4 个快捷组合 + 推荐使用场景 + `Cargo.toml` 配置示例
|
||
- 下游用户可快速选择并复制配置
|
||
|
||
**升级指南章节(README.md 新增)**:
|
||
- 针对工作 0 的 Breaking Change 提供迁移说明
|
||
- 列出旧路径 → 新路径的对照表
|
||
- 提供向后兼容的重导出方案说明
|
||
- 示例:`agcore::llm::provider::LlmProvider` → `agcore::llm::LlmProvider`
|
||
- 提醒用户更新 `use` 声明
|
||
|
||
**example 文件顶部注释**:
|
||
- 每个 example 第一行格式:`// Required features: cargo run --example xxx --features "..."`
|
||
- 对应工作 1 的 `required-features` 声明
|
||
|
||
**roadmap 状态同步**:
|
||
- `docs/roadmap.md`:补充 Phase 26-27 完成状态 + v0.3.2 链接
|
||
- `docs/roadmap-v0.3.2.md`:Phase 26/27 状态从 ⏳ 改为 ✅ + 完成日期
|
||
|
||
### 3.3 ADR 记录
|
||
|
||
#### ADR-1:LlmProvider trait 及关联类型归属 llm 模块
|
||
|
||
| 字段 | 内容 |
|
||
|------|------|
|
||
| 问题 | `LlmProvider` trait 定义在 provider 模块门控 `any(provider-openai, provider-anthropic, ...)` 下,纯 Mock 场景被迫引入至少一个 provider feature。其返回类型 `ProviderCapabilities` / `ProviderFeatures` 同样被困在 provider 门控中 |
|
||
| 决策 | 将 trait 定义 + `ProviderCapabilities` / `ProviderFeatures` 一并提取到 `src/llm/provider_trait.rs`,归属 `#[cfg(feature = "llm")]` |
|
||
| 备选方案 | 保持不动,在 mock provider 上添加 cfg 绕过 — 否决,因为 provider 模块整体门控错误 |
|
||
| 理由 | trait 本身是个接口定义,不依赖 reqwest 或任何 provider 实现细节;`ProviderCapabilities` / `ProviderFeatures` 是 trait 方法的返回类型,必须与 trait 同门控 |
|
||
| 影响 | 修改 6 个源文件 + 1 个新建文件 + 4 个示例文件(详见 §3.2 import 调整清单) |
|
||
| 状态 | 已采纳 |
|
||
|
||
#### ADR-2:CI 使用 nightly toolchain
|
||
|
||
| 字段 | 内容 |
|
||
|------|------|
|
||
| 问题 | 项目已使用 edition 2024,是否降级到 2021 以使用 stable Rust |
|
||
| 决策 | 测试和 clippy 使用 nightly(edition 2024 目前要求 nightly);format 使用 stable |
|
||
| 备选方案 | 降级 edition 到 2021 — 否决,已迁移至 edition 2024 且编译通过 |
|
||
| 理由 | edtion 2024 是主动选择的方向,降级是倒退且涉及大量语法变更;`cargo fmt --check` 无需 nightly |
|
||
| 影响 | CI 依赖 `actions-rust-lang/setup-rust-toolchain@v1`;format job 指定 `toolchain: stable` |
|
||
| 状态 | 已采纳 |
|
||
|
||
#### ADR-3:CI 矩阵使用 `--lib` 而非 `--all-targets`
|
||
|
||
| 字段 | 内容 |
|
||
|------|------|
|
||
| 问题 | `cargo test --all-targets` 会编译所有 example,与矩阵中自选的 feature 组合可能冲突 |
|
||
| 决策 | 矩阵测试使用 `--lib`,examples 由独立 job(`cargo test --features "full"` 不加 `--lib`)验证 |
|
||
| 备选方案 | 在矩阵中也传入 `--all-targets` — 否决,example 编译失败会干扰模块测试验证 |
|
||
| 理由 | 分离关注点:矩阵验证模块级编译 + 零警告,独立 job 验证 example 编译 |
|
||
| 状态 | 已采纳 |
|
||
|
||
## 4. 实施计划
|
||
|
||
### 4.1 任务拆解与优先级
|
||
|
||
| 优先级 | 工作 | 编号 | 规模 | 依赖 |
|
||
|--------|------|------|------|------|
|
||
| P0 | LlmProvider trait 归属修正 | 工作 0 | ~30 行(含关联类型移动 + import 调整) | 无 |
|
||
| P0 | bundle() 门控修复 | 工作 3 | 1 行 | 无 |
|
||
| P0 | examples required-features | 工作 1 | ~50 行 | 工作 0(context_slot_demo / quick_start 最小 features 从 agent+provider-openai 降为 agent) |
|
||
| P0 | CI 配置 | 工作 2 | ~80 行 | 无 |
|
||
| P1 | 文档更新 | 工作 5 | ~150 行 | 全部 |
|
||
| P2 | 编译时间基线 | 工作 4 | 手动 | 全部 |
|
||
|
||
### 4.2 各 example 的 required-features 清单
|
||
|
||
| example 文件名 | required-features | 运行环境备注 |
|
||
|---------------|-------------------|------------|
|
||
| `prompt_composer` | `["prompt"]` | — |
|
||
| `custom_tool` | `["tools"]` | — |
|
||
| `conversation_memory_demo` | `["memory"]` | — |
|
||
| `knowledge_graph_demo` | `["memory"]` | — |
|
||
| `knowledge_search_demo` | `["memory"]` | — |
|
||
| `agent_session_demo` | `["agent"]` | — |
|
||
| `task_agent_demo` | `["agent"]` | — |
|
||
| `context_slot_demo` | `["agent"]` | 工作 0 后无需 provider |
|
||
| `quick_start` | `["agent"]` | 工作 0 后无需 provider |
|
||
| `simple_visit` | `["llm", "provider-openai", "tracing-init"]` | 需要 API key |
|
||
| `streaming_events_demo` | `["llm", "provider-openai"]` | 需要 API key |
|
||
| `agent_switch_demo` | `["engine"]` | — |
|
||
| `bridge_keys_demo` | `["engine"]` | — |
|
||
| `dispatch_stream_demo` | `["engine"]` | — |
|
||
| `engine_demo` | `["engine"]` | — |
|
||
| `sub_agent_dispatch_demo` | `["engine"]` | — |
|
||
| `document_demo` | `["memory", "tracing-init"]` | 需 sqlite 依赖(memory-sqlite feature 可选) |
|
||
| `end_to_end` | `["agent", "memory-sqlite", "provider-openai"]` | 需要 API key + sqlite 依赖 |
|
||
|
||
**验证策略**:每个 example 除 `--lib` 验证外,还需单独运行以下命令确认 required-features 精确性:
|
||
```bash
|
||
cargo test --no-default-features --features "<features>" --example <name>
|
||
```
|
||
|
||
### 4.3 Commit 策略
|
||
|
||
每个工作独立 commit,按依赖顺序排列:
|
||
|
||
| 顺序 | Scope | Type | 描述 | 依赖 |
|
||
|------|-------|------|------|------|
|
||
| 1 | `core` | `refactor` | 将 LlmProvider trait 及关联类型移出 provider 模块归属 llm | 无 |
|
||
| 2 | `agent` | `fix` | 为 session.rs bundle() 方法添加 engine feature 门控 | 无 |
|
||
| 3 | `examples` | `chore` | 为 18 个 example 添加 required-features 声明 | 工作 1(context_slot 等受益于工作 0 的轻量 features) |
|
||
| 4 | `ci` | `chore` | 创建 CI 测试矩阵配置 | 无 |
|
||
| 5 | `docs` | `docs` | 更新 README feature 表 + 升级指南 + 示例注释 + roadmap 状态 | 全部 |
|
||
|
||
### 4.4 参考实现:CI 配置
|
||
|
||
```yaml
|
||
name: CI
|
||
on: [push, pull_request]
|
||
env:
|
||
RUSTFLAGS: "-D warnings"
|
||
jobs:
|
||
test-matrix:
|
||
strategy:
|
||
matrix:
|
||
features:
|
||
- "full"
|
||
- "light"
|
||
- "chat,provider-openai"
|
||
- "chat,provider-openai,tools-mcp"
|
||
- "multi,provider-openai"
|
||
- "multi,provider-openai,tools-mcp"
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||
with:
|
||
toolchain: nightly
|
||
- run: cargo test --no-default-features --features "${{ matrix.features }}" --lib
|
||
clippy:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||
with:
|
||
toolchain: nightly
|
||
- run: cargo clippy --all-features --lib -- -D warnings
|
||
format:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||
with:
|
||
toolchain: stable
|
||
- run: cargo fmt --check
|
||
examples:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||
with:
|
||
toolchain: nightly
|
||
- run: cargo test --features "full"
|
||
```
|
||
|
||
## 5. 风险评估
|
||
|
||
| 风险 | 概率 | 影响 | 缓解措施 | 对应验收项 |
|
||
|------|------|------|---------|-----------|
|
||
| 工作 0 重构后公开 API 被意外改变 | 低 | 高 | 重构前后分别跑 `cargo test --features "full"` 确认测试数一致(427),且 `cargo doc` 无差异 | A1 |
|
||
| required-features 标注不准确导致 example 运行时缺少 trait 实现 | 低 | 中 | 每个 example 在 `--lib` 验证后,再单独跑 `cargo test --example xxx --no-default-features --features "对应features"` 确认 | A10 |
|
||
| CI 首次在 GitHub runner 上因环境差异(OS、Toolchain 版本)失败 | 中 | 低 | 非阻塞问题,修复后重新推送即可;本地已在 macOS 验证 7 种组合 | A5 |
|
||
| edition 2024 在 GitHub runner 的特定 nightly 版本上不稳定 | 低 | 中 | 可在 `Cargo.toml` 中加 `rust-version = "1.85"` 下限约束 | A5 |
|
||
| bundle() 门控修复后 engine 组合下方法不可见 | 极低 | 中 | `cargo test --features "engine,provider-openai"` 编译通过即可验证 | A4 |
|
||
|
||
## 6. 验收标准
|
||
|
||
| # | 验收项 | 验证方式 | 对应工作 |
|
||
|---|--------|---------|---------|
|
||
| A1 | `cargo test --features "full"` 仍 427 passed | `cargo test -F full -q` | 工作 0 |
|
||
| A2 | `cargo test --no-default-features --features "llm,llm-types" --lib` 编译通过 | 无需任何 provider feature 即完成编译 | 工作 0 |
|
||
| A3 | 7 种组合下 `cargo test --no-default-features --features "组合" --lib -q` 全部通过 | 逐一验证 | 工作 1(example features 正确不会干扰 --lib) |
|
||
| A4 | 6 个矩阵组合(full / light / chat / chat+mcp / multi / multi+mcp)下 `RUSTFLAGS="-D warnings" cargo test --lib` 0 warnings | 所有组合均无编译器警告 | 工作 3 |
|
||
| A5 | `.github/workflows/ci.yml` 文件存在,结构包含 9 个 job(6 测试 + 1 clippy + 1 format + 1 examples) | 文件检查 | 工作 2 |
|
||
| A6 | README.md 包含 features 表格 + 使用场景 + Cargo.toml 配置示例 + 升级指南 | review 通过 | 工作 5 |
|
||
| A7 | 所有 18 个 example 文件首行含 `// Required features: cargo run --example xxx --features "..."` 注释 | review 通过 | 工作 5 |
|
||
| A8 | `docs/roadmap.md` 和 `docs/roadmap-v0.3.2.md` 中 Phase 26/27 状态标记为 ✅ | review 通过 | 工作 5 |
|
||
| A9 | 工作 0 后 `cargo doc --no-deps --features "llm,llm-types"` 可生成 `LlmProvider` / `ProviderCapabilities` / `ProviderFeatures` 的 API 文档(无需任何 provider feature) | review 通过 | 工作 0 |
|
||
| A10 | 每个 example 单独验证:`cargo test --no-default-features --features "<对应features>" --example <name>` 编译通过 | 逐一验证 18 个 example | 工作 1 |
|
||
| A11 | 全矩阵 CI(6 测试 + clippy + format + examples)从 checkout 到完成 ≤ 10 分钟 | 实测计时 | 工作 2 |
|