Skip to content

refactor(daemon): split acp.ts + pi-rpc.ts into an agent-protocol/ capability-barrel - #5200

Merged
AmyShang-alt merged 3 commits into
nexu-io:mainfrom
leonaburime-ucla:refactor/agent-protocol-barrel
Jul 8, 2026
Merged

refactor(daemon): split acp.ts + pi-rpc.ts into an agent-protocol/ capability-barrel#5200
AmyShang-alt merged 3 commits into
nexu-io:mainfrom
leonaburime-ucla:refactor/agent-protocol-barrel

Conversation

@leonaburime-ucla

Copy link
Copy Markdown
Contributor

Why

apps/daemon/src/acp.ts (1,744 lines) and apps/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.ts in 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, and pi-rpc.ts reached into acp.ts for 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-systems pattern), 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.ts into a single agent-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 (the attachAcpSession orchestrator), each behind the acp/ barrel.
  • pi-rpc/ concern subdir — internal (shared guards/types), events (mapPiRpcEvent), models (parsePiModels), session (attachPiRpcSession), behind the pi-rpc/ barrel.
  • Moving createJsonLineStream into core/ dissolves the former pi-rpc → acp import edge into a pure star topology (allowedEdges: [], foundation core) — no concern imports another concern; both import only core/.
  • Root barrel 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).
  • Every function body moved byte-identically (line-slice moves, no rewrites). Every file carries a @module docblock, every export is JSDoc'd, and a module README.md documents 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 on main yet; this PR produces the full documented structure and the guard entry lands once the infra does.

Surface area

  • UI — new page / dialog / panel / menu item / setting / empty state in apps/web or apps/desktop
  • Keyboard shortcut — new or changed
  • CLI / env var — new od subcommand or flag, new tools-* flag, or new OD_* env var
  • API / contract — new /api/* endpoint, new SSE event, or changed shape in packages/contracts
  • Extension point — new entry under skills/, design-systems/, design-templates/, or craft/
  • i18n keys — added new translation keys
  • New top-level dependency — new entry in the root package.json
  • Default behavior change — default model/setting, file/SQLite schema, auto-network, auto-install
  • None — internal refactor, docs, tests, or translation update only

Validation

  • 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).
  • Public-surface: old union of acp.ts + pi-rpc.ts exports (10) == new root-barrel names (10), exactly.
  • Byte-identity: 1,960 code lines, multiset-identical between the originals and the new non-barrel files — 0 dropped, 0 added (only deltas are import-path rewrites, added export keywords for barrel re-export, and doc-comments). Re-verified after the doc pass (still 1960==1960).
  • Runtime smoke: barrel resolves all 8 runtime exports; runtimes/defs/shared.ts + connectionTest.ts load clean (server.ts is @ts-nocheck, so its attachAcpSession/attachPiRpcSession import was runtime-checked, not just type-checked).

LA added 2 commits July 5, 2026 16:47
…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).
@lefarcen lefarcen added size/XXL PR changes 1500+ lines risk/high High risk: apps/desktop, daemon, auth, migration, workflows, package deps type/refactor Code refactor (no behavior change) labels Jul 6, 2026
@lefarcen
lefarcen requested a review from nettee July 6, 2026 00:05
@lefarcen lefarcen added the needs-validation Runtime change detected; needs human or /explore agent validation. label Jul 6, 2026
@lefarcen

lefarcen commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🧪 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 nettee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.

Comment thread apps/daemon/src/acp.ts
});
}

export function attachAcpSession({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 nettee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.

@lefarcen
lefarcen requested a review from AmyShang-alt July 6, 2026 00:35
@leonaburime-ucla

Copy link
Copy Markdown
Contributor Author

@nettee @lefarcen When will all these PRs be reviewed and merged?

@lefarcen

lefarcen commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

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.

@AmyShang-alt

Copy link
Copy Markdown
Contributor

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.

@AmyShang-alt AmyShang-alt added validated Runtime change validated (via /explore Pass or manual QA). and removed needs-validation Runtime change detected; needs human or /explore agent validation. labels Jul 8, 2026
@AmyShang-alt
AmyShang-alt added this pull request to the merge queue Jul 8, 2026
@lefarcen

lefarcen commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

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.

Merged via the queue into nexu-io:main with commit 91f22f3 Jul 8, 2026
23 checks passed
xxiaoxiong pushed a commit to xxiaoxiong/open-design that referenced this pull request Jul 13, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk/high High risk: apps/desktop, daemon, auth, migration, workflows, package deps size/XXL PR changes 1500+ lines type/refactor Code refactor (no behavior change) validated Runtime change validated (via /explore Pass or manual QA).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants