fix(cli): user-initiated abort no longer kills the ACP runner process - #1678
Open
FelixShowX wants to merge 1 commit into
Open
fix(cli): user-initiated abort no longer kills the ACP runner process#1678FelixShowX wants to merge 1 commit into
FelixShowX wants to merge 1 commit into
Conversation
AcpBackend.cancel() emits status 'stopped' after a successful session/cancel, which runAcp treated as fatal backend death — so a user tapping stop in the app killed the whole session process instead of just cancelling the turn. Track user-initiated aborts (userAbortInFlight) and treat the matching stopped status as a normal turn end (marked 'cancelled'). The flag is cleared at every new turn start and when cancel() throws, so a stale flag can never mask a genuine backend failure.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When the user taps "stop" in the mobile app during an ACP agent turn (gemini / opencode / any generic ACP backend), the CLI process crashes and the whole session dies, instead of just cancelling the in-flight turn.
Root cause
AcpBackend.cancel()emitsstatus: 'stopped'after a successfulsession/cancel:But
runAcptreats anystoppedstatus as fatal backend death:So a perfectly healthy user abort is indistinguishable from the backend dying, and the runner shuts the session down. The turn IS cancelled correctly on the agent side — the runner just kills itself right after.
Fix
Track user-initiated aborts and treat the resulting
stoppedas a normal (cancelled) turn end:handleAbort()setsuserAbortInFlight = truebefore callingbackend.cancel()stoppedstatus arrives with that flag set: reset thinking/keepAlive, resolve the pending turn (instead of rejecting it), and mark the turncancelled— the runner stays alive and the next prompt workscancel()throws (the abort never reached the agent). An abort that arrives while the session is idle — e.g. network latency delivers it right after the turn ended naturally — would otherwise leave the flag set, and a later genuine backend failure would be misread as a user abort, leaving the runner alive with a dead backend. Bounding the flag's effect to its own turn prevents that'cancelled'instead of'completed'Repro
happy acp <agent>(any ACP agent)Error: <agent> backend stopped: Cancelled by user. After: turn ends as cancelled, session stays online, next prompt works.Notes
stoppedstatus without a preceding user abort (same-turn) still shuts the runner downAcpSessionManager.endTurnalready accepts'cancelled'— no other files touched