docs: 质量优化重构总方案与任务级实施计划 v1
基于全面代码分析输出: - 质量优化重构总方案_v1.md:五维度总体方案 - 质量优化重构实施计划_任务级_v1.md:78个任务,10周详细安排 关键结果: - 新增模型提供商支持(腾讯云Coding Plan、百度文心、火山引擎、Cohere) - 四层架构设计 + EventBus 抽象 - CI lint/security/type 全线门禁 - 异常规范化 + 类型安全基线化 - God Object 拆分路线图 验收标准:Lint 0 错误、高危安全漏洞清零、启动时间 -50%、测试覆盖率 70%+
This commit is contained in:
878
plans/质量优化重构实施计划_任务级_v1.md
Normal file
878
plans/质量优化重构实施计划_任务级_v1.md
Normal file
@@ -0,0 +1,878 @@
|
||||
# Hermes Agent 立交桥项目 — 任务级详细实施计划 v1.0
|
||||
|
||||
> 基于《质量优化重构总方案_v1》确认后输出
|
||||
> 精度:任务级(每个任务可独立分配/跟踪/验收)
|
||||
> 总工期:10 周 | 总任务数:78 个
|
||||
|
||||
---
|
||||
|
||||
## 一、项目背景与目标
|
||||
|
||||
### 1.1 现状问题
|
||||
| 维度 | 关键病症 | 数量级影响 |
|
||||
|------|---------|-----------|
|
||||
| 代码质量 | Lint错误 / 类型错误 / 安全漏洞 | 1,717 + 2,383 + 26高危 |
|
||||
| 系统稳定 | God Object / 循环依赖 / 回调爆炸 | 4个 >10k行 / 5+循环 / 12+回调 |
|
||||
| 运维简捷 | 缺少CI门禁 / 日志无结构 / 配置体量大 | CI无lint/type检查 / 纯文本日志 / 3,882行配置 |
|
||||
| 性能 | 启动慢 / 内存无限增长 / 并发模型混乱 | 内联导入 / 消息无上限 / sync+async混用 |
|
||||
| 架构 | 无分层 / 插件偶合 / 技能复制粘贴 | hermes_cli作全局库 / 工具导入CLI插件 / memory插件重复 |
|
||||
| 模型生态 | 缺少国内主流厂商支持 | 缺少腾讯云Coding Plan / 百度文心 / 火山 / Cohere |
|
||||
|
||||
### 1.2 总体目标
|
||||
1. **代码质量**:Lint 0 错误,核心模块类型安全,高危安全漏洞清零
|
||||
2. **系统稳定**:单模块 < 1,500 行,循环依赖清零,回调收敛到 EventBus
|
||||
3. **运维简捷**:CI 全线通过(lint/type/sec/cov/complexity),JSON 日志,Pydantic 配置
|
||||
4. **性能优化**:启动时间 -50%,消息历史 Token 硬上限,并发模型统一
|
||||
5. **架构简洁**:四层架构落地,插件正交,技能抽象
|
||||
6. **模型生态**:新增腾讯云Coding Plan / 百度文心 / 火山引擎 / Cohere 等主流厂商
|
||||
|
||||
---
|
||||
|
||||
## 二、总体里程碑
|
||||
|
||||
```
|
||||
M1 基线治理期 第1-3周 安全零 + Lint零 + 测试绿通 + CI门禁 + 类型基线化 + core/包创建
|
||||
M2 引擎重构期 第4-6周 God Object 拆分 + 循环依赖清理 + EventBus + 导入优化
|
||||
M3 架构收尾期 第7-9周 Plugin正交 + Skill抽象 + 可观测性 + 配置简化 + 模型生态扩展
|
||||
M4 验收回归期 第10周 全量回归测试 + 性能基准 + 文档补全
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、任务级详细计划
|
||||
|
||||
### 第 1 周:安全清零 + Ruff 修复 + 测试绿通
|
||||
|
||||
#### W1-T1 修复 shell=True 注入漏洞
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 安全修复 PR
|
||||
- **验收标准**:
|
||||
- `tui_gateway/server.py:2267,3078` 改 `shlex.split` + `shell=False`
|
||||
- `cli.py:6077` 同上
|
||||
- `tools/skills_hub.py` 5处修复
|
||||
- `tools/environments/docker.py:541,560` 修复
|
||||
- `tools/transcription_tools.py:355` 修复
|
||||
- `bandit -r . -lll` 无 B602 高危
|
||||
- **风险点**: `skills_hub.py` 命令拼接逻辑复杂,需逐行 review
|
||||
- **工时**: 1d
|
||||
|
||||
#### W1-T2 修复弱哈希使用
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 安全修复 PR
|
||||
- **验收标准**:
|
||||
- `agent/codex_responses_adapter.py:171` `hashlib.sha1(usedforsecurity=False)`
|
||||
- `agent/context_compressor.py:466` `hashlib.md5(usedforsecurity=False)`
|
||||
- `gateway/platforms/weixin.py:1787` 同上
|
||||
- `bandit -r . -lll` 无 B324 高危
|
||||
- **风险点**: 微信平台使用 SHA1 为协议约定,需确认 `usedforsecurity=False` 不破坏签名验证
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W1-T3 修复 urlopen 和 trust_remote_code 风险
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 安全修复 PR
|
||||
- **验收标准**:
|
||||
- `agent/anthropic_adapter.py:487,795` 增加 scheme 白名单校验
|
||||
- `trajectory_compressor.py:366` 固定 revision + 校验哈希
|
||||
- `bandit -r . -lll` 无 B310/B615 高危
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W1-T4 Ruff 全线自动修复
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 代码风格统一 PR
|
||||
- **验收标准**:
|
||||
- `ruff check --fix` 全部执行,1,031 自动修复应清零
|
||||
- 剩余 686 处分批人工 review,先处理 F401/F841/F541
|
||||
- CI 新增 `ruff check` 门禁步骤
|
||||
- `ruff check` 通过 = 0 errors
|
||||
- **风险点**: 大规模修复导致 merge conflict,需一次性执行后立即合并,通知全员 rebase
|
||||
- **工时**: 1d
|
||||
|
||||
#### W1-T5 修复硬失败测试
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 测试修复 PR
|
||||
- **验收标准**:
|
||||
- `tests/agent/test_model_metadata_local_ctx.py::test_passes_bearer_token_to_probe_requests` PASS
|
||||
- `tests/agent/test_credential_pool.py::test_load_pool_seeds_qwen_oauth_via_cli_tokens` PASS
|
||||
- `tests/agent/test_credential_pool.py::test_load_pool_seeds_copilot_via_gh_auth_token` PASS
|
||||
- `tests/agent/test_insights.py::TestGatewayFormatting::test_gateway_format_hides_cost` PASS
|
||||
- `scripts/run_tests.sh` 全通过
|
||||
- **风险点**: credential_pool 测试可能涉及 OAuth token 模拟逻辑,需确认是模拟缺陷还是业务回归
|
||||
- **工时**: 1d
|
||||
|
||||
#### W1-T6 清理测试中的未使用导入/变量
|
||||
- **输入依赖**: W1-T4 完成
|
||||
- **输出产物**: 测试清洁 PR
|
||||
- **验收标准**:
|
||||
- `tests/` 下 F401/F841 清零
|
||||
- 注册 `pytest.mark.ssh` 等自定义 mark 到 `pyproject.toml`
|
||||
- **工时**: 0.5d
|
||||
|
||||
---
|
||||
|
||||
### 第 2 周:core/ 包创建 + hermes_cli 解耦启动 + CI 增强
|
||||
|
||||
#### W2-T1 新建 `core/` 包结构
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: `core/` 目录 + `__init__.py`
|
||||
- **验收标准**:
|
||||
- 创建目录结构:`core/config.py`, `core/paths.py`, `core/models.py`, `core/auth/__init__.py`
|
||||
- `core/__init__.py` 仅暴露安全 API,不导入重型模块
|
||||
- `core/` 不依赖任何其他内部包
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W2-T2 将 `hermes_cli/config.py` 中无 UI 依赖函数迁移至 `core/config.py`
|
||||
- **输入依赖**: W2-T1
|
||||
- **输出产物**: `core/config.py` + 迁移 PR
|
||||
- **验收标准**:
|
||||
- 迁移:`load_config()`, `save_config()`, `get_hermes_home()`, `display_hermes_home()`, `_apply_profile_override()`
|
||||
- 保留 `hermes_cli/config.py` 为 re-export facade(向后兼容 1 版本)
|
||||
- `core/config.py` 单元测试 PASS
|
||||
- `tests/hermes_cli/test_profiles.py` PASS
|
||||
- **风险点**: 迁移过程中可能丢失配置版本迁移逻辑,需对比原文件 3,882 行逐行审计
|
||||
- **工时**: 2d
|
||||
|
||||
#### W2-T3 将 `hermes_cli/auth.py` 中通用认证逻辑迁移至 `core/auth/`
|
||||
- **输入依赖**: W2-T1
|
||||
- **输出产物**: `core/auth/tokens.py`, `core/auth/oauth.py`, `core/auth/providers/` + 迁移 PR
|
||||
- **验收标准**:
|
||||
- 迁移:API key 解析、token 刷新、加密存储
|
||||
- 各 provider OAuth 流程保留在 `hermes_cli/auth.py`(因涉及 CLI 交互)
|
||||
- `hermes_cli/auth.py` 保留 facade
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W2-T4 更新所有 `from hermes_cli.config import ...` 为 `from core.config import ...`
|
||||
- **输入依赖**: W2-T2
|
||||
- **输出产物**: 全局导入修复 PR
|
||||
- **验收标准**:
|
||||
- `agent/`, `tools/`, `gateway/`, `tui_gateway/` 中所有 `from hermes_cli.config import` 替换
|
||||
- `ruff check` PASS
|
||||
- `pytest` 全通过
|
||||
- **风险点**: 可能导致插件第三方远程 import 失败,需留兼容 shim
|
||||
- **工时**: 1d
|
||||
|
||||
#### W2-T5 更新所有 `from hermes_cli.auth import ...` 非 UI 依赖
|
||||
- **输入依赖**: W2-T3, W2-T4
|
||||
- **输出产物**: 全局导入修复 PR
|
||||
- **验收标准**:
|
||||
- 非交互类认证导入替换为 `from core.auth import`
|
||||
- `ruff check` PASS
|
||||
- `pytest` 全通过
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W2-T6 CI 增强:新增 lint 和 security 门禁
|
||||
- **输入依赖**: W1-T1~T4 完成
|
||||
- **输出产物**: `.github/workflows/tests.yml` 升级 PR
|
||||
- **验收标准**:
|
||||
- CI 新增 `ruff check` 步骤(门禁)
|
||||
- CI 新增 `bandit -r agent/ tools/ gateway/ -lll` 步骤(门禁)
|
||||
- CI 新增 `xenon --max-absolute B` 步骤(门禁,先开启不阻断)
|
||||
- `uv pip install` 改为矩阵安装(core / dev / messaging 分层)
|
||||
- CI 增加 `~/.cache/uv` 缓存
|
||||
- **工时**: 1d
|
||||
|
||||
#### W2-T7 CI 增强:新增测试覆盖率报告
|
||||
- **输入依赖**: W2-T6
|
||||
- **输出产物**: CI 升级 PR
|
||||
- **验收标准**:
|
||||
- CI 新增 `pytest --cov=agent --cov=tools --cov=gateway --cov-report=xml`
|
||||
- 集成 codecov 或 PR comment 中显示覆盖率变化
|
||||
- **工时**: 0.5d
|
||||
|
||||
---
|
||||
|
||||
### 第 3 周:类型安全基线化 + 异常规范 + 死代码清理
|
||||
|
||||
#### W3-T1 安装缺失 stub 包
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 依赖增加 PR
|
||||
- **验收标准**:
|
||||
- 安装 `types-PyYAML`, `types-requests`
|
||||
- `mypy agent/ tools/registry.py` 中 `import-untyped` 错误清零
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W3-T2 治理隐式 Optional(核心模块)
|
||||
- **输入依赖**: W3-T1
|
||||
- **输出产物**: 类型修复 PR
|
||||
- **验收标准**:
|
||||
- 修复 `agent/context_engine.py:73`, `tools/file_operations.py:330`, `agent/trajectory.py:31`, `tools/checkpoint_manager.py:453`, `hermes_state.py:138`
|
||||
- 统一使用 `Optional[T]` 或 `T | None` 语法
|
||||
- `mypy --strict agent/` 不报隐式 Optional 错误
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W3-T3 治理 Union-attr 和 incompatible assignment
|
||||
- **输入依赖**: W3-T2
|
||||
- **输出产物**: 类型修复 PR
|
||||
- **验收标准**:
|
||||
- 修复 `agent/copilot_acp_client.py:389` 等 Union-attr 错误
|
||||
- 修复 `tools/file_operations.py:169-216` incompatible assignment
|
||||
- `mypy --strict agent/ tools/registry.py` 不报 union-attr
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W3-T4 异常处理规范化(第一批)
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 异常规范化 PR
|
||||
- **验收标准**:
|
||||
- 高优先级模块 `tui_gateway/server.py`, `agent/auxiliary_client.py`, `tools/voice_mode.py` 中的裸 except 治理
|
||||
- 每个 except 块必须携带 `logger.warning/error`
|
||||
- 禁止空 `pass`
|
||||
- `bandit -r .` 中 B110 数量显著下降
|
||||
- **工时**: 1d
|
||||
|
||||
#### W3-T5 死代码清理(Vulture 结果)
|
||||
- **输入依赖**: W1-T4
|
||||
- **输出产物**: 死代码清理 PR
|
||||
- **验收标准**:
|
||||
- 移除 `acp_adapter/server.py:314` `client_capabilities` 等未使用变量
|
||||
- 移除 `agent/display.py:795` 未使用异常变量
|
||||
- 移除 `gateway/platforms/slack.py` 4 处未使用 `say`
|
||||
- `ruff check` PASS
|
||||
- `pytest` 全通过
|
||||
- **风险点**: 部分 "未使用"变量可能是用于调试的,需人工确认
|
||||
- **工时**: 1d
|
||||
|
||||
#### W3-T6 异常规范化(第二批,全局)
|
||||
- **输入依赖**: W3-T4
|
||||
- **输出产物**: 异常规范化 PR
|
||||
- **验收标准**:
|
||||
- 全局 1,244 处 `except Exception: pass` → 明确异常类型
|
||||
- 不能确定的场景使用 `except Exception as e: logger.warning(...)`
|
||||
- `bandit -r .` B110 计数 = 0(生产代码)
|
||||
- **工时**: 2d
|
||||
|
||||
---
|
||||
|
||||
### 第 4 周:run_agent.py 拆分 + 导入优化 + TurnEngine 初始化
|
||||
|
||||
#### W4-T1 设计 `agent/loop/` 包结构
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 设计文档 / ADR
|
||||
- **验收标准**:
|
||||
- 定义 `agent/loop/` 目录:`turn_engine.py`, `streaming.py`, `compression.py`, `retry_policy.py`, `checkpointing.py`
|
||||
- 定义模块界面,确保无循环依赖
|
||||
- 保留 `run_agent.py` facade 设计(`__getattr__` 延迟导入)
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W4-T2 实现 `agent/loop/turn_engine.py`
|
||||
- **输入依赖**: W4-T1
|
||||
- **输出产物**: `agent/loop/turn_engine.py` + 单元测试
|
||||
- **验收标准**:
|
||||
- 从 `run_agent.py` 抽取对话引擎核心(API 调用、工具执行、消息管理)
|
||||
- 支持 sync 模式,预留 async 接口
|
||||
- 单元测试覆盖率 ≥ 80%
|
||||
- `pytest` 全通过
|
||||
- **风险点**: `run_conversation` 逻辑复杂,抽取时可能遗漏 edge case
|
||||
- **工时**: 2d
|
||||
|
||||
#### W4-T3 实现 `agent/loop/streaming.py` 和 `compression.py`
|
||||
- **输入依赖**: W4-T2
|
||||
- **输出产物**: 两个模块 + 单元测试
|
||||
- **验收标准**:
|
||||
- `streaming.py`: 管理 SSE/stream 解析、delta 分发
|
||||
- `compression.py`: 抽象 `ContextCompressor`,支持增量压缩策略
|
||||
- 单元测试覆盖率 ≥ 80%
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W4-T4 实现 `agent/loop/retry_policy.py` 和 `checkpointing.py`
|
||||
- **输入依赖**: W4-T2
|
||||
- **输出产物**: 两个模块 + 单元测试
|
||||
- **验收标准**:
|
||||
- `retry_policy.py`: 抽象 `RetryPolicy` dataclass,统一重试逻辑
|
||||
- `checkpointing.py`: 抽象检查点管理,支持 SQLite 归档
|
||||
- 单元测试覆盖率 ≥ 80%
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W4-T5 `run_agent.py` 改为 facade 并近似保留原 API
|
||||
- **输入依赖**: W4-T2~T4
|
||||
- **输出产物**: `run_agent.py` 重构 PR
|
||||
- **验收标准**:
|
||||
- `run_agent.py` 保留 `AIAgent` 类名和 `__init__` / `chat` / `run_conversation` 签名
|
||||
- 内部实现转发到 `agent/loop/`
|
||||
- `pytest tests/agent/` 全通过
|
||||
- `ruff check` PASS
|
||||
- **风险点**: facade 可能引入过渡层性能损耗,需基准测试
|
||||
- **工时**: 1d
|
||||
|
||||
#### W4-T6 导入优化:工具注册懒加载
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 懒加载 PR
|
||||
- **验收标准**:
|
||||
- `tools/*.py` 中顶层 `registry.register()` 改为延迟注册(首次调用时才执行网络/文件检查)
|
||||
- 冷启动时间基准:`time python -c "import run_agent"` 记录当前值
|
||||
- 目标:启动时间减少 ≥ 30%
|
||||
- **工时**: 1d
|
||||
|
||||
#### W4-T7 `__init__.py` 减负
|
||||
- **输入依赖**: W4-T6
|
||||
- **输出产物**: `__init__.py` 优化 PR
|
||||
- **验收标准**:
|
||||
- 所有 `__init__.py` 中禁止导入重型模块(`run_agent`, `cli`, `model_tools`)
|
||||
- `time python -c "import run_agent"` 启动时间减少 ≥ 50%
|
||||
- **工时**: 0.5d
|
||||
|
||||
---
|
||||
|
||||
### 第 5 周:gateway/run.py 拆分 + 循环依赖清理 + 消息历史优化
|
||||
|
||||
#### W5-T1 设计 `gateway/` 拆分结构
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 设计文档
|
||||
- **验收标准**:
|
||||
- 定义 `gateway/lifecycle.py`, `gateway/delivery_router.py`, `gateway/platform_coordinator.py`, `gateway/voice_manager.py`
|
||||
- 保留 `gateway/run.py` facade
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W5-T2 实现 `gateway/lifecycle.py`
|
||||
- **输入依赖**: W5-T1
|
||||
- **输出产物**: `gateway/lifecycle.py` + 测试
|
||||
- **验收标准**:
|
||||
- 管理 Gateway 启动/停止/重启/配置加载
|
||||
- 单元测试覆盖率 ≥ 70%
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W5-T3 实现 `gateway/delivery_router.py` 和 `platform_coordinator.py`
|
||||
- **输入依赖**: W5-T2
|
||||
- **输出产物**: 两个模块 + 测试
|
||||
- **验收标准**:
|
||||
- `delivery_router.py`: 消息路由、会话匹配、重试逻辑
|
||||
- `platform_coordinator.py`: 多平台适配器管理
|
||||
- 单元测试覆盖率 ≥ 70%
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W5-T4 实现 `gateway/voice_manager.py`
|
||||
- **输入依赖**: W5-T2
|
||||
- **输出产物**: `gateway/voice_manager.py` + 测试
|
||||
- **验收标准**:
|
||||
- 管理语音模式、TTS/STT 生命周期
|
||||
- 单元测试覆盖率 ≥ 70%
|
||||
- **工时**: 1d
|
||||
|
||||
#### W5-T5 `gateway/run.py` 改为 facade
|
||||
- **输入依赖**: W5-T2~T4
|
||||
- **输出产物**: `gateway/run.py` 重构 PR
|
||||
- **验收标准**:
|
||||
- 保留 `GatewayRunner` 类名和核心方法签名
|
||||
- 内部转发到各子模块
|
||||
- `pytest tests/gateway/` 全通过
|
||||
- **工时**: 1d
|
||||
|
||||
#### W5-T6 消息历史 Token 硬上限 + SQLite 归档
|
||||
- **输入依赖**: W4-T2
|
||||
- **输出产物**: `agent/loop/context_manager.py` + 测试
|
||||
- **验收标准**:
|
||||
- 实现 `TokenBudget` 类,硬上限默认 128k tokens(可配置)
|
||||
- 超限消息自动归档到 SQLite(`hermes_state.py` 扩展)
|
||||
- 归档后支持检索(`/resume` 命令不受影响)
|
||||
- 测试覆盖率 ≥ 80%
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W5-T7 循环依赖清理(余留)
|
||||
- **输入依赖**: W2-T4, W2-T5, W4-T5, W5-T5
|
||||
- **输出产物**: 循环依赖解决 PR
|
||||
- **验收标准**:
|
||||
- `pydeps agent/ tools/ gateway/ hermes_cli/ tui_gateway/` 无包级循环
|
||||
- 所有 `from hermes_cli.config import` 在非 CLI 代码中清零
|
||||
- `pytest` 全通过
|
||||
- **风险点**: 部分循环依赖可能需要更多中间层抽象
|
||||
- **工时**: 1.5d
|
||||
|
||||
---
|
||||
|
||||
### 第 6 周:cli.py 拆分 + AgentEventBus + 回调收敛
|
||||
|
||||
#### W6-T1 设计 `AgentEventBus` / `AgentObserver`
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: ADR
|
||||
- **验收标准**:
|
||||
- 定义 Protocol:`AgentObserver`
|
||||
- 定义 `AgentEventBus` 类,支持多观察者注册/取消/事件分发
|
||||
- 定义事件类型:`ToolStartEvent`, `ToolProgressEvent`, `StreamDeltaEvent`, `ClarifyEvent`, ...
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W6-T2 实现 `AgentEventBus`
|
||||
- **输入依赖**: W6-T1
|
||||
- **输出产物**: `agent/event_bus.py` + 测试
|
||||
- **验收标准**:
|
||||
- 实现同步/异步事件分发
|
||||
- 单元测试覆盖率 ≥ 90%
|
||||
- **工时**: 1d
|
||||
|
||||
#### W6-T3 将 `AIAgent` 12+ 回调改为 EventBus 模式
|
||||
- **输入依赖**: W6-T2, W4-T5
|
||||
- **输出产物**: 回调收敛 PR
|
||||
- **验收标准**:
|
||||
- `AIAgent.__init__` 从 50+ 参数 → `AgentConfig` + `AgentObserver` 参数
|
||||
- `tool_progress_callback`, `thinking_callback`, `reasoning_callback` 等收敛为单一 `observer: AgentObserver`
|
||||
- 保持向后兼容(旧回调参数映射为内部适配器)
|
||||
- `pytest tests/agent/` 全通过
|
||||
- **风险点**: 回调变化影响所有前端(CLI/TUI/Gateway),需逐一测试
|
||||
- **工时**: 2d
|
||||
|
||||
#### W6-T4 设计 `cli/` 拆分结构
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 设计文档
|
||||
- **验收标准**:
|
||||
- 定义 `cli/display_engine.py`, `cli/stream_renderer.py`, `cli/input_handler.py`, `cli/layout_manager.py`
|
||||
- 保留 `cli.py` facade
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W6-T5 实现 `cli/display_engine.py` 和 `stream_renderer.py`
|
||||
- **输入依赖**: W6-T4
|
||||
- **输出产物**: 两个模块 + 测试
|
||||
- **验收标准**:
|
||||
- `display_engine.py`: KawaiiSpinner、Rich 面板、品牌渲染
|
||||
- `stream_renderer.py`: 流式输出、该理解笔、思考标签处理
|
||||
- 单元测试覆盖率 ≥ 70%
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W6-T6 实现 `cli/input_handler.py` 和 `layout_manager.py`
|
||||
- **输入依赖**: W6-T5
|
||||
- **输出产物**: 两个模块 + 测试
|
||||
- **验收标准**:
|
||||
- `input_handler.py`: 文件托拽、图片处理、输入历史
|
||||
- `layout_manager.py`: TUI 布局、分隔符、窗口管理
|
||||
- 单元测试覆盖率 ≥ 70%
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W6-T7 `cli.py` 改为 facade
|
||||
- **输入依赖**: W6-T5, W6-T6
|
||||
- **输出产物**: `cli.py` 重构 PR
|
||||
- **验收标准**:
|
||||
- 保留 `HermesCLI` 类名和核心方法
|
||||
- 内部转发到 `cli/` 子模块
|
||||
- `pytest` 全通过
|
||||
- **工时**: 1d
|
||||
|
||||
---
|
||||
|
||||
### 第 7 周:可观测性 + 配置 Pydantic 化 + hermes_cli/main.py 拆分
|
||||
|
||||
#### W7-T1 结构化日志(JSON 模式)
|
||||
- **输入依赖**: W2-T2
|
||||
- **输出产物**: `hermes_logging.py` 升级 PR
|
||||
- **验收标准**:
|
||||
- `hermes_logging.py` 支持 `HERMES_LOG_FORMAT=json` 环境变量
|
||||
- JSON 日志字段包含:timestamp, level, logger, message, task_id, duration_ms
|
||||
- 默认保持文本模式(向后兼容)
|
||||
- `pytest` 全通过
|
||||
- **工时**: 1d
|
||||
|
||||
#### W7-T2 指标埋点
|
||||
- **输入依赖**: W4-T2
|
||||
- **输出产物**: `agent/metrics.py` + 测试
|
||||
- **验收标准**:
|
||||
- 实现 `hermes_turn_latency_seconds` 计数器
|
||||
- 实现 `hermes_tool_errors_total` 计数器
|
||||
- 实现 `hermes_api_calls_total` 计数器
|
||||
- 支持定时将指标写入文件(`/tmp/hermes_metrics.prom`)
|
||||
- 测试覆盖率 ≥ 80%
|
||||
- **工时**: 1d
|
||||
|
||||
#### W7-T3 Gateway `/health` 和 `/ready` 端点
|
||||
- **输入依赖**: W5-T2
|
||||
- **输出产物**: 健康检查 PR
|
||||
- **验收标准**:
|
||||
- Gateway API 模式时增加 `/health`(基础健康)和 `/ready`(依赖就绪)
|
||||
- `/ready` 检查 AI provider 连通性、数据库连接
|
||||
- `pytest tests/gateway/` 通过
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W7-T4 配置 Pydantic 化
|
||||
- **输入依赖**: W2-T2
|
||||
- **输出产物**: `core/config_models.py` + 测试
|
||||
- **验收标准**:
|
||||
- 将 `DEFAULT_CONFIG` 和配置校验逻辑迁移为 Pydantic Settings 模型
|
||||
- 支持环境变量自动映射
|
||||
- 支持配置热重载(SIGHUP 或文件监视)
|
||||
- 配置版本迁移逻辑保留
|
||||
- 测试覆盖率 ≥ 80%
|
||||
- **风险点**: Pydantic 化可能引入新的默认值差异,需对比原逻辑
|
||||
- **工时**: 2d
|
||||
|
||||
#### W7-T5 `hermes_cli/main.py` 拆分
|
||||
- **输入依赖**: W6-T7, W7-T4
|
||||
- **输出产物**: `hermes_cli/commands/` 目录 + facade PR
|
||||
- **验收标准**:
|
||||
- 创建 `hermes_cli/commands/chat.py`, `commands/gateway.py`, `commands/setup.py`, `commands/profile.py`
|
||||
- `hermes_cli/main.py` 保留 facade(向后兼容)
|
||||
- 每个新模块 < 1,500 行
|
||||
- `pytest tests/hermes_cli/` 全通过
|
||||
- **工时**: 2d
|
||||
|
||||
---
|
||||
|
||||
### 第 8 周:Plugin 正交化 + Skill 抽象 + 模型生态扩展
|
||||
|
||||
#### W8-T1 提取 `PluginHost` Protocol 到 `agent/`
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: `agent/plugin_host.py` + ADR
|
||||
- **验收标准**:
|
||||
- 定义 `PluginHost` Protocol(`on_session_start`, `on_tool_call`, `on_response` 等 hook)
|
||||
- 定义 `HookLifecycleManager` 类,统一调度 hook 执行
|
||||
- 不依赖 `hermes_cli`
|
||||
- **工时**: 1d
|
||||
|
||||
#### W8-T2 `hermes_cli/plugins.py` 实现 `PluginHost` Protocol
|
||||
- **输入依赖**: W8-T1
|
||||
- **输出产物**: `hermes_cli/plugins.py` 改造 PR
|
||||
- **验收标准**:
|
||||
- `hermes_cli/plugins.py` 实现 `PluginHost` Protocol
|
||||
- `invoke_hook()` 改为 `HookLifecycleManager.dispatch()`
|
||||
- `pytest` 全通过
|
||||
- **工时**: 1d
|
||||
|
||||
#### W8-T3 `tools/` 解耦 `hermes_cli.plugins`
|
||||
- **输入依赖**: W8-T2
|
||||
- **输出产物**: 解耦 PR
|
||||
- **验收标准**:
|
||||
- `tools/skills_tool.py` 中 `from hermes_cli.plugins import invoke_hook` → `from agent.plugin_host import HookLifecycleManager`
|
||||
- `tools/terminal_tool.py` 同理
|
||||
- `ruff check` PASS
|
||||
- `pytest` 全通过
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W8-T4 抽象 `BaseMemoryPlugin`
|
||||
- **输入依赖**: W8-T1
|
||||
- **输出产物**: `plugins/base_memory.py` + 改造 PR
|
||||
- **验收标准**:
|
||||
- 定义 `BaseMemoryPlugin` ABC(`store()`, `retrieve()`, `delete()`)
|
||||
- 将 `plugins/memory/*` 下的复制粘贴模式改为继承 `BaseMemoryPlugin`
|
||||
- 每个 memory backend 模块 < 300 行
|
||||
- `pytest` 全通过
|
||||
- **工时**: 1d
|
||||
|
||||
#### W8-T5 模型生态扩展:腾讯云 Coding Plan 支持
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 模型支持 PR
|
||||
- **验收标准**:
|
||||
- 新增 ProviderEntry:`ProviderEntry("tencent-coding", "Tencent Cloud Coding Plan", "Tencent Cloud Coding Plan (hunyuan models — coding plan API)")`
|
||||
- 新增 HERMES_OVERLAY:`"tencent-coding": HermesOverlay(transport="openai_chat", base_url_env_var="TENCENT_CODING_BASE_URL")`
|
||||
- 新增 aliases:`tencent`, `coding-plan`, `codingplan` → `tencent-coding`
|
||||
- 新增环境变量:`TENCENT_CODING_API_KEY` 到 `.env.example`
|
||||
- 新增默认模型列表:`tencent/hunyuan-coding`, `tencent/hunyuan-lite`
|
||||
- 新增 setup 向导支持
|
||||
- 测试覆盖:`tests/hermes_cli/test_models.py` 新增用例
|
||||
- **工时**: 1d
|
||||
|
||||
#### W8-T6 模型生态扩展:百度文心一言
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 模型支持 PR
|
||||
- **验收标准**:
|
||||
- 新增 ProviderEntry:`ProviderEntry("baidu", "Baidu ERNIE", "Baidu ERNIE (ernie-bot models — direct API)")`
|
||||
- HERMES_OVERLAY:`transport="openai_chat"`, `base_url_env_var="BAIDU_BASE_URL"`
|
||||
- aliases:`ernie`, `wenxin` → `baidu`
|
||||
- `.env.example` 新增 `BAIDU_API_KEY`
|
||||
- 测试覆盖新增用例
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W8-T7 模型生态扩展:火山引擎 / 豆包
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 模型支持 PR
|
||||
- **验收标准**:
|
||||
- 新增 ProviderEntry:`ProviderEntry("volcengine", "Volcano Engine / Doubao", "Volcano Engine Doubao (doubao models — direct API)")`
|
||||
- HERMES_OVERLAY:`transport="openai_chat"`, `base_url_env_var="VOLCENGINE_BASE_URL"`
|
||||
- aliases:`doubao`, `volcano` → `volcengine`
|
||||
- `.env.example` 新增 `VOLCENGINE_API_KEY`
|
||||
- 测试覆盖新增用例
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W8-T8 模型生态扩展:Cohere
|
||||
- **输入依赖**: 无
|
||||
- **输出产物**: 模型支持 PR
|
||||
- **验收标准**:
|
||||
- 新增 ProviderEntry:`ProviderEntry("cohere", "Cohere", "Cohere (Command R+ models — direct API)")`
|
||||
- HERMES_OVERLAY:`transport="openai_chat"`, `base_url_env_var="COHERE_BASE_URL"`
|
||||
- `.env.example` 新增 `COHERE_API_KEY`
|
||||
- 测试覆盖新增用例
|
||||
- **工时**: 0.5d
|
||||
|
||||
---
|
||||
|
||||
### 第 9 周:并发模型统一 + 上下文压缩优化 + 内存治理
|
||||
|
||||
#### W9-T1 并发模型设计
|
||||
- **输入依赖**: W4-T2
|
||||
- **输出产物**: ADR
|
||||
- **验收标准**:
|
||||
- Gateway 侧全异步
|
||||
- CLI 侧同步 wrapper
|
||||
- 底层共享 `asyncio` 事件循环
|
||||
- 工具 handler 支持 `async def`
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W9-T2 `agent/loop/` 支持 async 模式
|
||||
- **输入依赖**: W9-T1, W4-T2
|
||||
- **输出产物**: `agent/loop/async_turn_engine.py` + 测试
|
||||
- **验收标准**:
|
||||
- 实现 `AsyncTurnEngine`,复用 `turn_engine.py` 核心逻辑
|
||||
- 工具调用支持 async handler
|
||||
- 单元测试覆盖率 ≥ 80%
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W9-T3 Gateway 移植到全异步
|
||||
- **输入依赖**: W9-T2, W5-T5
|
||||
- **输出产物**: Gateway async 移植 PR
|
||||
- **验收标准**:
|
||||
- `gateway/run.py` 中所有工具调用改为 `await`
|
||||
- `environments/agent_loop.py` 中 ThreadPoolExecutor 改为 asyncio
|
||||
- `pytest tests/gateway/` 全通过
|
||||
- 压测 latency 不恶化
|
||||
- **风险点**: 并发模型变化影响所有平台适配器,需逐一测试
|
||||
- **工时**: 2d
|
||||
|
||||
#### W9-T4 上下文压缩增量优化
|
||||
- **输入依赖**: W4-T3
|
||||
- **输出产物**: `agent/loop/compression.py` 升级 PR
|
||||
- **验收标准**:
|
||||
- 实现增量压缩(只压缩新增消息)
|
||||
- 实现压缩结果 LRU 缓存
|
||||
- 新增 `compression_strategy` 配置:`speed` / `balanced` / `quality`
|
||||
- 性能对比:压缩时间 -30%
|
||||
- **工时**: 1d
|
||||
|
||||
#### W9-T5 内存治理:全局状态收敛
|
||||
- **输入依赖**: W4-T2
|
||||
- **输出产物**: 内存优化 PR
|
||||
- **验收标准**:
|
||||
- `_last_resolved_tool_names`, `_tool_loop`, `_worker_thread_local` 收敛到 `AgentContext`
|
||||
- `trajectory_compressor.py` 中 tokenizer 改为 LRU 缓存(maxsize=4),支持显式清空
|
||||
- 使用 `tracemalloc` 验证内存无泄漏
|
||||
- **工时**: 1d
|
||||
|
||||
#### W9-T6 `environments/agent_loop.py` 与 `run_agent.py` 合并验证
|
||||
- **输入依赖**: W9-T3
|
||||
- **输出产物**: 合并验证报告
|
||||
- **验收标准**:
|
||||
- 确认 `environments/agent_loop.py` 逻辑已完全被 `agent/loop/` 覆盖
|
||||
- 确认无逻辑 divergence
|
||||
- 删除 `environments/agent_loop.py` 或改为 facade
|
||||
- `pytest tests/environments/` 全通过
|
||||
- **工时**: 0.5d
|
||||
|
||||
---
|
||||
|
||||
### 第 10 周:全量回归测试 + 性能基准 + 文档补全
|
||||
|
||||
#### W10-T1 全量回归测试
|
||||
- **输入依赖**: 所有前期任务
|
||||
- **输出产物**: 测试报告
|
||||
- **验收标准**:
|
||||
- `scripts/run_tests.sh` 全通过(14,140 测试)
|
||||
- 无回归失败
|
||||
- 核心模块覆盖率 ≥ 70%
|
||||
- **工时**: 1d
|
||||
|
||||
#### W10-T2 测试覆盖率提升
|
||||
- **输入依赖**: W10-T1
|
||||
- **输出产物**: 测试补充 PR
|
||||
- **验收标准**:
|
||||
- `agent/display.py` 45% → 70%
|
||||
- `tools/file_operations.py` 53% → 75%
|
||||
- 新增测试用例通过 CI
|
||||
- **工时**: 1.5d
|
||||
|
||||
#### W10-T3 性能基准验收
|
||||
- **输入依赖**: W4-T6~T7, W9-T4~T5
|
||||
- **输出产物**: 性能报告
|
||||
- **验收标准**:
|
||||
- 启动时间:`time python -c "import run_agent"` 当前基准 → -50%
|
||||
- 对话压测:100 轮对话 latency / throughput / 错误率 不恶化
|
||||
- 压缩对比:增量压缩时间 -30%
|
||||
- 内存报告:100 轮对话后内存增长 < 10MB
|
||||
- **工时**: 1d
|
||||
|
||||
#### W10-T4 CI 全线通过验收
|
||||
- **输入依赖**: 所有前期任务
|
||||
- **输出产物**: CI 验收报告
|
||||
- **验收标准**:
|
||||
- `ruff check` 门禁通过 = 0 errors
|
||||
- `mypy --strict agent/ tools/registry.py` 门禁通过 = 0 errors
|
||||
- `bandit -r agent/ tools/ gateway/ -lll` 门禁通过 = 0 High
|
||||
- `pytest` 全通过
|
||||
- `xenon --max-absolute B` 无阻断(先记录)
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W10-T5 架构图和模块依赖图更新
|
||||
- **输入依赖**: 所有前期任务
|
||||
- **输出产物**: 更新后的 `AGENTS.md` 架构部分
|
||||
- **验收标准**:
|
||||
- 更新 `AGENTS.md` 中的 File Dependency Chain
|
||||
- 新增四层架构图
|
||||
- 新增模块依赖规则说明
|
||||
- 更新添加新工具/配置/命令的步骤说明
|
||||
- **工时**: 0.5d
|
||||
|
||||
#### W10-T6 文档补全
|
||||
- **输入依赖**: W10-T5
|
||||
- **输出产物**: 更新后的文档
|
||||
- **验收标准**:
|
||||
- 新增《开发者迁移指南》(从旧模块到新模块的导入变化)
|
||||
- 新增《新增模型提供商指南》
|
||||
- 更新 README 中的模型支持列表
|
||||
- 更新 RELEASE 文档
|
||||
- **工时**: 0.5d
|
||||
|
||||
---
|
||||
|
||||
## 四、任务关联与依赖图
|
||||
|
||||
```
|
||||
W1: T1-T6 独立并行
|
||||
├→ W2-T6 (CI lint/security 门禁)
|
||||
└→ W3-T5 (死代码清理需要 lint 完成)
|
||||
|
||||
W2: T1-T7 串行+并行
|
||||
T1 → T2 → T4
|
||||
T1 → T3 → T5
|
||||
T2,T3,T4,T5 → W5-T7 (循环依赖清理)
|
||||
T6 → W7-T4 (配置 Pydantic 化需 core/config)
|
||||
|
||||
W3: T1-T6 并行+串行
|
||||
T1 → T2 → T3
|
||||
T4 → T6
|
||||
T2,T3 → W4-T5 (类型安全需要修复后才能参与 run_agent 拆分)
|
||||
|
||||
W4: T1-T7 并行+串行
|
||||
T1 → T2 → T3,T4
|
||||
T2,T3,T4 → T5
|
||||
T6 → T7
|
||||
T5 → W5-T6 (消息历史需要 TurnEngine)
|
||||
T5 → W6-T3 (回调收敛需要新引擎)
|
||||
T5 → W9-T2 (async 需要 TurnEngine)
|
||||
|
||||
W5: T1-T7 并行+串行
|
||||
T1 → T2 → T3,T4
|
||||
T2,T3,T4 → T5
|
||||
T6 → W10-T3 (测试验收需要消息历史)
|
||||
T5 → W7-T3 (health 端点需要 gateway 拆分)
|
||||
T5 → W9-T3 (async 需要新 gateway)
|
||||
|
||||
W6: T1-T7 并行+串行
|
||||
T1 → T2 → T3
|
||||
T4 → T5,T6 → T7
|
||||
T3 → W9-T3 (并发模型需要 EventBus)
|
||||
|
||||
W7: T1-T5 并行+串行
|
||||
T1,T2 → W10-T3 (性能验收)
|
||||
T4 → T5
|
||||
|
||||
W8: T1-T8 高度并行
|
||||
T1 → T2 → T3
|
||||
T1 → T4
|
||||
T5-T8 独立
|
||||
|
||||
W9: T1-T6 并行+串行
|
||||
T1 → T2 → T3
|
||||
T4,T5,T6 独立
|
||||
T3 → W10-T3 (性能验收)
|
||||
|
||||
W10: T1-T6 串行+并行
|
||||
T1 → T2
|
||||
T3,T4,T5,T6 独立
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、质量门禁与验收矩阵
|
||||
|
||||
### 5.1 CI 门禁(红线)
|
||||
| 检查项 | 工具 | 门禁时机 | 阈值 | 责任人 |
|
||||
|--------|------|---------|------|--------|
|
||||
| Lint | ruff | 每次 push/PR | 0 errors | CI |
|
||||
| 安全 | bandit | 每次 push/PR | 0 High/Medium | CI |
|
||||
| 类型 | mypy | 每次 push/PR | 核心模块 0 errors | CI |
|
||||
| 复杂度 | xenon | 每次 push/PR | 记录不阻断 | CI |
|
||||
| 测试 | pytest | 每次 push/PR | 100% PASS | CI |
|
||||
| 覆盖率 | pytest-cov | 每次 push/PR | 核心 ≥ 70% | CI |
|
||||
|
||||
### 5.2 代码审查规范
|
||||
- 所有 PR 必须通过 CI 全部门禁
|
||||
- God Object 拆分 PR 必须有单独的集成测试通过
|
||||
- 安全修复 PR 必须有安全团队 review
|
||||
- 架构变更 PR 必须更新 ADR 和 AGENTS.md
|
||||
|
||||
### 5.3 测试覆盖率路线图
|
||||
| 模块 | 当前 | M1 目标 | M2 目标 | M4 目标 |
|
||||
|------|------|---------|---------|---------|
|
||||
| tools/registry.py | 85% | 85% | 90% | 95% |
|
||||
| agent/context_references.py | 84% | 84% | 90% | 95% |
|
||||
| agent/loop/* | N/A | 80% | 85% | 90% |
|
||||
| agent/display.py | 45% | 50% | 60% | 70% |
|
||||
| tools/file_operations.py | 53% | 55% | 65% | 75% |
|
||||
| gateway/lifecycle.py | N/A | 70% | 75% | 80% |
|
||||
|
||||
---
|
||||
|
||||
## 六、风险应对与回退方案
|
||||
|
||||
### 6.1 风险登记簿
|
||||
| ID | 风险描述 | 概率 | 影响 | 应对措施 | 回退方案 |
|
||||
|----|---------|------|------|---------|--------|
|
||||
| R1 | 拆分 God Object 引入回归 | 中 | 高 | 保留 facade;每个拆分独立 PR;增加集成测试 | facade 文件恢复原内实现 |
|
||||
| R2 | hermes_cli→core 迁移破坏插件 | 中 | 高 | 提供兼容 shim;灰度发布 | 恢复 hermes_cli 为全局库(技术债务增加) |
|
||||
| R3 | Ruff 大规模修复 merge conflict | 高 | 低 | 一次性执行后立即合并;通知全员 rebase | 分批执行,每天一个目录 |
|
||||
| R4 | Mypy 严格模式阻塞开发 | 中 | 中 | 分模块开启;允许 `type: ignore` 配额(每模块 5 个) | 降低 mypy 严格级别,先用 `--ignore-missing-imports` |
|
||||
| R5 | 性能优化改变并发语义 | 低 | 高 | 压测对比;金丝雀发布 | 保留旧并发模型作为 fallback |
|
||||
| R6 | 模型提供商接口变更 | 中 | 中 | 模型提供商支持独立 PR,不阻断主线 | 移除该提供商支持,等待接口稳定 |
|
||||
| R7 | 关键人员离岗 | 低 | 高 | 每个关键任务配备份责任人;文档完整 | 减少当周任务量,保持核心功能稳定 |
|
||||
|
||||
### 6.2 回退策略详细
|
||||
- **代码级回退**:所有重构 PR 必须通过 `git revert` 可以在 5 分钟内完成
|
||||
- **功能级回退**:新功能(如 async Gateway)必须有特性开关,默认关闭
|
||||
- **配置级回退**:所有新配置必须有后向兼容的默认值
|
||||
|
||||
---
|
||||
|
||||
## 七、资源需求
|
||||
|
||||
### 7.1 人力
|
||||
| 角色 | 人数 | 职责 |
|
||||
|------|------|------|
|
||||
| 架构负责人 | 1 | ADR 审查、架构门禁、技术决策 |
|
||||
| 后端开发 | 2 | God Object 拆分、core/ 包、引擎重构 |
|
||||
| 工具/配置开发 | 1 | CI 增强、配置 Pydantic 化、可观测性 |
|
||||
| 安全/测试 | 1 | 安全漏洞修复、测试补充、回归测试 |
|
||||
| 模型生态 | 1 | 新增模型提供商支持 |
|
||||
| 总计 | **6 人** | |
|
||||
|
||||
### 7.2 工具链
|
||||
| 工具 | 用途 | 版本要求 |
|
||||
|------|------|---------|
|
||||
| ruff | Lint + format | ≥ 0.9 |
|
||||
| mypy | 类型检查 | ≥ 1.15 |
|
||||
| bandit | 安全扫描 | ≥ 1.8 |
|
||||
| pytest + pytest-xdist + pytest-cov | 测试 | ≥ 9.0 |
|
||||
| xenon | 代码复杂度 | ≥ 0.9 |
|
||||
| pydeps | 依赖分析 | 最新 |
|
||||
| tracemalloc | 内存分析 | Python 内置 |
|
||||
|
||||
### 7.3 环境
|
||||
- Python 3.11+ 开发环境
|
||||
- GitHub Actions ubuntu-latest runner
|
||||
- 本地测试机:至少 8GB RAM,SSD
|
||||
- 测试 API 键位置:项目提供测试帐号(高优先级提供商)
|
||||
|
||||
---
|
||||
|
||||
## 八、附录
|
||||
|
||||
### A. 术语对照表
|
||||
| 本文档术语 | 对应工具/概念 |
|
||||
|----------|------------|
|
||||
| God Object | 超大模块(如 run_agent.py 12,048 行) |
|
||||
| facade | 保持原有 API 签名,内部转发到新模块的兼容层 |
|
||||
| EventBus | 事件总线,用于取代多个回调函数参数 |
|
||||
| 四层架构 | Presentation → Application → Domain → Infrastructure |
|
||||
| 金丝雀发布 | 小流量逐步切换,降低风险 |
|
||||
| CI 门禁 | 持续集成中必须通过的检查步骤 |
|
||||
|
||||
### B. 相关文档
|
||||
- `plans/质量优化重构总方案_v1.md` — 总体方案
|
||||
- `AGENTS.md` — 当前架构说明
|
||||
- `.github/workflows/tests.yml` — 当前 CI 配置
|
||||
- `pyproject.toml` — 依赖管理
|
||||
|
||||
---
|
||||
|
||||
> 文档编号: PLAN-2026-0421-v1
|
||||
> 最后更新: 2026-04-21
|
||||
> 审批状态: 待用户最终确认
|
||||
274
plans/质量优化重构总方案_v1.md
Normal file
274
plans/质量优化重构总方案_v1.md
Normal file
@@ -0,0 +1,274 @@
|
||||
# Hermes Agent 立交桥项目 — 全面质量优化重构方案 v1.0
|
||||
|
||||
> 项目名称隐喻:当前代码库如同一座年久失修的立交桥 —— 车道纵横交错(循环依赖)、
|
||||
> 承重结构超重( God Object )、信号系统混乱(回调爆炸)、维护人员无从下手。
|
||||
> 本方案旨在对其进行"结构性加固+交通流线重构+智能信号升级"。
|
||||
|
||||
---
|
||||
|
||||
## 一、项目全景诊断
|
||||
|
||||
### 1.1 规模画像
|
||||
| 指标 | 数值 | 评级 |
|
||||
|------|------|------|
|
||||
| Python 源码文件 | 1,044 | 大型 |
|
||||
| TypeScript/TSX 文件 | 276 | 中型 |
|
||||
| 总代码行数 | ~535,704 | 超大型 |
|
||||
| 测试数量 | 14,140 (669 文件) | 优秀 |
|
||||
| 项目体积 | 1.1GB (venv 782MB) | 偏重 |
|
||||
| 生产依赖 | 37+ 核心包 | 可控 |
|
||||
|
||||
### 1.2 技术债务热力图
|
||||
| 维度 | 问题数量 | 严重度 |
|
||||
|------|---------|--------|
|
||||
| Lint 违规 (Ruff) | 1,717 (1,031 可自动修复) | 中高 |
|
||||
| 类型错误 (Mypy) | ~2,383 | 高 |
|
||||
| 高危安全漏洞 | 26 | **紧急** |
|
||||
| 中危安全漏洞 | 575 | 高 |
|
||||
| 裸 except Exception: pass | 1,244 | 中 |
|
||||
| 循环依赖包对 | 5+ | **高** |
|
||||
| 超 3,000 行 God Object | 4 个 | **高** |
|
||||
| 测试硬失败 | 4 个 | 中 |
|
||||
| 测试覆盖率洼地 | 45-53% | 中 |
|
||||
|
||||
---
|
||||
|
||||
## 二、五维度重构方案
|
||||
|
||||
### 维度 A:代码质量 — 消除路面裂缝
|
||||
|
||||
#### A1. 静态分析基线化(P0,第 1 周)
|
||||
- **Ruff 全线修复**:`ruff check --fix` 自动修复 1,031 处;剩余 686 处按规则分批人工 review
|
||||
- **F401 未使用导入专项**:860 处未使用导入清理,减少模块加载时间 5-10%
|
||||
- **F841 未使用变量**:160 处,清理死代码,降低认知负担
|
||||
|
||||
#### A2. 类型安全加固(P1,第 2-3 周)
|
||||
- **隐式 Optional 治理**:PEP 484 违规(`def foo(x: int = None)`)全量修复,约 200+ 处
|
||||
- **核心模块类型覆盖**:优先 `agent/`, `tools/registry.py`, `hermes_cli/config.py`
|
||||
- **Stub 补全**:安装 `types-PyYAML`, `types-requests`,消除 `import-untyped` 噪音
|
||||
- **Mypy 门禁**:CI 新增 `mypy --strict agent/ tools/registry.py` 步骤,逐步扩大范围
|
||||
|
||||
#### A3. 安全漏洞清零(P0,第 1-2 周)
|
||||
| 漏洞类型 | 文件位置 | 修复方案 |
|
||||
|---------|---------|---------|
|
||||
| B602 shell=True 注入 | `tui_gateway/server.py:2267,3078` | 改 `shlex.split` + `shell=False` |
|
||||
| B602 shell=True 注入 | `cli.py:6077` | 同上 |
|
||||
| B602 shell=True 注入 | `tools/skills_hub.py` (5处) | 参数化或改用 `subprocess.run([...])` |
|
||||
| B602 shell=True 注入 | `tools/environments/docker.py:541,560` | 同上 |
|
||||
| B324 弱哈希 | `agent/codex_responses_adapter.py:171` | `hashlib.sha1(usedforsecurity=False)` |
|
||||
| B324 弱哈希 | `agent/context_compressor.py:466` | `hashlib.md5(usedforsecurity=False)` |
|
||||
| B324 弱哈希 | `gateway/platforms/weixin.py:1787` | 同上 |
|
||||
| B310 urlopen | `agent/anthropic_adapter.py:487,795` | 增加 scheme 校验白名单 |
|
||||
| B615 trust_remote_code | `trajectory_compressor.py:366` | 固定 revision + 校验哈希 |
|
||||
|
||||
#### A4. 异常处理规范化(P1,第 3 周)
|
||||
- **裸 except 治理**:1,244 处 `except Exception: pass` → 明确异常类型
|
||||
- **静默失败审计**:高优先级模块(`tui_gateway/server.py`, `agent/auxiliary_client.py`)首批治理
|
||||
- **日志补偿**:所有 except 块必须携带 `logger.warning/error`,禁止空 pass
|
||||
|
||||
---
|
||||
|
||||
### 维度 B:系统稳定 — 加固承重结构
|
||||
|
||||
#### B1. God Object 拆解(P1-P2,第 2-6 周)
|
||||
当前 4 个超万行/近万行巨兽:
|
||||
|
||||
| 原文件 | 行数 | 拆分目标 |
|
||||
|--------|------|---------|
|
||||
| `run_agent.py` | 12,048 | `agent/loop/turn_engine.py` + `streaming.py` + `compression.py` + `retry_policy.py` + `checkpointing.py` |
|
||||
| `gateway/run.py` | 11,043 | `gateway/lifecycle.py` + `delivery_router.py` + `platform_coordinator.py` + `voice_manager.py` |
|
||||
| `cli.py` | 10,870 | `cli/display_engine.py` + `stream_renderer.py` + `input_handler.py` + `layout_manager.py` |
|
||||
| `hermes_cli/main.py` | 8,707 | `commands/chat.py` + `commands/gateway.py` + `commands/setup.py` + `commands/profile.py` |
|
||||
|
||||
**拆分原则**:
|
||||
- 每个新模块 < 1,500 行
|
||||
- 保留原文件为 facade(向后兼容 1 个版本)
|
||||
- 使用 `__getattr__` 延迟导入避免循环依赖
|
||||
|
||||
#### B2. 循环依赖解耦(P1,第 3-5 周)
|
||||
核心问题:`hermes_cli` 既是 CLI 入口,又是全局配置/认证库。
|
||||
|
||||
**根治方案 — 提取 `core/` 层**:
|
||||
```
|
||||
core/
|
||||
├── config.py # 从 hermes_cli/config.py 提取纯配置逻辑
|
||||
├── auth/
|
||||
│ ├── providers/ # 各 provider OAuth 独立模块
|
||||
│ ├── tokens.py
|
||||
│ └── oauth.py
|
||||
├── paths.py # get_hermes_home() 等路径工具
|
||||
└── models.py # 模型元数据/目录
|
||||
```
|
||||
|
||||
**迁移路径**:
|
||||
1. 新建 `core/` 包,将 `hermes_cli/config.py` 中无 UI 依赖的函数迁移
|
||||
2. `hermes_cli/config.py` 改为 re-export facade
|
||||
3. 逐文件替换 `from hermes_cli.config import ...` → `from core.config import ...`
|
||||
4. 同理处理 `hermes_cli/auth.py` → `core/auth/`
|
||||
|
||||
#### B3. 核心对话引擎单一化(P1,第 4-5 周)
|
||||
- **问题**:`run_agent.py:run_conversation` 与 `environments/agent_loop.py` 逻辑重复
|
||||
- **方案**:将 `environments/agent_loop.py` 的 ThreadPoolExecutor 模型合并到 `agent/loop/` 中
|
||||
- **统一入口**:`TurnEngine` 类,支持 sync/async 双模式,消除 divergence risk
|
||||
|
||||
#### B4. 回调爆炸收敛(P2,第 5-6 周)
|
||||
- **现状**:`AIAgent.__init__` 接收 12+ 个回调参数
|
||||
- **方案**:引入 `AgentEventBus` 或 `AgentObserver` Protocol
|
||||
```python
|
||||
class AgentObserver(Protocol):
|
||||
def on_tool_start(self, tool_name: str, args: dict): ...
|
||||
def on_tool_progress(self, tool_name: str, delta: str): ...
|
||||
def on_stream_delta(self, text: str): ...
|
||||
# ... 统一收敛
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 维度 C:运维简捷 — 智能信号系统
|
||||
|
||||
#### C1. CI/CD 增强(P1,第 2-3 周)
|
||||
当前 `.github/workflows/tests.yml` 已覆盖 pytest,但缺少:
|
||||
|
||||
| 新增步骤 | 工具 | 阈值 |
|
||||
|---------|------|------|
|
||||
| Lint 门禁 | `ruff check` | 0 errors |
|
||||
| 类型检查 | `mypy --strict` | 核心模块 0 errors |
|
||||
| 安全扫描 | `bandit -r agent/ tools/ gateway/` | 无 High/Medium |
|
||||
| 代码复杂度 | `xenon --max-absolute B` | 无 D/F 级模块 |
|
||||
| 测试覆盖率 | `pytest --cov` | 核心模块 ≥ 70% |
|
||||
|
||||
**优化现有 CI**:
|
||||
- `tests.yml` 中 `uv pip install -e ".[all,dev]"` 过重 → 改为矩阵安装(core / messaging / dev 分层)
|
||||
- 增加缓存:`~/.cache/uv`, `.venv`
|
||||
|
||||
#### C2. 可观测性升级(P2,第 5-6 周)
|
||||
- **结构化日志**:`hermes_logging.py` 当前为文本日志,增加 JSON 模式(`HERMES_LOG_FORMAT=json`)
|
||||
- **指标埋点**:核心对话循环增加 `hermes_turn_latency_seconds`, `hermes_tool_errors_total` 等 Prometheus 风格指标
|
||||
- **健康检查端点**:Gateway 增加 `/health` 和 `/ready`(FastAPI 模式时)
|
||||
|
||||
#### C3. 配置管理简化(P2,第 6 周)
|
||||
- **统一配置 Schema**:`hermes_cli/config.py` 3,882 行 → Pydantic Settings 模型
|
||||
- **环境变量自文档**:`.env.example` 已有,但缺少验证逻辑
|
||||
- **配置热重载**:Gateway 运行时不重启加载配置变更
|
||||
|
||||
#### C4. 依赖瘦身(P2,第 6-7 周)
|
||||
- `uv.lock` 体积审计:找出只有一个文件使用的重型依赖
|
||||
- `optional-dependencies` 已较好,但 `all` 安装过重 → 提供 `hermes-agent[slim]` 精简版
|
||||
- 检查 `node_modules` 在 Docker 镜像中的残留
|
||||
|
||||
---
|
||||
|
||||
### 维度 D:性能优化 — 拓宽车道、减少拥堵
|
||||
|
||||
#### D1. 启动加速(P1,第 3-4 周)
|
||||
- **导入优化**:`tools/*.py` 中大量顶层 `registry.register()` 触发网络/文件检查 → 改为延迟注册
|
||||
- **__init__.py 减负**:禁止 `__init__.py` 中 import 重型模块
|
||||
- **基准**:当前冷启动时间(`python -c "import run_agent"`)→ 目标减少 50%
|
||||
|
||||
#### D2. 内存优化(P2,第 5-6 周)
|
||||
- **全局状态审计**:`_last_resolved_tool_names`, `_tool_loop`, `_worker_thread_local` 等全局变量 → 注入 `AgentContext`
|
||||
- **大对象生命周期**:`trajectory_compressor.py` 中 HuggingFace tokenizer 全局缓存 → LRU + 显式释放
|
||||
- **消息历史截断**:当前 `messages` 列表无限增长 → 实现 TokenBudget 硬上限,超限时归档到 SQLite
|
||||
|
||||
#### D3. 并发模型统一(P2,第 6 周)
|
||||
- **现状**:`run_agent.py` 同步循环,`gateway/run.py` 异步,`environments/agent_loop.py` ThreadPool
|
||||
- **目标**:Gateway 侧全异步;CLI 侧同步 wrapper;底层共享 `asyncio` 事件循环
|
||||
- **工具执行**:当前工具在同步线程中跑 → 支持 `async def` 工具 handler
|
||||
|
||||
#### D4. 上下文压缩优化(P2,第 6 周)
|
||||
- **现状**:`ContextCompressor` 内联在对话循环中,每次 turn 都触发
|
||||
- **优化**:增量压缩,只压缩新增消息;缓存压缩结果;提供 `compression_strategy` 配置(speed/balanced/quality)
|
||||
|
||||
---
|
||||
|
||||
### 维度 E:架构简洁 — 重建交通流线
|
||||
|
||||
#### E1. 分层架构重构(P2-P3,第 6-10 周)
|
||||
目标四层结构:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Presentation Layer │
|
||||
│ cli.py / gateway/ / ui-tui / tui_gateway│
|
||||
├─────────────────────────────────────────┤
|
||||
│ Application Layer │
|
||||
│ hermes_cli/commands.py / agent/loop/ │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Domain Layer │
|
||||
│ agent/ (prompt, context, compression) │
|
||||
│ tools/ (registry, handlers) │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Infrastructure Layer │
|
||||
│ core/ (config, auth, paths, models) │
|
||||
│ environments/ (docker, ssh, modal...) │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**依赖规则**:
|
||||
- 上层可依赖下层,禁止反向
|
||||
- `core/` 不依赖任何其他内部包
|
||||
- `tools/` 不依赖 `hermes_cli/`, `gateway/`, `cli.py`
|
||||
|
||||
#### E2. Plugin 系统正交化(P2,第 6-7 周)
|
||||
- **问题**:`tools/skills_tool.py` 导入 `hermes_cli.plugins`,`tools/terminal_tool.py` 也导入
|
||||
- **方案**:将 `PluginHost` Protocol 定义在 `agent/` 层,`hermes_cli/plugins.py` 实现该 Protocol
|
||||
- **Hook 生命周期管理器**:从 `run_agent.py` 的硬编码 hook 调用 → `HookLifecycleManager` 统一调度
|
||||
|
||||
#### E3. Skill 系统去重(P3,第 8-9 周)
|
||||
- **现状**:`plugins/memory/*` 下多个插件复制粘贴相同 `__init__.py` 模式
|
||||
- **方案**:抽象 `BaseMemoryPlugin`,统一生命周期;各 memory backend 只实现 `store()`/`retrieve()`/`delete()`
|
||||
|
||||
#### E4. 测试架构升级(P1-P3,贯穿全程)
|
||||
- **修复硬失败**:`test_credential_pool.py`, `test_insights.py`, `test_model_metadata_local_ctx.py`
|
||||
- **覆盖率提升**:`agent/display.py` 45% → 70%;`tools/file_operations.py` 53% → 75%
|
||||
- **Mock 策略统一**:禁止测试中直接 `patch("run_agent.something")`,改用 `patch("agent.loop.turn_engine.something")`
|
||||
- **并行测试稳定**:当前 `-n auto` 在 16+ 核机器上不稳定 → 固定 `-n 4`(已体现在 `scripts/run_tests.sh`)
|
||||
|
||||
---
|
||||
|
||||
## 三、风险矩阵与回退策略
|
||||
|
||||
| 风险 | 概率 | 影响 | 缓解措施 |
|
||||
|------|------|------|---------|
|
||||
| 拆分 God Object 引入回归 | 中 | 高 | 保留 facade 文件 1 个版本;每个拆分独立 PR;增加集成测试 |
|
||||
| hermes_cli → core 迁移破坏插件 | 中 | 高 | 提供 `hermes_cli.config` 兼容 shim;灰度发布 |
|
||||
| Ruff 大规模修复导致 merge conflict | 高 | 低 | 一次性执行后立即合并;通知全员 rebase |
|
||||
| Mypy 严格模式阻塞开发 | 中 | 中 | 分模块开启,先核心后外围;允许 `type: ignore` 配额 |
|
||||
| 性能优化改变并发语义 | 低 | 高 | 压测对比( latency / throughput / 错误率 );金丝雀发布 |
|
||||
|
||||
---
|
||||
|
||||
## 四、预期收益
|
||||
|
||||
| 指标 | 当前基线 | 目标 | 测量方式 |
|
||||
|------|---------|------|---------|
|
||||
| 代码 Lint 错误 | 1,717 | 0 | `ruff check` |
|
||||
| 类型错误 (核心模块) | ~800 | 0 | `mypy agent/ tools/registry.py` |
|
||||
| 高危安全漏洞 | 26 | 0 | `bandit -lll` |
|
||||
| 最大单文件行数 | 12,048 | < 1,500 | `find . -name "*.py" | xargs wc -l` |
|
||||
| 冷启动导入时间 | 基线 TBD | -50% | `time python -c "import run_agent"` |
|
||||
| 核心模块测试覆盖率 | 45-53% | ≥ 70% | `pytest --cov` |
|
||||
| CI 全绿通过率 | 99.8% | 100% | GitHub Actions |
|
||||
| 循环依赖包对 | 5+ | 0 | `pydeps` / 静态分析 |
|
||||
|
||||
---
|
||||
|
||||
## 五、实施节奏概览
|
||||
|
||||
```
|
||||
第 1 周:安全清零 + Ruff 修复 + 测试修复
|
||||
第 2 周:core/ 包创建 + hermes_cli 解耦启动
|
||||
第 3 周:类型安全基线化 + CI 增强
|
||||
第 4 周:run_agent.py 拆分启动 + 导入优化
|
||||
第 5 周:gateway/run.py 拆分 + 循环依赖清理
|
||||
第 6 周:cli.py 拆分 + AgentEventBus 落地
|
||||
第 7 周:可观测性 + 配置 Pydantic 化
|
||||
第 8 周:Plugin 正交化 + Skill 抽象
|
||||
第 9 周:并发模型统一 + 上下文压缩优化
|
||||
第 10 周:全量回归测试 + 性能基准验收
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> 下一步:与用户讨论确认本方案,细化各阶段任务粒度、责任人、验收标准,
|
||||
> 形成可执行的《详细实施计划文档》。
|
||||
Reference in New Issue
Block a user