Skip to content

fix(session): restart the loop for queued input stranded by an interrupt - #40956

Open
zhihanliu-collab wants to merge 1 commit into
anomalyco:devfrom
zhihanliu-collab:lzy/fix-queued-input-stranded-on-cancel
Open

fix(session): restart the loop for queued input stranded by an interrupt#40956
zhihanliu-collab wants to merge 1 commit into
anomalyco:devfrom
zhihanliu-collab:lzy/fix-queued-input-stranded-on-cancel

Conversation

@zhihanliu-collab

Copy link
Copy Markdown

Issue for this PR

Closes #40955

Type of change

  • Bug fix

What does this PR do?

Interrupting a turn (Esc, or POST /session/:id/abort) silently drops queued input. The queue is durability-only: user messages sent while a turn runs are persisted immediately and normally get picked up by a later loop iteration (steer semantics). But SessionPrompt.cancel only stops the run — after the abort nothing ever restarts the loop, so any user message sitting behind the last assistant message is stranded in history forever, never answered. In the TUI this shows up as the QUEUED tag silently vanishing.

The fix sits right after the cancel settles: re-read the reconstructed history the same way SessionPrompt.run does (MessageV2.filterCompactedEffect + MessageV2.latest), and if there is a user message behind the last assistant message — i.e. queued input that was never picked up — fork a fresh loop for it. Bare interrupts deliberately keep today's semantics: when nothing was queued behind the aborted turn, the interrupted in-flight question is not re-answered (second test below pins this, and by extension interrupt→interrupt still gives a full stop, since a re-esc'd turn leaves its new aborted assistant message tail-most).

How did you verify your code works?

Two regression tests in packages/opencode/test/session/prompt.test.ts against the test LLM server:

  • cancel restarts the loop for queued input stranded behind the aborted turn — turn hung mid-stream, user message admitted while busy, cancel; the stranded message gets a finished assistant reply afterwards and the session returns to idle.
  • cancel without queued input does not restart the loop — bare cancel with only the in-flight question; no new turn is started, nothing gets answered, session stays idle.

Plus: full test/session/ suite (399 tests) green, full prompt.test.ts (59) green, tsgo --noEmit clean.

Screenshots / recordings

N/A (server-side behavior change).

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Interrupting a turn (Esc / POST /session/:id/abort) silently dropped
queued input: user messages admitted while the turn was running stay
persisted in history behind the aborted assistant message, but nothing
restarts the run loop after a cancel, so they are never answered.

After SessionRunState.cancel settles, look at the reconstructed history
the same way the run loop does: if there is a user message behind the
last assistant message (queue input that was never picked up), fork a
fresh loop for it. Bare interrupts keep today's semantics — with nothing
queued, the interrupted question is not re-answered.

Regression tests both directions: stranded queued input gets answered
after cancel; a bare cancel starts no new turn.

Fixes anomalyco#40955
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search, I found one potentially related PR:

PR #39189fix(tui): restore queued messages when a session is interrupted
#39189

This PR addresses a similar issue with queued messages being lost during session interrupts, though from the TUI perspective. Since your PR (40956) is fixing the server-side SessionPrompt.cancel behavior to restart the loop for stranded queued input, PR #39189 may be related or partially overlap in scope. You may want to check if that PR was merged and whether your fix complements or supersedes any changes made there.

The other results (feat PRs around queued messages) are feature additions rather than related bug fixes.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Queued messages are silently dropped when a turn is interrupted

1 participant