Let the operator cancel the most recently queued message - #359
Merged
Conversation
Ctrl+G retracts the newest queue or steer item and rewrites its transcript row rather than leaving it tagged as still pending, so the readout cannot show a cancelled message as one that will still dispatch. Chose Ctrl+G because it is unclaimed by both the textarea's own bindings and this shell's other chords, and readline/Emacs users already read it as "abort", unlike Ctrl+X (cut, readline prefix). Cancellation targets the last item only. Selecting an earlier item would need a picker overlay; last-only is an honest minimum until an operator actually asks for more.
paintStreamRow now owns turning a cancelled user row into the "[cancelled]" prefix, reading a new cancelled flag on StreamRow. row.text stays exactly what the operator typed, so copy-mode and anything else reading it back are unaffected by the cancel. Regression tests now assert on captureCharFrame() before and after a cancel, not only on shell.streamLog, and cover a steer-kind cancel alongside queue in session-queue.test.ts, shell.test.ts and keybindings.test.ts.
TheGreatAxios
force-pushed
the
cl-5572-cancel-queued-message
branch
from
August 7, 2026 07:39
912a2db to
906a207
Compare
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.
Summary
SessionQueueStateand marks its transcript row with acancelledflag.paintStreamRowreads that flag and renders the[cancelled]prefix for user rows —row.textitself stays exactly what the operator typed, so copy-mode and anything else readingtextsees the original message, not a mutated one.TextareaRenderable's default bindings (checked against the bundleddefaultTextareaKeyBindingstable) and this shell's other chords. Readline/Emacs users already read it as "abort" — unlike Ctrl+X, the first attempt's pick, which is cut/prefix muscle memory.cancelLastretracts the newest item regardless of kind (queue or steer). Reaching an earlier item would need a picker overlay — not justified without an operator asking for it. Editing a queued message (also named in CL-5563) stays out of scope.Verification
bun run test— 3970 pass, 0 failbun run typecheck— cleanbun run build— cleancaptureCharFrame()), not onlyshell.streamLog— the exact gap that let the first attempt through. Covered for both queue- and steer-kind cancels, insession-queue.test.ts,shell.test.ts, andkeybindings.test.ts.withTestRenderer:Before:
Row model:
[{"text":"keep this one","meta":"queue"},{"text":"oops wrong message","meta":"queue"}]After
applyShellCancelLast:Row model:
[{"text":"keep this one","meta":"queue","cancelled":undefined},{"text":"oops wrong message","meta":"cancelled","cancelled":true}]—textis unchanged; only the flag and the paint output differ.Closes CL-5572