Files
hermes-ui/docs/chat-chain-changes/2026-10-16-phase003-remove-coding-agents.md
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

4.4 KiB

date, pr, feature, impact
date pr feature impact
2026-10-16 pending Phase 003 - remove the coding-agent and ekko-agent runtimes Every chat session now runs through the Hermes bridge; sessions stored with the old `coding_agent` source are normalized to `cli` on load.

Phase 003 — Remove the coding-agent and ekko-agent runtimes

Phase: docs/phases/phase_003.md (groups I and J)

What Changed

The chat chain had three dispatch branches: bridge, coding agent (Claude Code / Codex), and ekko-agent. Phase 003 deletes the latter two, leaving the bridge as the single execution path.

Deleted modules

  • packages/server/src/services/agent-runner/ — 13 files. Adapters for the Anthropic and OpenAI Responses streaming shapes, the Claude Code / Codex HTTP proxies, the SSE helpers, and coding-agent-run-manager.
  • packages/server/src/services/ekko-agent/ — 2 files (manager.ts, mcp.ts).
  • packages/ekko-agent/ — the in-house agent runtime package.
  • run-chat/handle-coding-agent-run.ts, run-chat/handle-ekko-agent-run.ts.
  • run-chat/sse-utils.ts — an orphan that only re-exported agent-runner/sse. No production module imported it; the single remaining reference was a vi.mock in run-chat-load-state.test.ts.
  • The three route modules, the controller, the service, CodingAgentsView.vue, and packages/client/src/api/coding-agents.ts.

Dispatch

runAndWait in run-chat/index.ts was a three-way branch. It is now a single call to handleBridgeRun. Two predicates went away with it:

  • isCodingAgentExecution(source, data)
  • isEkkoAgentExecution(data)

isWorking was computed as !isCodingAgentExecution(...) at three call sites (queue start, direct run start, resumed run). All three are now true.

Types and session fields

  • ChatCodingAgentId — defined twice (server run-chat/types.ts, client api/coding-agents.ts). Both definitions are gone; nothing imports them now.
  • ChatRunSource lost 'coding_agent'.
  • QueuedRun lost codingAgentId / agentId.
  • StartRunRequest lost coding_agent_id / agent_id.
  • The client Session shape lost codingAgentId / codingAgentMode.

ChatRunSource compatibility

resolveRunSource previously passed 'coding_agent' through. It now falls through to the default 'cli', so sessions stored with the old source run through the bridge without a data migration. The same is true for the value-based checks in controllers/hermes/sessions.ts — they read the stored string, and any source that is not global_agent or workflow resolves to the bridge path.

isCodingAgentSession in the sessions controller controlled three things at once: whether a workspace was created, whether the bridge was notified of a model change, and whether agent_native_session_id was cleared. All three now apply to every session, which is the intended post-Phase-003 behavior.

Workflow

WorkflowNodeAgent narrowed to 'hermes'. resolveWorkflowNodeRunTarget ignores its argument and always returns the Hermes target, so saved workflows that still name claude-code or codex keep loading. The node editor's protocol dropdown and the apiModeRequired validation were removed, along with the apiMode field on WorkflowAgentNodeData.

Usage recording

RecordSessionUsageInput.source and .agent narrowed to 'hermes'. The only caller is handle-bridge-run.ts, which already passed those values. Rows written before this phase keep their stored source / agent strings; the client's AgentBreakdown maps anything it does not recognize to unknown.

Contract Check

/chat-run event names, field names, and field types are unchanged. The socket.start_run payload only ever sent coding_agent_id / agent_id for sessions that were already coding-agent sessions; nothing new is sent. Two optional request fields were removed, and every session that used them now takes the bridge path instead.

Residual Strings

Kept on purpose, so existing records still render a sensible label:

  • packages/client/src/shared/session-display.ts — coding_agent: 'Coding Agent' in SOURCE_LABELS, which labels sessions already stored in the DB.
  • packages/server/src/controllers/hermes/sessions.ts — the isVisibleWebUiSessionSource check still lists 'coding_agent' so old sessions stay visible in the Web UI session list.

Both are registered in the scripts/harness-check.mjs allow-list.

Verification

npm run harness:check
npm run build
npm run test