apps/ui, apps/cli: queue follow-up prompts during an active agent turn - #3146
Merged
Conversation
Let users stage new prompts while the agent is running instead of having to wait for a turn to end. Staged prompts render as faint user-style bubbles and auto-dispatch FIFO when the current run ends. Users can drop them before they fire (× in the GUI, backspace on an empty editor in the CLI). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirror the .userText change from #3145 on the faint queued variant so the two bubble styles read as the same column on the right, with queued items sitting just above the composer as drafts-in-waiting. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youknowriad
force-pushed
the
claude/distracted-einstein-aa1915
branch
from
April 20, 2026 11:09
a1aab83 to
b6fb5d0
Compare
As the queue grows, the composer area pushes the scroll container up and the tail of the transcript can slip out of view. Include the queue length in the auto-scroll effect so the newest messages stay visible when a prompt is staged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
📊 Performance Test ResultsComparing 49604e7 vs trunk app-size
site-editor
site-startup
Results are median values from multiple test runs. Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff) |
2 tasks
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.
Related issues
Closes STU-1574
How AI was used in this PR
Claude (Opus 4.7) wrote the code end-to-end based on research into how Claude Code, opencode, Cursor, Aider, and pi handle mid-turn input, and a walk-through of how the GUI (
useAgentRun) and CLI (AiChatUI) currently block submits. I reviewed each diff before committing and asked for the queued-prompt visual to be restyled once before landing.Proposed Changes
Today both surfaces block new input while the agent is running — you have to wait for a turn to finish before typing the next instruction. This adds a queue on both sides so follow-ups can be staged mid-turn and auto-dispatch once the current run ends, with a way to discard them before they fire.
apps/ui (
useAgentRun+ session-view)queuedPrompts: QueuedPrompt[]in the reducer withqueue_append/queue_remove/queue_shift/queue_clearactions.run_endednow preserves the queue across run boundaries.startRun.sendMessagequeues wheneverphase !== 'idle', questions are pending, or the queue already has items (preserves FIFO). An effect auto-dispatches the head whenphase === 'idle', guarded by adispatchingQueuedRefref to prevent duplicate runs during the async window between start-call andsend_start. On queued-dispatch failure the whole queue is cleared so a broken backend doesn't cascade errors.Composerstays enabled during a run: the primary button switches to "Queue" and a Stop button shows alongside it. Placeholder text swaps between "Set your next instruction…" and "Queue a follow-up instruction…".QueuedPromptscomponent renders staged prompts above the composer as faint user-style bubbles (matching.userTextshape: left-aligned,18px 18px 18px 8pxcorners, 4% accent tint, dashed border, muted text). Each bubble has an × to discard before it fires.apps/cli (
AiChatUI, pi-tui)queuedPrompts: string[]and a persistentqueuedContainer: Containermounted betweenmessagesand the editor.editor.onSubmitnow branches: ifsubmitResolveis set (idle), resolve as before; if_inAgentTurnis true, push the prompt ontoqueuedPromptsand clear the editor.waitForInputdrainsqueuedPrompts.shift()immediately when the queue is non-empty, so the existingwhile (true) { waitForInput(); runAgentTurn(...) }loop incommands/ai/index.tspicks up follow-ups without any change on the caller side. Queued slash commands still route correctly when dequeued.showLoaderre-attaches trailing children in order[loader, queuedContainer, editor]so the thinking loader sits above staged bubbles, which sit above the editor.backspace to unqueuewhenever the queue is non-empty.↳ textwith a muted slate-on-very-light-blue style (#e8eef5bg,#5a6b7dfg) — visually the CLI analogue of the dashed bubble in the GUI./clearwipes the queue alongside the transcript.Testing Instructions
apps/ui
apps/cli
npm run cli:build && node apps/cli/dist/cli/main.mjsinto an AI chat.↳ …) should appear just above the editor, below the loader./clearwhile a queue exists — queue and transcript should both wipe.Pre-merge Checklist
npm run typecheckclean forapps/uiandapps/cli.npm test -- apps/cli/ai/tests/ui.test.ts(6/6) andapps/cli/commands/ai/tests/ai.test.ts(21/21) pass. TheclearTranscripttest needed a tiny stub for the newqueuedPromptsfield (tests useObject.create(AiChatUI.prototype)and stub only the fields they exercise).#e8eef5/#5a6b7drelies on truecolor for the muted look.🤖 Generated with Claude Code