From e93cbd2933874a726cb23715479489387bee764e Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 22 Apr 2026 07:10:08 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E8=B4=A8=E9=87=8F=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=80=BB=E6=96=B9=E6=A1=88=E4=B8=8E=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E7=BA=A7=E5=AE=9E=E6=96=BD=E8=AE=A1=E5=88=92=20v1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 基于全面代码分析输出: - 质量优化重构总方案_v1.md:五维度总体方案 - 质量优化重构实施计划_任务级_v1.md:78个任务,10周详细安排 关键结果: - 新增模型提供商支持(腾讯云Coding Plan、百度文心、火山引擎、Cohere) - 四层架构设计 + EventBus 抽象 - CI lint/security/type 全线门禁 - 异常规范化 + 类型安全基线化 - God Object 拆分路线图 验收标准:Lint 0 错误、高危安全漏洞清零、启动时间 -50%、测试覆盖率 70%+ --- plans/质量优化重构实施计划_任务级_v1.md | 878 ++++++++++++++++++++++++ plans/质量优化重构总方案_v1.md | 274 ++++++++ 2 files changed, 1152 insertions(+) create mode 100644 plans/质量优化重构实施计划_任务级_v1.md create mode 100644 plans/质量优化重构总方案_v1.md diff --git a/plans/质量优化重构实施计划_任务级_v1.md b/plans/质量优化重构实施计划_任务级_v1.md new file mode 100644 index 00000000..5318f356 --- /dev/null +++ b/plans/质量优化重构实施计划_任务级_v1.md @@ -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 +> 审批状态: 待用户最终确认 diff --git a/plans/质量优化重构总方案_v1.md b/plans/质量优化重构总方案_v1.md new file mode 100644 index 00000000..b15ca471 --- /dev/null +++ b/plans/质量优化重构总方案_v1.md @@ -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 周:全量回归测试 + 性能基准验收 +``` + +--- + +> 下一步:与用户讨论确认本方案,细化各阶段任务粒度、责任人、验收标准, +> 形成可执行的《详细实施计划文档》。