Files
hermes-ui/docs/phases/phase_003.md
T
toor 8c1ddf415f Phase 003: remove the coding-agent and ekko-agent runtimes
Every chat session now runs through the Hermes bridge, so the three chat
chains become feature-equivalent instead of three partially-maintained
dispatch paths. Keeping the coding-agent and in-house agent runtimes alive
meant every bridge change had to be mirrored into two more runtimes that
had already drifted.

Historical rows are read, not migrated: sessions stored with the retired
source normalize to cli on load, workflow graphs naming the retired agents
keep loading and run on the bridge, and the visible-source check plus
SOURCE_LABELS still recognize the old value so those sessions stay listed.

The public surface follows the code: the OpenAPI generator and the MCP
chat-run tool schema drop the six retired entry fields so external callers
are not told about runtimes that no longer exist.

harness-check gains a RETIRED_RUNTIME scan so the residual check is a
mechanical gate instead of a manual grep, with the two surviving read-side
compat sites recorded with reasons.

Refs: docs/phases/phase_003.md
2026-10-16 13:27:50 +08:00

6.5 KiB
Raw Blame History

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 组

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 组

rm -rf packages/server/src/services/ekko-agent/
rm -f  packages/server/src/services/hermes/run-chat/handle-ekko-agent-run.ts

1.3 相关测试

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 命令

cd /Users/jack/source/MyProject/js/hermes-ui

# 残留检查(harness 机械门禁,RETIRED_RUNTIME_ALLOWED 登记保留理由)
npm run harness:check
# 期望:Harness check passed

npm run build
npm run test
npm run test:e2e

6.2 手工(三条链路必须逐条走)

  • 普通聊天:发消息 → 流式输出 → 完成
  • 全局 Agent:跑一条 → 走桥正常
  • 群聊:多 agent 房间发消息 → 路由正常
  • 会话列表不再出现代理类型图标
  • 用量页 AgentBreakdown 不再显示 ekko / coding 分组
  • 工作流页不再能选编程代理
  • 侧边栏无编程代理入口

7. 风险

# 风险 缓解
P3-1 isWorking 三处漏改 → 聊天状态卡死或一直转圈 npm run harness:check 的 RETIRED_RUNTIME 扫描必须零命中
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(砍桌面端 + 官网)。