fix(coding-agent): answer ACP prompts only once the session admits the next turn - #800
Conversation
6a6ab06 to
ac97743
Compare
|
Missing CHANGELOG entry: this fixes a user-visible ACP race (immediate follow-up prompt rejected with "Agent is already processing"). Please add a bullet under |
|
Reworked per review: ACP prompts now queue behind in-flight work ( |
3f68e8d to
bf2c00e
Compare
bf2c00e to
5d7d4cf
Compare
|
Macroscope has since reviewed this pull request. An earlier review was skipped by a cost limit; a review has now completed, so that notice no longer applies. |
# Conflicts: # packages/coding-agent/CHANGELOG.md
# Conflicts: # packages/coding-agent/CHANGELOG.md # packages/coding-agent/src/modes/acp/acp-mode.ts # packages/coding-agent/src/modes/daemon/daemon-protocol.ts # packages/coding-agent/test/suite/acp-mode.test.ts
… merge Renumber owned prompt cancellation to schema revision 20 (17-19 landed on main), adapt compatibility gating to the requirements-array form, and return stopReason "cancelled" for a prompt parked behind the terminal lifecycle when a cancellation drops it before it starts.
Conflict resolution (3 files, all CHANGELOG):
- packages/{ai,coding-agent,tui}/CHANGELOG.md — keep fork [Unreleased]
bullets (Z.AI reasoning_effort; mermaid/selection/statusline/cwd/ctrl+c/
config-scope panes/agents-view fixes), take upstream's finalized
[0.7.4] sections verbatim
Upstream payload: model search intent ranking (PrimeIntellect-ai#539), ACP resident
session lifecycle hardening (PrimeIntellect-ai#1494), ACP follow-up prompt queueing
(PrimeIntellect-ai#800), v0.7.4 release prep (version bumps, catalogs).
Fork features verified intact after merge: mermaid transform + settings
toggle, tui Markdown transform hook, config scope panes, cwd statusline,
grok-mermaid dependency, Z.AI supportsReasoningEffort catalog entries.
…e next turn (PrimeIntellect-ai#800) * fix(coding-agent): queue ACP prompts behind in-flight work * fix(acp): keep queued-prompt semantics through the resident lifecycle merge Renumber owned prompt cancellation to schema revision 20 (17-19 landed on main), adapt compatibility gating to the requirements-array form, and return stopReason "cancelled" for a prompt parked behind the terminal lifecycle when a cancellation drops it before it starts. --------- Co-authored-by: Sebastian <sebastian@primeintellect.ai>
Linear: ENG-5376
ACP could answer
session/promptafter its first idle check even though injected work had restarted the session. An immediate follow-up was then rejected asAgent is already processing.Without this change:
waitForHeadlessCompletion()observes an idle session.end_turn.Re-check
connection.waitForIdle()before returning the ACP response. This closes the admission race seen in multi-turn Verifiers runs.#881 fixes a different gap:
waitForIdle()did not include a continuation already scheduled bycompact.run. One makes the idle check complete; this PR puts a final check at the response boundary.Verification:
Note
Queue ACP follow-up prompts behind in-flight work and cancel queued turns before delivery
stopReason="cancelled"and passesstreamingBehavior:"followUp",queueIfBusy:truetopromptAndWaitAgentSession.promptAndWaitaccepts an optionalAbortSignalviaoptions.signal; on abort it cancels queued session-owned turn actions matching theagentMessageIdbefore delivery and rejects the completionowned_prompt_cancellation(default-on) andcancelOwnedflag oncancel_prompt_admissioncommands allow cancelling session-owned prompts that have not started; gated by protocol 7, schema revision 20DaemonAgentConnectionsendscancelOwned:truewhen the server advertises the capabilitycancel_prompt_admissionwithcancelOwned=truenow aborts an owned admission's controller in daemon-mode.ts; clients below protocol 7 / schema 20 will not send the flag and owned cancellation is a no-op for themMacroscope summarized 7ce5609.
Note
Medium Risk
Changes daemon worker lifecycle, persisted launch environment, and ACP turn-boundary semantics that verifiers and embedders depend on; behavior is heavily tested but mis-timed idle or env handling could still break reconnect or scoring.
Overview
ACP
session/promptnow awaitsconnection.waitForIdle()before returningend_turn, so clients are not told the turn finished while injected work (e.g. subagent messages) has already restarted the session and would reject an immediate follow-up with “Agent is already processing.”ACP session lifecycle and scoring metadata:
session/newreserves the single-session slot before the first await, subscribes beforegetInitialSnapshot(), and fails setup cleanly if the snapshot read errors. After headless completion, asession_info_updatecarries namespacedquiescence(outstandingSubagents,remainingAutonomousContinuations) plus autonomous state from a live roster snapshot; snapshot failures at emission time propagate instead of reporting a false zero.Daemon / ACP residency: Normal ACP sessions (with a session file) use resident workers so disconnect/reconnect can reattach;
--no-sessionACP stays client-owned. Resident creates always forwardlaunchEnvfrom the caller (model endpoint, tokens, proxy, etc.). The supervisor persistslaunchEnvon resident worker descriptors for recovery after restart and strips it when promoting to client-owned, with integration tests for env across worker recovery and live IPython namespace across ACP reconnect.Reviewed by Cursor Bugbot for commit ac97743. Bugbot is set up for automated code reviews on this repo. Configure here.