refactor(daemon): split acp.ts + pi-rpc.ts into an agent-protocol/ capability-barrel - #5200
Conversation
…ility-barrel Move acp.ts (1744) and pi-rpc.ts (684) into a single agent-protocol/ capability-barrel module: a core/ foundation kernel (shared JSON-line-stream transport) plus per-protocol concern subdirs (acp/, pi-rpc/), each with a barrel. The shared createJsonLineStream transport moves into core/, dissolving the former pi-rpc -> acp edge into a clean star topology (allowedEdges: []). Pure structural move: every function body byte-identical (verified via line-multiset, 1960==1960, 0 added/0 dropped); public surface reproduced exactly (10 names) through the root barrel. All importers repointed to ./agent-protocol/index.js (server.ts, connectionTest.ts, runtimes/defs/shared.ts + 5 test files). Guard registration deferred (check-barrel-imports infra not on main yet).
…nt-protocol/ Documentation only — zero code lines changed (verified by line-multiset, 1960==1960). Every file gets a @module docblock, every exported symbol gets JSDoc, and README.md mirrors design-systems/README.md (What changed / Why this shape / Import conventions / Directory structure / Consumers).
|
🧪 Queued for QA validation — this PR touches runtime behavior that needs a manual QA pass before it's merged. Nothing needed from you right now; we'll update here once that validation is done. Thanks for the contribution! 🙏 |
nettee
left a comment
There was a problem hiding this comment.
I found one refactor regression worth fixing before this module shape gets copied elsewhere: deleting the legacy ACP entrypoint leaves one daemon verification script pointing at a built file that no longer exists. I wasn't able to rerun the daemon Vitest suite locally in this worktree because vitest is not installed here.
| }); | ||
| } | ||
|
|
||
| export function attachAcpSession({ |
There was a problem hiding this comment.
Deleting the ACP entrypoint here leaves apps/daemon/scripts/verify-amr-real-vela.mjs:29 importing ../dist/acp.js, but this refactor stops producing that build artifact. After the next pnpm --filter @open-design/daemon build, the script's dynamic import will fail with ERR_MODULE_NOT_FOUND, which breaks one of the few real-vela smoke verifiers for this subsystem. Please either keep a thin compatibility shim at src/acp.ts that re-exports attachAcpSession from agent-protocol, or update the script in this PR to import the new built path (dist/agent-protocol/index.js or dist/agent-protocol/acp/index.js) so the manual validation path stays usable.
There was a problem hiding this comment.
Good catch — fixed in e26a776. Repointed the dynamic import from ../dist/acp.js to ../dist/agent-protocol/index.js (the root barrel re-exports attachAcpSession). Chose the repoint over a compat shim since a re-export shim is exactly the leftover this capability-barrel refactor is meant to remove. Verified locally: pnpm --filter @open-design/daemon build emits dist/agent-protocol/index.js, and the script's dynamic import resolves attachAcpSession as a function.
…l barrel The acp.ts -> agent-protocol/ split stops emitting dist/acp.js, so the real-vela smoke verifier's dynamic import of ../dist/acp.js would fail with ERR_MODULE_NOT_FOUND after a clean build. Repoint it to ../dist/agent-protocol/index.js, which re-exports attachAcpSession. Verified: daemon build emits dist/agent-protocol/index.js and the script's import resolves attachAcpSession as a function.
nettee
left a comment
There was a problem hiding this comment.
@leonaburime-ucla I re-reviewed the current e26a7764c4c30ff93c1274c00a5b03f2b152a37c head and verified the live PR diff is limited to the agent-protocol/ barrel split, importer rewires, test import updates, and the verify-amr-real-vela dist-path fix. I did not find additional correctness or maintainability regressions in the changed ranges beyond the already-addressed smoke-script import issue, and the public adapter surface looks preserved across the new barrels. I couldn't rerun the daemon typecheck/Vitest suite in this worktree because node_modules are absent here, but the scoped refactor itself looks consistent. Nice cleanup on a large protocol module.
|
Hey @leonaburime-ucla — on this PR, the code-review side is already in good shape and CI is green. The remaining step is QA validation from @AmyShang-alt; once that lands, a maintainer can make the final merge call. I can't promise an exact merge time from here, but it's waiting on that validation rather than another code-review round. |
|
QA passed for PR #5200. Verified current head e26a776 on namespace pr5200 against daemon http://127.0.0.1:61539. ACP/AMR runtime smoke passed: POST /api/runs with agentId=amr produced acp-json-rpc events including model status, thinking deltas, text_delta, Write tool_use for pr5200-smoke.txt, successful tool_result, usage, and final end status=succeeded. No protocol parse failure or AGENT_EXECUTION_FAILED observed. Abort smoke also passed: POST /api/runs/9767853c-1755-4a86-a7ee-58d2706efe10/cancel returned ok=true with status=canceled, cancelRequested=true, childExited=true, processGroupId=20633, exitCode=130, and no error/errorCode. This confirms the ACP runtime cancellation path still terminates the child process and settles the run cleanly. Given CI is green and the high-risk ACP runtime path plus cancellation path were manually verified, QA accepts this PR. |
|
Thanks @AmyShang-alt — that QA pass is exactly what this one was waiting on. @leonaburime-ucla, the review + validation side is now complete on the current head; the remaining step is the final maintainer merge call. |
…pability-barrel (nexu-io#5200) * refactor(daemon): split acp.ts + pi-rpc.ts into agent-protocol/ capability-barrel Move acp.ts (1744) and pi-rpc.ts (684) into a single agent-protocol/ capability-barrel module: a core/ foundation kernel (shared JSON-line-stream transport) plus per-protocol concern subdirs (acp/, pi-rpc/), each with a barrel. The shared createJsonLineStream transport moves into core/, dissolving the former pi-rpc -> acp edge into a clean star topology (allowedEdges: []). Pure structural move: every function body byte-identical (verified via line-multiset, 1960==1960, 0 added/0 dropped); public surface reproduced exactly (10 names) through the root barrel. All importers repointed to ./agent-protocol/index.js (server.ts, connectionTest.ts, runtimes/defs/shared.ts + 5 test files). Guard registration deferred (check-barrel-imports infra not on main yet). * docs(daemon): @module docblocks, per-export JSDoc, and README for agent-protocol/ Documentation only — zero code lines changed (verified by line-multiset, 1960==1960). Every file gets a @module docblock, every exported symbol gets JSDoc, and README.md mirrors design-systems/README.md (What changed / Why this shape / Import conventions / Directory structure / Consumers). * fix(daemon): repoint verify-amr-real-vela script to the agent-protocol barrel The acp.ts -> agent-protocol/ split stops emitting dist/acp.js, so the real-vela smoke verifier's dynamic import of ../dist/acp.js would fail with ERR_MODULE_NOT_FOUND after a clean build. Repoint it to ../dist/agent-protocol/index.js, which re-exports attachAcpSession. Verified: daemon build emits dist/agent-protocol/index.js and the script's import resolves attachAcpSession as a function. --------- Co-authored-by: LA <la@LAs-MacBook-Pro.lan>
Why
apps/daemon/src/acp.ts(1,744 lines) andapps/daemon/src/pi-rpc.ts(684 lines) were two flat god-files driving the daemon's subprocess agent protocols — ACP (Agent Client Protocol, used by Hermes/Kilo/Kiro/Devin/Vibe/vela-AMR) and pi's--mode rpc.acp.tsin particular mixed JSON-RPC transport, model detection, session-update classification, artifact/tool-call suppression, and a 750-line session orchestrator in one module with no enforced internal boundaries, andpi-rpc.tsreached intoacp.tsfor its shared line-stream transport (createJsonLineStream). Editing either meant reading past every unrelated concern, and nothing stopped a new cross-file coupling from forming.This is the maintainability lift for that subsystem: split both into one navigable, boundary-shaped capability-barrel module (the
design-systemspattern), so each protocol concern can evolve on its own and the shared transport has one owner.What users will see
Nothing. This is a pure internal refactor — the public API (10 exports) and all runtime behavior are identical. QA regression surface is the subprocess-agent run path: ACP agents (Hermes, Kilo, Kiro, Devin, Vibe, vela/AMR) and pi RPC — model detection (
/api/agents), session streaming (text/thinking/tool_use/tool_result/usage), artifact-write mirroring, permission auto-reply, resume, and abort.What this does
Merges flat
acp.ts+pi-rpc.tsinto a singleagent-protocol/module:core/foundation kernel — the one shared primitive:createJsonLineStream(the streaming JSON-line transport both protocols use). Imports no sibling.acp/concern subdir —types,constants,json(value/text helpers),rpc(JSON-RPC send + error shapes),session-params,models(detection/normalization),updates(status/artifact/AMR classification),session(theattachAcpSessionorchestrator), each behind theacp/barrel.pi-rpc/concern subdir —internal(shared guards/types),events(mapPiRpcEvent),models(parsePiModels),session(attachPiRpcSession), behind thepi-rpc/barrel.createJsonLineStreamintocore/dissolves the formerpi-rpc → acpimport edge into a pure star topology (allowedEdges: [], foundationcore) — no concern imports another concern; both import onlycore/.agent-protocol/index.ts= explicit named re-exports reproducing the exact prior public surface (10 names). Every importer repointed to./agent-protocol/index.js(server.ts,connectionTest.ts,runtimes/defs/shared.ts+ 5 test files).@moduledocblock, every export is JSDoc'd, and a moduleREADME.mddocuments the shape.Scope / boundary
One subsystem, pure structural move, no logic changes. The capability-barrel guard registration (
scripts/check-barrel-imports.ts/CAPABILITY_BARREL_DOMAINS) is intentionally deferred — that infra is not onmainyet; this PR produces the full documented structure and the guard entry lands once the infra does.Surface area
apps/weborapps/desktopodsubcommand or flag, newtools-*flag, or newOD_*env var/api/*endpoint, new SSE event, or changed shape inpackages/contractsskills/,design-systems/,design-templates/, orcraft/package.jsonValidation
pnpm --filter @open-design/daemon typecheck(src + tests): green (0 errors).pnpm --filter @open-design/daemon exec vitest run acp pi-rpc structured-streams amr-acp: 5 files / 160 tests pass — matches baseline.pnpm guard: green (71/71).acp.ts+pi-rpc.tsexports (10) == new root-barrel names (10), exactly.exportkeywords for barrel re-export, and doc-comments). Re-verified after the doc pass (still 1960==1960).runtimes/defs/shared.ts+connectionTest.tsload clean (server.ts is@ts-nocheck, so itsattachAcpSession/attachPiRpcSessionimport was runtime-checked, not just type-checked).