Skip to content

fix(tui): restore queued messages when a session is interrupted - #49018

Open
baymaxibk wants to merge 1 commit into
anomalyco:devfrom
baymaxibk:fix/tui-restore-queued-messages-on-interrupt
Open

baymaxibk wants to merge 1 commit into
anomalyco:devfrom
baymaxibk:fix/tui-restore-queued-messages-on-interrupt

Conversation

@baymaxibk

Copy link
Copy Markdown

Issue for this PR

Closes #33812

Revives #39189 by @chaitanyarahalkar (auto-closed by automated-pr-cleanup, not rejected on merits). All credit for the approach to them; I re-based the change onto current dev, re-verified, and am re-submitting it.

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

If you type a follow-up while the agent is streaming and then press ESC twice to interrupt, the message you typed is lost. It is still persisted server-side, but no turn ever runs for it and the QUEUED badge disappears, so you have to retype it.

The cause is that the interrupt handler aborts without checking whether a user message arrived after the running assistant turn started. runLoop only picks up a queued message when the current assistant message completes, so interrupting before that point leaves the message with nothing to consume it.

Before aborting, the handler now collects user messages newer than the running turn and puts their text and file parts back into the prompt box via PromptRef.set - the same call session.undo already uses to return a reverted message's text to the input. It only restores when the prompt is empty, so it will not overwrite a draft you have already started typing.

This uses the client-side restore rather than re-arming the runner after cancel. Re-arming would make double-ESC sometimes stop the session and sometimes immediately start another turn, and when you interrupt you usually want to edit the message before resending it anyway.

Known limitation (unchanged from the original PR): the orphaned user message still sits in the transcript. Removing it needs a session.revert call, which seemed like a separate change.

How did you verify your code works?

bun test test/prompt/queued.test.ts in packages/tui - 4 tests covering the queuedMessages selector: one queued message, several stacked up, an idle session, and an abandoned turn that a later turn already completed.

Full packages/tui suite on Windows: 197 pass, 1 skip, 1 fail - the failure (abbreviates paths within home boundaries) is pre-existing on clean dev on Windows (POSIX /tmp path assumption) and unrelated to this change. tsgo --noEmit could not complete locally (OOM on my machine); relying on CI for typecheck.

To reproduce by hand: start a turn, type a second message while it is streaming, then press ESC twice. Before this change the input box is empty and the text is gone; after it, the text is back in the box.

Screenshots / recordings

No visual change - the diff is behavioural. The observable difference is that the prompt box contains your text after an interrupt instead of being empty.

Checklist

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

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.

ESC interrupt clears followup queue instead of preserving it

2 participants