Skip to content

feat(cli): add ACP session creation and listing - #3744

Open
Sun-GLiang wants to merge 11 commits into
apache:mainfrom
Sun-GLiang:feat/acp-session-lifecycle
Open

feat(cli): add ACP session creation and listing#3744
Sun-GLiang wants to merge 11 commits into
apache:mainfrom
Sun-GLiang:feat/acp-session-lifecycle

Conversation

@Sun-GLiang

@Sun-GLiang Sun-GLiang commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add the Runtime Host seams needed by ACP Session lifecycle work: a bounded single-page Session catalog reader and a one-shot subscription open that never retries on a replacement Host.
  • Add an ACP connection-scoped Session registry that creates durable Maka Sessions, continuously consumes one subscription per Session, tracks the latest snapshot, records subscription failures, and cleans up all adapter-owned resources on EOF.
  • Implement ACP session/new and cursor-paginated session/list through the official SDK, including canonical cwd filtering, legacy-record omission, stable Runtime Host error mapping, and explicit rejection of unsupported MCP server and additional-directory inputs.
  • Extend PR1's transport-only startup contract by owning the deliberately deferred Runtime Host bootstrap: the first implemented Host-backed Session method lazily creates one shared, abortable CLI Host context, while initialize and unsupported methods remain Host-independent.
  • Keep session/close unadvertised and returning -32601; durable Runtime Host Sessions are never deleted or archived by adapter cleanup. Active-turn cancellation and adapter-state removal remain follow-up work in PR4 and will be revalidated before that PR starts.

Refs #3132
Builds on #3658 (merged)

PR1 alignment

  • Synchronized with the current apache/maka:main after feat(cli): add ACP stdio server foundation #3658 merged; the merge preserved both PR2's Session catalog page exports and main's Connection catalog exports.
  • Reuses PR1's official SDK transport and child-process harness rather than introducing a second ACP server path.
  • Implements the Runtime Host connection work deliberately deferred by PR1, without weakening PR1's Host-free initialize contract.

Conflict resolution

  • Resolved packages/runtime-host/src/client/index.ts by retaining the PR2 RuntimeHostSessionCatalogPage / cursor exports and main's RuntimeHostConnectionCatalogEntry / snapshot exports.
  • Updated session-subscription-capacity.json to the merged protocol epoch 87, so the CI protocol-compatibility guard accepts the additive export.

Verification

  • Focused ACP/Host-bootstrap tests — 54 passed, 0 failed.
  • Focused Runtime Host catalog/reconnect/session tests — 32 passed, 0 failed.
  • Protocol epoch guard against the current main — passed.
  • npm run build — passed.
  • npm run build:test — passed.
  • npm run typecheck — passed.
  • npm run lint — passed.
  • npm run format:check — passed.
  • The full Runtime Host suite still contains an unrelated WorkHub correction failure (candidate_set_stale) in code outside this PR; the obsolete task-ledger dist test is removed by the clean build:test flow.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex assisted with implementation, tests, rebase/conflict resolution, verification, and review. Every PR2 commit includes a Generated-by: Codex trailer.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@Sun-GLiang
Sun-GLiang force-pushed the feat/acp-session-lifecycle branch from 67c6644 to 4ed9973 Compare August 26, 2026 10:08
@Sun-GLiang
Sun-GLiang marked this pull request as ready for review August 26, 2026 10:20
@github-actions github-actions Bot added the effort/XL Over 1000 readable lines label Aug 27, 2026
@Sun-GLiang
Sun-GLiang force-pushed the feat/acp-session-lifecycle branch from 4ed9973 to 951bd81 Compare August 29, 2026 01:14

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

Thanks for adding the ACP session lifecycle in a focused layer. I found two production-path issues that look worth addressing before this moves forward. These are suggestions from an outside review, so please do push back if an ACP lifecycle or bootstrap guarantee changes either premise.

AI-assisted review disclosure: Codex ran independent protocol, lifecycle, and test analysis lanes; Astro-Han is the contributor of record for this review.


let subscription: AcpSessionSubscription;
try {
subscription = await connection.openSessionSubscriptionOnce({

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.

[P1] (category ① — normal supported path)

Thanks for keeping Runtime Host as the Session authority. One lifecycle limit still looks reachable on the normal session/new path: this creates the durable Session first, then opens and retains one subscription for every created Session until the entire ACP stdio connection exits. Runtime Host caps a connection at 16 subscriptions, and this PR has no per-Session close/release operation, so the 17th create returns an error after the Session was already committed; each retry creates another catalog entry and fails again. Could the adapter either make attachment lazy/releasable, or reserve capacity with the real subscription owner before committing the Session, and cover 17+ creates on one real ACP connection? Please feel free to push back if the ACP client lifecycle guarantees the process is replaced before this limit.

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.

Verified: the 17th create could reach session.create before the Host rejected subscription.open, leaving a durable Session behind. Fixed in 419c386 without changing the approved PR2 lifecycle boundary. The registry now reserves the shared Runtime Host per-connection subscription capacity from active + pending attachments before session.create, including concurrent requests; the 17th request is rejected before persistence, and capacity is released when a subscription terminates. The Host and adapter use one shared limit constant. Coverage includes concurrent admission, released-slot reuse, and 17 creates through the official ACP SDK against a real Runtime Host.

I am pushing back on making attachment lazy/releasable or adding a connection pool in this PR: those would conflict with PR2s one shared Host context, immediate continuous subscription consumption, and deliberately unimplemented session/close. PR2 therefore keeps a maximum of 16 simultaneously attached Sessions; broader live-session support should be revalidated with the planned close lifecycle rather than changing that architecture here.

Comment thread packages/cli/src/acp/stdio-server.ts Outdated
): Promise<number> {
const sessionRegistry = new AcpSessionRegistry({
connect: async (signal) => {
const context = await (dependencies.connectRuntimeHostCli ?? connectRuntimeHostCli)({

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.

[P2] (category ② — reasonable failure/recovery path)

Thanks for reusing the existing Host bootstrap. The ACP registry only consumes the connection and close(), but connectRuntimeHostCli() also reads the entire connection/model catalog before returning. That makes otherwise healthy session/list and session/new fail as connection_failed whenever the unrelated connection catalog is temporarily unreadable or revision-churning, before a Session request is sent. Would a connection-only/lazy-catalog bootstrap be a better fit here, with a regression where the connection catalog fails while session.catalog.query remains healthy? Please push back if ACP intentionally requires a healthy model catalog even for listing existing Sessions.

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.

Verified: ACP session/new and session/list do not require the model connection catalog, so the previous bootstrap coupled healthy Session operations to an unrelated catalog read. Fixed in 419c386 by extracting connectRuntimeHostCliConnection for connection/profile ownership and cleanup; the existing connectRuntimeHostCli remains the catalog-reading wrapper for current CLI/TUI callers, while ACP uses the connection-only seam. A regression makes the model catalog reader throw and confirms the connection-only bootstrap still succeeds; existing catalog abort/cleanup behavior remains covered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/XL Over 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants