# Phase 003 — 砍 I 组(编程代理)+ J 组(ekko-agent) | 项 | 值 | |---|---| | 目标 | 删除 Claude Code / Codex 编程代理与自有 Agent,聊天链路只走 Hermes 桥 | | 前置 | Phase 002 通过 | | 产出 | 三条聊天链路(普通聊天 / 全局 Agent / 群聊)功能对等 | | 参考 | `docs/03-施工蓝图.md` §5 | --- ## 0. 为什么可以安全砍(已核实) `run-chat/index.ts` 的 dispatch 结构: ``` ensureBridgeReadyForChatRun() → handleBridgeRun() ← 主路径,最先执行且 return → if (isEkkoAgentExecution(data)) handleEkkoAgentRun() ← J 组 → handleCodingAgentRun() ← I 组兜底 ``` - bridge 分支在最前且有 `return`,删掉后面两条不影响它 - 全局 Agent 走 `global-agent/server.ts` → `getChatRunServer().runAndWait()`,砍 I/J 后自动只走桥 - 群聊走 `group-chat/agent-clients.ts` 的 `AgentBridgeClient` 直连,与 I/J 无关 --- ## 1. 功能任务 1 — 删文件 ### 1.1 I 组 ```bash rm -rf packages/client/src/views/hermes/CodingAgentsView.vue rm -f packages/client/src/api/coding-agents.ts rm -f packages/server/src/routes/coding-agents.ts rm -f packages/server/src/routes/claude-code-proxy.ts rm -f packages/server/src/routes/codex-proxy.ts rm -f packages/server/src/controllers/coding-agents.ts rm -f packages/server/src/services/coding-agents.ts rm -rf packages/server/src/services/agent-runner/ # 含 stream-tee 网关 + adapters ``` ### 1.2 J 组 ```bash rm -rf packages/server/src/services/ekko-agent/ rm -f packages/server/src/services/hermes/run-chat/handle-ekko-agent-run.ts ``` ### 1.3 相关测试 ```bash rm -f tests/server/coding-agents-*.test.ts rm -f tests/server/coding-agent-run-manager-windows.test.ts rm -f tests/server/agent-runner-gateway.test.ts rm -f tests/server/handle-coding-agent-run.test.ts rm -f tests/client/coding-agent-api-modes.test.ts ``` > 先 `ls tests/server/ | grep -i "coding\|agent-runner\|ekko"` 拿到实际清单再删,别只按上面猜。 --- ## 2. 功能任务 2 — server 路由层 `packages/server/src/routes/index.ts`: 1. 删 `codingAgentRoutes` / `claudeCodeProxyRoutes` / `codexProxyRoutes` 的 import 2. 删对应的 `app.use(...)`(在原文件 L64/65/79 附近) 3. **保持 L78 那条注释的约束**:本地 API 路由必须注册在 proxy 兜底路由之前 `packages/server/src/controllers/hermes/sessions.ts`:删代理相关字段。 --- ## 3. 功能任务 3 — run-chat dispatch 简化(**核心**) `packages/server/src/services/hermes/run-chat/index.ts`: ### 3.1 删 import ``` handle-coding-agent-run handle-ekko-agent-run ``` ### 3.2 删两个判定函数 ``` isCodingAgentExecution() isEkkoAgentExecution() ``` ### 3.3 删 dispatch 分支 `handleBridgeRun()` 之后直接结束,删掉 `isEkkoAgentExecution` / `handleCodingAgentRun` 两条。 ### 3.4 修 `isWorking` 判定(三处,**最容易漏**) `isCodingAgentExecution` 同时被用于工作状态判定: | 原行 | 原逻辑 | 改后 | |---|---|---| | L289 | `state.isWorking = !isCodingAgentExecution(source, data)` | `state.isWorking = true` | | L423 | `if (!isCodingAgentExecution(source, data)) { ... }` | 去掉条件,保留花括号内逻辑 | | L707 | `state.isWorking = !isCodingAgentExecution(source, data)` | `state.isWorking = true` | **不要留空壳函数**。行号以本项目 `run-chat/index.ts` 实际为准,用 `grep -n isCodingAgentExecution` 定位。 ### 3.5 同目录其他文件 | 文件 | 改动 | |---|---| | `run-chat/types.ts` | 删 `ChatCodingAgentId` 类型及其引用 | | `run-chat/session-command.ts` | 删代理分支 | | `run-chat/load-state.ts` | 删代理分支 | | `run-chat/abort.ts` | 删代理分支 | --- ## 4. 功能任务 4 — client 导航与视图 | 文件 | 改动 | |---|---| | `router/index.ts` | 删 `name: 'hermes.codingAgents'` 路由块 | | `components/layout/AppSidebar.vue` | 删编程代理导航项 | | `components/hermes/chat/SessionListItem.vue` | 删代理类型图标分支 | | `components/hermes/chat/ChatInput.vue` | 删代理选择 UI | | `components/hermes/chat/ChatPanel.vue` | 删代理相关分支 | | `components/hermes/chat/MessageList.vue` | 删代理消息渲染分支 | | `components/hermes/chat/HistoryMessageList.vue` | 删代理消息渲染分支 | | `components/hermes/usage/AgentBreakdown.vue` | 删 ekko / coding agent 分组 | | `stores/hermes/chat.ts` | 删代理选择器 state 与 setter | | `shared/session-display.ts` | 删代理类型标签 | --- ## 5. 功能任务 5 — 工作流与用量 | 文件 | 改动 | |---|---| | `components/hermes/workflow/types.ts` | 删 `coding_agent_id` | | `components/hermes/workflow/WorkflowAgentNode.vue` | 删 agent 类型选择 | | `views/hermes/WorkflowView.vue` | 删对应 UI | | `views/hermes/HistoryView.vue` | 删对应列 | | `services/hermes/workflow-manager.ts` | 删 `coding_agent_id` 持久化 | | `services/usage-recorder.ts` | 删 ekko / coding agent 用量归类 | **历史数据兼容**:旧会话里可能存有 `coding_agent_id`。读侧改成「读到就忽略」,**不做数据迁移**。 --- ## 6. 验收 ### 6.1 命令 ```bash cd /Users/jack/source/MyProject/js/hermes-ui # 残留检查 grep -rn "coding_agent\|codingAgent\|CodingAgent\|ekko-agent\|ekkoAgent\|EkkoAgent" \ packages/ tests/ --include="*.ts" --include="*.vue" --include="*.json" # 期望:零命中 npm run build npm run test npm run test:e2e ``` ### 6.2 手工(**三条链路必须逐条走**) - [ ] 普通聊天:发消息 → 流式输出 → 完成 - [ ] 全局 Agent:跑一条 → 走桥正常 - [ ] 群聊:多 agent 房间发消息 → 路由正常 - [ ] 会话列表不再出现代理类型图标 - [ ] 用量页 AgentBreakdown 不再显示 ekko / coding 分组 - [ ] 工作流页不再能选编程代理 - [ ] 侧边栏无编程代理入口 --- ## 7. 风险 | # | 风险 | 缓解 | |---|---|---| | P3-1 | `isWorking` 三处漏改 → 聊天状态卡死或一直转圈 | `grep -n isCodingAgentExecution` 必须零命中后才算改完 | | P3-2 | 历史会话带 `coding_agent_id` 导致渲染报错 | 读侧容忍未知字段;手工造一条旧会话验证 | | P3-3 | 删 `agent-runner/` 时误删共用工具 | 先 `grep -rn "agent-runner"` 确认引用方只在这两组内 | | P3-4 | e2e 有用例依赖 coding-agents API | `npm run test:e2e` 必跑,红了删对应用例 | | P3-5 | `AgentBreakdown` 删分组后百分比除零 | 该组件有空态处理,确认无 `NaN%` | --- ## 8. 完成标志 进入 Phase 004(砍桌面端 + 官网)。