fix(acp): stream agent-initiated turns - #2392
Conversation
🦋 Changeset detectedLatest commit: 58f499e The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@codex review |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0d7614cba8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
0d7614c to
3ba3afa
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3ba3afa7d4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
3ba3afa to
58f499e
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 58f499e1f3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| .hooks.onDidCreateSession.register( | ||
| 'node-sdk-event-wiring', | ||
| async (event, next) => { | ||
| this.wireSession(event.handle); |
There was a problem hiding this comment.
Replace wiring when the session handle changes
When concurrent lifecycle operations materialize the same session ID, this hook can receive a newer handle while sessionWirings still contains the older handle. wireSession() treats the ID alone as idempotent, so it leaves event and interaction subscriptions attached to the obsolete scope; if the older operation then fails, its catch also removes the ID's only wiring. The successfully retained/current session consequently emits no SDK events and pending approvals or questions can hang. Make wiring ownership handle-aware so a new generation replaces the old subscription and cleanup removes only the generation installed by this hook invocation.
Useful? React with 👍 / 👎.
|
Closing this draft because its scope expanded beyond #2163 into unrelated cross-engine session lifecycle and persistence work. I will replace it with a focused adapter-only fix based on the latest main, with before/after default-engine E2E evidence. This PR remains available only as a testing and design reference. |
Related Issue
Resolves #2163
Problem
ACP projected updates only while a
session/promptrequest was active. A task- or cron-triggered main-agent turn could therefore complete in the engine while a connected ACP client received nosession/updatenotifications.Cold
session/load/resume also had snapshot/live and lifecycle races: restored producers could emit before ACP attached; overlapping create/resume/close/archive operations could invalidate the wrong materialization; failed startup could leave a stale MiniDB summary; and v1 crash recovery could duplicate, lose, or mis-correlate deferred producer input. AUserPromptSubmithook that blocked or failed before turn creation also had no correlated terminal event, while a prompt accepted during resume handoff could be persisted into the wrong turn.What changed
promptId/activationId, so an autonomous turn cannot complete an unrelated prompt.session/loadreplays only the persisted prefix, then drains the post-cut FIFO. Safe-trigger fallback is emitted before later tool/assistant history.KimiHarness. A failed caller cannot roll back a successful caller or remove handlers/session wrappers it does not own.turn.defer/turn.defer.consume, blob rehydration, ordered matching for identical legacy inputs, and a stable deferred id oncontext.append_message. Reject prompts before persistence while resume handoff owns the turn-start gate, returning a retryable busy error instead of folding the prompt into another producer's turn.next()calls, and terminal cleanup so stale materializations cannot publish or delete a newer session.@moonshot-ai/kimi-code.Verification
Before, on an untouched upstream worktree at
691ec467with the real-engine regression E2Es copied byte-for-byte:The follow-up review regressions were also run against the prior PR head
3ba3afa7before applying this hardening:void next()coverage: 68 passed and 1 failed with an observedunhandledRejection.After, at
58f499e1rebased on upstreamf1a3475a:pnpm test: 1,019 passed test files (12 skipped); 16,884 passed tests, 3 expected failures, 83 skipped, 2 todo.pnpm typecheck,pnpm lint(0 errors), andpnpm buildpassed.pnpm sherif,pnpm lint:pkg, domain-layer validation, SDK API Extractor/declaration build, changeset status, and all config/wire/state manifest freshness checks passed.git diff --checkis clean, and an independent read-only diff hygiene audit found no unrelated files, sensitive/internal identifiers, personal paths, or attribution metadata.Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update. No command, configuration, or documented UI contract changed.