Revert "3"

This reverts commit f733414ddd.
This commit is contained in:
nettee
2026-05-13 19:07:12 +08:00
parent f733414ddd
commit 1b0df2588e
@@ -21,8 +21,7 @@ created: '2026-05-13'
### Success Criteria
- 上层入口基于统一 `RuntimeAdapter` 调度 agent。
- `RuntimeAgentDef` 不再作为上层 runtime 抽象暴露;如果保留它能减少 churn,它可以继续作为 runtime 包内部实现细节存在。
- 默认保留现有 `apps/daemon/src/runtimes/defs/*` 文件结构;不得为了匹配新抽象而批量移动文件、重命名符号或整理相邻代码。
- 废弃 `RuntimeAgentDef` 作为 runtime 抽象;现有 `defs/*` 迁移为 adapter 模块或 adapter 内部 helper。
- 新增或调整 agent runtime 时,主要改动集中在底层 runtime adapter 或协议适配模块。
- `server.ts` 和其他上层模块不再承担按具体 runtime、协议、parser、handler 或输出格式分支的职责。
@@ -39,10 +38,10 @@ created: '2026-05-13'
### Available Approaches
- **Adapter public boundary over existing definitions**: expose `getRuntimeAdapter(agentId)` to upper daemon modules, wrap existing `RuntimeAgentDef` entries and protocol helpers behind adapter methods, and keep definitions internal unless a narrower change requires removal. Source: `apps/daemon/src/runtimes/types.ts:37-68`, `apps/daemon/src/server.ts:3181-3189,4080-4176`, `apps/daemon/src/connectionTest.ts:901-968`
- **Definition-owned runtime behavior**: extend each runtime definition with behavior hooks for spawn IO, stream attachment, prompt delivery, and completion semantics. Rejected as the public boundary because it risks keeping definitions in orchestration paths; individual adapter implementations may still compose existing definitions internally to avoid churn. Source: `apps/daemon/src/runtimes/registry.ts:19-36`, `apps/daemon/src/runtimes/defs/pi.ts:88-94`, `apps/daemon/src/runtimes/defs/deepseek.ts:44-54`
- **Adapter-only public boundary**: expose `getRuntimeAdapter(agentId)` to upper daemon modules, retire `RuntimeAgentDef`, and expose all launch/protocol/capability behavior through adapter methods. Source: `apps/daemon/src/runtimes/types.ts:37-68`, `apps/daemon/src/server.ts:3181-3189,4080-4176`, `apps/daemon/src/connectionTest.ts:901-968`
- **Definition-owned runtime behavior**: extend each runtime definition with behavior hooks for spawn IO, stream attachment, prompt delivery, and completion semantics. Rejected because it preserves the definition abstraction and risks keeping definitions in orchestration paths. Source: `apps/daemon/src/runtimes/registry.ts:19-36`, `apps/daemon/src/runtimes/defs/pi.ts:88-94`, `apps/daemon/src/runtimes/defs/deepseek.ts:44-54`
- **Shared attach helper used by chat and connection tests**: extract the duplicated stream/session dispatch into a daemon runtime module consumed by both `/api/chat` and connection tests. Source: `apps/daemon/src/server.ts:4080-4176`, `apps/daemon/src/connectionTest.ts:901-968`
- **Adapter modules with helper composition**: compose adapter methods from existing `defs/*` launch definitions plus parser/session helpers, without moving definitions by default. Source: `apps/daemon/src/runtimes/defs/claude.ts:60-69`, `apps/daemon/src/claude-stream.ts:1-30`, `apps/daemon/src/acp.ts:398-458`
- **Adapter modules with helper composition**: migrate each `defs/*` launch definition into a runtime adapter module, while reusing parser/session helpers for protocol behavior. Source: `apps/daemon/src/runtimes/defs/claude.ts:60-69`, `apps/daemon/src/claude-stream.ts:1-30`, `apps/daemon/src/acp.ts:398-458`
### Constraints & Dependencies
@@ -76,35 +75,31 @@ flowchart TD
Adapter --> Sink[RuntimeSink]
Sink --> SSE[SSE: agent/stdout/stderr/error/end]
Adapter --> Close[evaluateClose]
Close --> Run[run.acpSession\nor run.runtimeSession if needed]
Close --> Run[run.runtimeSession\ncompat: run.acpSession]
```
采用 adapter public boundary:`server.ts`、`connectionTest.ts` 等上层 daemon 模块只通过 `getRuntimeAdapter(agentId)` 获取 `RuntimeAdapter`;identity、能力、启动、prompt delivery、parser/session 和 close-status 语义通过 `RuntimeAdapter` 暴露。Adapter 实现可以组合现有 `RuntimeAgentDef`、`defs/*`、parser/session helper;除非边界收敛确实需要,默认不移动 runtime definition 文件、不批量重命名符号。
采用 adapter-only runtime 抽象:`RuntimeAgentDef` 退役,现有 `defs/*` 迁移为 adapter 模块或 adapter 内部 helper。`server.ts`、`connectionTest.ts` 等上层 daemon 模块只通过 `getRuntimeAdapter(agentId)` 获取 `RuntimeAdapter`;所有 identity、能力、启动、prompt delivery、parser/session、MCP、close-status 语义都通过 `RuntimeAdapter` 暴露。
### Change Scope
- Area: daemon runtime public boundary. Impact: 上层从 `getAgentDef(agentId)` 改为 `getRuntimeAdapter(agentId)`;`RuntimeAgentDef` 可保留为 runtime 包内部实现。Source: `apps/daemon/src/runtimes/types.ts:37-68`, `apps/daemon/src/runtimes/registry.ts:19-48`
- Area: daemon runtime adapter module. Impact: 新增 `apps/daemon/src/runtimes/runtime-adapters.ts`(或同等模块)集中暴露上层实际需要的 identity、capabilities、spawn、parser/session/stdin/prompt/close policy;不迁移无关 detection/model/prompt-budget helper,除非调用边界强制需要。Source: `apps/daemon/src/server.ts:3787-3860,4080-4264`, `apps/daemon/src/connectionTest.ts:901-1292`
- Area: daemon runtime public boundary. Impact: 上层从 `getAgentDef(agentId)` 改为 `getRuntimeAdapter(agentId)`;删除 `RuntimeAgentDef` 抽象并由 adapter registry 直接聚合 runtimes。Source: `apps/daemon/src/runtimes/types.ts:37-68`, `apps/daemon/src/runtimes/registry.ts:19-48`
- Area: daemon runtime adapter module. Impact: 新增 `apps/daemon/src/runtimes/runtime-adapters.ts`(或同等模块)集中暴露 identity、capabilities、option validation、spawn、parser/session/stdin/prompt/MCP/close policy。Source: `apps/daemon/src/server.ts:3787-3860,4080-4264`, `apps/daemon/src/connectionTest.ts:901-1292`
- Area: `/api/chat` orchestration. Impact: `server.ts` 保留 run 生命周期、请求校验、SSE sink、诊断和最终状态落库,但不直接读取 runtime launch/protocol fields;这些都由 adapter 方法提供。Source: `apps/daemon/src/server.ts:3181-3189,3787-3860,4061-4264`
- Area: connection tests. Impact: `connectionTest.ts` 复用同一 adapter spawn/attach/evaluateClose 行为,避免第二套 runtime dispatch drift。Source: `apps/daemon/src/connectionTest.ts:901-968,1126-1292`
- Area: prompt composition and critique eligibility. Impact: 用 adapter capability 表达 plain/API prompt mode 与 Critique Theater eligibility,避免上层继续以 `streamFormat === 'plain'` 推断。Source: `apps/daemon/src/prompts/system.ts:258-267`, `apps/daemon/src/server.ts:3079-3098,3923-3944`
- Area: external MCP delivery. Impact: 仅在消除上层 protocol dispatch 必须时迁移 Claude `.mcp.json` 与 ACP MCP descriptors;否则保持现有位置,避免扩大范围。Source: `apps/daemon/src/server.ts:3515-3586`
### Scope Guard
本次变更是 behavior-preserving 的手术式重构。每一行改动都必须能追溯到以下目的之一:移除上层 runtime/protocol dispatch,或让 chat 和 connection test 共享同一 dispatch 路径。文件移动、符号批量重命名、格式化清理、相邻代码整理、完全删除 `RuntimeAgentDef`、完整 capability model 重塑、runtime session 命名清理都默认不在本次范围内。只移除本次改动制造出来的 unused import、unused variable、unused helper。
- Area: external MCP delivery. Impact: Claude `.mcp.json` 与 ACP MCP descriptors 进入 adapter prepare hook,上层只传递规范化 MCP context。Source: `apps/daemon/src/server.ts:3515-3586`
### Design Decisions
- Decision: 使用 `RuntimeAdapter` 作为 daemon 上层唯一 runtime public boundary;`RuntimeAgentDef` 可继续作为 adapter 内部 launch/metadata record,直到后续独立重构有明确收益。Source: `apps/daemon/src/runtimes/types.ts:37-68`, `apps/daemon/src/runtimes/registry.ts:19-48`
- Decision: 删除 `RuntimeAgentDef` 抽象,使用 `RuntimeAdapter` 作为唯一 runtime 类型和 public boundary。Source: `apps/daemon/src/runtimes/types.ts:37-68`, `apps/daemon/src/runtimes/registry.ts:19-48`
- Decision: adapter 解析必须 fail fast;`getRuntimeAdapter(agentId)` 找不到 runtime 或 adapter 构造失败时直接失败,不回退到 plain/mock behavior。Source: `apps/daemon/src/runtimes/registry.ts:19-48`, `apps/daemon/src/runtimes/types.ts:50-55`
- Decision: 引入最小 `RuntimeSink`,只承载 chat 和 connection test 共享 attach 路径所需的 `agent`/`stdout`/`stderr`/`error` 发射与必要 state;不要顺手重写无关 SSE 或 activity 逻辑。Source: `apps/daemon/src/server.ts:4061-4078,4088-4167`
- Decision: spawn、stdin mode、prompt delivery、env/args resolution、stream/session attach 和 close policy 属于 adapter 对外能力;image support、prompt budget 等现有 helper 只有在上层边界要求时才迁移。Source: `apps/daemon/src/server.ts:3811-3860,4101-4154,4266-4268`, `apps/daemon/src/connectionTest.ts:1105-1147,1284-1292`
- Decision: session-aware runtimes 可返回统一 `RuntimeSession`,包含 `abort`、`hasFatalError`、`completedSuccessfully` 等能力;实现阶段优先复用现有 `run.acpSession` 存储,只有确有必要才新增 `run.runtimeSession` 兼容字段。Source: `apps/daemon/src/server.ts:4174-4176,4196-4244`, `apps/daemon/src/connectionTest.ts:893-899,1197-1220`
- Decision: 引入 `RuntimeSink`,由共享 sink 维护 `agent`/`stdout`/`stderr`/`error` 发射、activity 更新、structured error、substantive-output tracking;adapter 只把协议输出规范化给 sink。Source: `apps/daemon/src/server.ts:4061-4078,4088-4167`
- Decision: spawn、stdin mode、prompt delivery、image support、prompt budget、env/args resolution 都属于 adapter 对外能力;上层不再读取 launch/protocol fields。Source: `apps/daemon/src/server.ts:3811-3860,4101-4154,4266-4268`, `apps/daemon/src/connectionTest.ts:1105-1147,1284-1292`
- Decision: session-aware runtimes 返回统一 `RuntimeSession`,包含 `abort`、`hasFatalError`、`completedSuccessfully` 等能力;实现阶段可先写入 `run.runtimeSession` 并兼容赋值到现有 `run.acpSession`。Source: `apps/daemon/src/server.ts:4174-4176,4196-4244`, `apps/daemon/src/connectionTest.ts:893-899,1197-1220`
- Decision: close-status policy 由 adapter/session 提供 override;generic close handler 只合并 cancel、exit code、signal、stream error、empty-output guard 与 adapter override。Source: `apps/daemon/src/server.ts:4192-4264`, `apps/daemon/src/connectionTest.ts:1197-1220`
- Decision: prompt-mode、Critique Theater、substantive-output tracking 可逐步改为显式 capabilities;第一轮只替换当前阻塞上层 format dispatch 的检查。Source: `apps/daemon/src/prompts/system.ts:258-267`, `apps/daemon/src/server.ts:3079-3098,3923-3944,4040-4078`
- Decision: prompt-mode、Critique Theater、substantive-output tracking 改为显式 capabilities,避免通过 `streamFormat` 字符串推断行为。Source: `apps/daemon/src/prompts/system.ts:258-267`, `apps/daemon/src/server.ts:3079-3098,3923-3944,4040-4078`
- Decision: 保持现有 SSE contract 不变;structured handlers 继续发 `agent`,plain streams 继续发 `stdout`,错误发 `error`,run 终止发 `end`。Source: `apps/daemon/src/runs.ts:49-89`, `apps/daemon/src/server.ts:4061-4078,4168-4172,4264`
- Decision: 本次重构不改变 Claude external MCP 写入失败的 best-effort 语义;除非必须迁移位置,否则保持现有代码。是否改为 hard failure 另行决策。Source: `apps/daemon/src/server.ts:3515-3586`
- Decision: 本次重构不改变 Claude external MCP 写入失败的 best-effort 语义,只迁移位置;是否改为 hard failure 另行决策。Source: `apps/daemon/src/server.ts:3515-3586`
### Why this design
@@ -186,14 +181,13 @@ launch.child.on('close', (code, signal) => {
### File Structure
- `apps/daemon/src/runtimes/types.ts` - add public adapter/session/sink/spawn/close types while preserving `RuntimeAgentDef` if existing internals still need it.
- `apps/daemon/src/runtimes/runtime-adapters.ts` - expose `getRuntimeAdapter(agentId)` and, only if needed by existing callers, `listRuntimeAdapters()`; compose adapters from existing definitions and protocol helpers.
- `apps/daemon/src/runtimes/runtime-sink.ts` - optional normalized sink helpers for chat and connection test usage, only if separating them avoids duplication without rewriting unrelated SSE logic.
- `apps/daemon/src/runtimes/defs/*` - preserve existing files by default; do not move or rename definitions solely to fit the adapter shape.
- `apps/daemon/src/server.ts` - replace `getAgentDef` and format dispatch with adapter calls where needed; keep run lifecycle, SSE wiring, diagnostics, and final status ownership.
- `apps/daemon/src/connectionTest.ts` - replace duplicated stream/session dispatch with shared adapter attach/close behavior; keep local result mapping.
- `apps/daemon/src/prompts/system.ts` and `packages/contracts/src/prompts/system.ts` - update only if removing upper-layer format checks requires explicit prompt mode alignment.
- `apps/daemon/tests/*runtime-adapter*.test.ts` - add focused adapter/sink/registry regression coverage; keep existing parser/session tests as the main safety net.
- `apps/daemon/src/runtimes/types.ts` - replace `RuntimeAgentDef` with public adapter/session/sink/spawn/close types.
- `apps/daemon/src/runtimes/runtime-adapters.ts` - expose `getRuntimeAdapter(agentId)` and `listRuntimeAdapters()`; aggregate adapter modules directly.
- `apps/daemon/src/runtimes/runtime-sink.ts` - normalized sink helpers for chat and connection test usage, if separating keeps dependencies cleaner.
- `apps/daemon/src/server.ts` - replace `getAgentDef` and format dispatch with adapter calls; keep run lifecycle, SSE wiring, diagnostics, and final status ownership.
- `apps/daemon/src/connectionTest.ts` - replace local `attachAgentStreamHandlers`, args building, and stdin dispatch with shared adapter spawn/attach/close policy.
- `apps/daemon/src/prompts/system.ts` and `packages/contracts/src/prompts/system.ts` - replace stream-format-based API/plain prompt decision with explicit semantic prompt mode if contract surface needs to stay aligned.
- `apps/daemon/tests/*runtime-adapter*.test.ts` - new focused adapter/sink/registry regression coverage.
### Interfaces / APIs
@@ -257,8 +251,8 @@ type RuntimeAdapter = {
name: string;
capabilities: RuntimeCapabilities;
summarize?(): RuntimeAdapterSummary;
validateOptions?(input: RuntimeOptionInput): RuntimeOptions;
summarize(): RuntimeAdapterSummary;
validateOptions(input: RuntimeOptionInput): RuntimeOptions;
prepareRun?(ctx: RuntimePrepareContext): Promise<void>;
spawn(ctx: RuntimeSpawnContext): Promise<RuntimeSpawnResult>;
attach(ctx: RuntimeAttachContext): RuntimeAttachment;
@@ -275,27 +269,27 @@ type RuntimeAdapter = {
- Plain stdout 继续发 `stdout` 而不是 `agent`,避免改变 web/client event contract。Source: `apps/daemon/src/server.ts:4168-4172`
- `start` event 中的 `streamFormat` 如有客户端依赖可暂时保留为 opaque metadata,但上层代码不得再基于它分支。Source: `apps/daemon/src/server.ts:3787-3799`
- Claude CLI diagnostic tails 仍需从 raw stdout/stderr 捕获,迁移 adapter 时不能丢失诊断输入。Source: `apps/daemon/src/server.ts:3872-3882,4177-4183,4247-4264`
- Adapter 容易膨胀成 god object;第一轮只暴露上层移除 runtime dispatch 所必需的方法。实现时用现有 launch helper、protocol helper、close-policy helper 组合出 adapter,不为了抽象完整性迁移无关 helper。Source: `apps/daemon/src/runtimes/types.ts:37-68`, `apps/daemon/src/server.ts:3141-4269`
- Adapter 容易膨胀成 god object;实现时用 launch helper、protocol helper、close-policy helper 组合出 adapter,对外仍只暴露一个 adapter 边界。Source: `apps/daemon/src/runtimes/types.ts:37-68`, `apps/daemon/src/server.ts:3141-4269`
## Plan
- [ ] Step 1: Add adapter facade over existing runtime definitions
- [ ] Substep 1.1 Implement: add minimal public `RuntimeAdapter`, spawn, attachment, sink, and close-decision types required by upper-layer dispatch removal.
- [ ] Substep 1.2 Implement: add `getRuntimeAdapter(agentId)` by composing existing `RuntimeAgentDef` entries, parser helpers, and session helpers; keep `defs/*` in place.
- [ ] Substep 1.3 Implement: add normalized sink helpers only where needed for shared chat/connection-test attach behavior, without changing existing SSE channel names.
- [ ] Step 1: Replace runtime definitions with adapter-only boundary
- [ ] Substep 1.1 Implement: add public `RuntimeAdapter`, spawn, attachment, sink, summary, and close-decision types.
- [ ] Substep 1.2 Implement: migrate existing `RuntimeAgentDef` entries into `RuntimeAdapter` modules and remove `RuntimeAgentDef` as an exported abstraction.
- [ ] Substep 1.3 Implement: add normalized sink helpers without changing existing SSE channel names.
- [ ] Substep 1.4 Verify: unit-test adapter lookup coverage, unknown agent failure, and sink channel mapping.
- [ ] Step 2: Move stream/session attachment behind adapters
- [ ] Substep 2.1 Implement: migrate Claude/Qoder/Copilot/JSON-event/plain attachment logic into adapters.
- [ ] Substep 2.2 Implement: migrate Pi/ACP session attachment and runtime session handles into adapters.
- [ ] Substep 2.3 Implement: update `connectionTest.ts` to consume shared adapters first.
- [ ] Substep 2.4 Verify: run daemon parser/session tests plus new fake-child adapter tests.
- [ ] Step 3: Refactor chat orchestration to adapter boundary calls
- [ ] Step 3: Refactor chat orchestration to adapter-only calls
- [ ] Substep 3.1 Implement: replace `server.ts` `getAgentDef`, args building, stdin handling, and stream-format dispatch with `getRuntimeAdapter`, `runtime.spawn`, `runtime.attach`, `runtime.deliverPrompt`, and `runtime.evaluateClose` calls.
- [ ] Substep 3.2 Implement: move stdin mode, prompt delivery, env/args, and close decisions into adapter methods; move external MCP preparation, image support, or prompt budget only if required to remove upper-layer dispatch.
- [ ] Substep 3.3 Implement: preserve existing `run.acpSession` storage; introduce generic runtime session naming only if the adapter boundary cannot otherwise represent session-aware runtimes.
- [ ] Substep 3.2 Implement: move stdin mode, prompt delivery, external MCP preparation, image support, prompt budget, env/args, and close decisions into adapter methods.
- [ ] Substep 3.3 Implement: preserve `run.acpSession` compatibility while introducing generic runtime session naming.
- [ ] Substep 3.4 Verify: run daemon tests and add regression coverage for empty-output, structured error, and ACP clean SIGTERM behavior.
- [ ] Step 4: Remove upper-layer format knowledge
- [ ] Substep 4.1 Implement: replace prompt mode and Critique Theater format checks with adapter capabilities only where those checks are currently in upper-layer dispatch paths.
- [ ] Substep 4.1 Implement: replace prompt mode and Critique Theater format checks with adapter capabilities.
- [ ] Substep 4.2 Implement: add guard/regression check preventing `getAgentDef`, direct runtime launch/protocol field access, or runtime format dispatch in `server.ts` and `connectionTest.ts`.
- [ ] Substep 4.3 Verify: run `pnpm --filter @open-design/daemon test`, `pnpm --filter @open-design/daemon typecheck`, `pnpm guard`, and `pnpm typecheck`.