7.5 KiB
/queue Slash Command & Auto-Queue Toggle — Technical Spec
Problem
Users need a way to queue a follow-up prompt while the agent is mid-response. This requires a new slash command, an auto-queue toggle in the status bar, validation logic, a workspace action to route the prompt, and updates to the pending user query block to support dismissal.
Relevant Code
app/src/search/slash_command_menu/static_commands/commands.rs (288-297)—QUEUEstatic command definitionapp/src/terminal/input/slash_commands/mod.rs (739-768)—/queueexecution handlerapp/src/terminal/input.rs—submit_queued_prompt(re-submits queued prompts through slash/skill/plain-text routing) andmaybe_queue_input_for_in_progress_conversation(auto-queue toggle bottleneck)app/src/workspace/action.rs (453-456)—QueuePromptForConversationworkspace action variantapp/src/workspace/view.rs (19634-19658)— workspace-level handler that routes toTerminalViewapp/src/terminal/view/pending_user_query.rs— pending query block insertion, removal, and auto-send logicapp/src/ai/blocklist/block/pending_user_query_block.rs— pending block view with dismiss buttonapp/src/ai/blocklist/block/status_bar.rs— auto-queue toggle button in the warping indicatorapp/src/ai/blocklist/context_model.rs—queue_next_prompt_enabledstateapp/src/terminal/view.rs:18101—active_ai_blockhelper (skips pending query blocks)app/src/terminal/view.rs:20044—last_ai_blockhelper (skips pending query blocks)app/src/terminal/view/init.rs—TOGGLE_QUEUE_NEXT_PROMPT_KEYBINDING(Cmd+Shift+J)
Current State
The codebase already has a PendingUserQueryBlock and send_user_query_after_next_conversation_finished mechanism used by /compact-and and /fork-and-compact. These commands queue a prompt that fires after summarization completes. The /queue command reuses this infrastructure for a simpler case: queue a prompt during any in-progress conversation (no summarization involved).
Prior to this change, PendingUserQueryBlock had no dismiss functionality, and active_ai_block/last_ai_block did not account for pending query blocks at the tail of the rich content list.
Proposed Changes
1. Slash command registration
New QUEUE static command in commands.rs with:
- Required argument (the prompt text).
- Availability:
AGENT_VIEW | ACTIVE_CONVERSATION | NO_LRC_CONTROL. requires_ai_mode: true.- Gated behind
FeatureFlag::QueueSlashCommand(dogfood). The command only appears in the slash command menu when the flag is enabled.
2. Command execution (slash_commands/mod.rs)
The handler validates two preconditions:
- Active conversation exists (else error toast).
- Prompt argument is non-empty (else error toast).
Then checks conversation status:
- If
is_in_progress()oris_blocked(): dispatchesWorkspaceAction::QueuePromptForConversation { prompt }. - If idle (conversation finished): sends the prompt immediately via
submit_queued_prompt, which routes through slash command / skill / plain-text detection.
3. Workspace action routing (action.rs, view.rs)
New QueuePromptForConversation { prompt } variant on WorkspaceAction. The workspace handler resolves the active terminal view and calls terminal.send_user_query_after_next_conversation_finished(prompt, interruptible: true, ctx). The interruptible parameter controls whether the pending block shows a "Send now" button; /queue and auto-queue set this to true, while summarization-triggered queuing (/compact-and, /fork-and-compact) sets it to false.
4. Dismiss and Send-now support on PendingUserQueryBlock
- Block now owns a
ViewHandle<ActionButton>close button (X icon,ButtonSize::XSmall,NakedTheme) and an optionalViewHandle<ActionButton>send-now button (Play icon), created only when the block is constructed withinterruptible: true. - New
PendingUserQueryBlockAction::{Dismiss, SendNow}andPendingUserQueryBlockEvent::{Dismissed, SendNow}. PendingUserQueryBlockimplementsTypedActionViewto translate actions → events.- The button column ("Remove queued prompt" + optional "Send now") is positioned top-right via
Stack+OffsetPositioning. - The caller in
pending_user_query.rssubscribes toDismissed(→remove_pending_user_query_block) andSendNow(→send_queued_prompt_now, which removes the block and immediately submits the queued prompt through the input) events.
5. Skip pending blocks in active_ai_block / last_ai_block
Both methods use Iterator::rfind to skip all trailing non-AI items (usage footers and pending query blocks) rather than checking only the last entry.
6. Auto-queue toggle (context_model.rs, status_bar.rs, input.rs)
queue_next_prompt_enabled: boolonBlocklistAIContextModeltracks the toggle state.toggle_queue_next_prompt()flips the flag and emitsQueueNextPromptToggled.- The status bar renders a
ClockPlusicon button gated behindFeatureFlag::QueueSlashCommand. The icon is accent-colored when active. - Keybinding
Cmd+Shift+Jmaps toTerminalAction::ToggleQueueNextPrompt. maybe_queue_input_for_in_progress_conversationininput.rsis the bottleneck: when the toggle is on and the active conversation is in progress, it captures the input buffer, clears it, and dispatchesQueuePromptForConversation.- The toggle persists across exchanges (same semantics as fast-forward).
End-to-End Flow
sequenceDiagram
participant User
participant Input as TerminalInput
participant WS as WorkspaceView
participant TV as TerminalView
participant PUQ as PendingUserQueryBlock
User->>Input: /queue fix the tests
Input->>Input: Validate conversation, prompt, status
Input->>WS: dispatch QueuePromptForConversation
WS->>TV: send_user_query_after_next_conversation_finished
TV->>PUQ: insert_pending_user_query_block
Note over PUQ: Shows queued prompt with dismiss button
alt Agent completes successfully
TV->>TV: on_next_conversation_finished(Complete)
TV->>Input: submit_queued_prompt("fix the tests")
Note over Input: Routes through slash/skill/plain-text detection
TV->>PUQ: remove block
else Agent errors/cancelled
TV->>TV: on_next_conversation_finished(Error|Cancelled)
TV->>TV: restore prompt to input buffer
TV->>PUQ: remove block
else User dismisses
User->>PUQ: click X
PUQ->>TV: PendingUserQueryBlockEvent::Dismissed
TV->>TV: remove_pending_user_query_block (cancels callback)
end
Risks and Mitigations
- Only one queued prompt at a time: calling
/queueagain while one is pending replaces the previous one (viaremove_pending_user_query_blockininsert_pending_user_query_block). This is acceptable for v1. - Pending indicator behind feature flag: the
PendingUserQueryIndicatorflag gates the visual block (dogfood). Without the flag, the prompt is still queued and auto-sent — just without visual feedback. This is the same behavior as/compact-and. - Queue command behind feature flag: the
QueueSlashCommandflag gates the/queuecommand registration (dogfood). The command handler, workspace action, and pending block infrastructure are always compiled in but only reachable when the flag is enabled.
Testing and Validation
- Manual testing of the five error/success paths described in the product spec.
- Code review of the
active_ai_block/last_ai_blockskip logic to ensure pending blocks don't break conversation state detection.