Skip to content

Commit d9bf873

Browse files
fix(cli): queue custom reviews while busy
1 parent 366311e commit d9bf873

2 files changed

Lines changed: 96 additions & 1 deletion

File tree

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { afterEach, describe, expect, mock, test } from 'bun:test'
2+
3+
import { buildReviewPrompt } from '../prompt-builders'
4+
import { routeUserPrompt } from '../router'
5+
import { useChatStore } from '../../state/chat-store'
6+
7+
import type { RouterParams } from '../command-registry'
8+
9+
const createMockParams = (
10+
overrides: Partial<RouterParams> = {},
11+
): RouterParams => ({
12+
agentMode: 'DEFAULT',
13+
inputRef: { current: null },
14+
inputValue: 'focus on the authentication flow',
15+
isChainInProgressRef: { current: false },
16+
isStreaming: false,
17+
logoutMutation: {} as RouterParams['logoutMutation'],
18+
streamMessageIdRef: { current: null },
19+
addToQueue: mock(() => {}),
20+
clearMessages: mock(() => {}),
21+
saveToHistory: mock(() => {}),
22+
scrollToLatest: mock(() => {}),
23+
sendMessage: mock(async () => {}),
24+
setCanProcessQueue: mock(() => {}),
25+
setInputFocused: mock(() => {}),
26+
setInputValue: mock(() => {}),
27+
setIsAuthenticated: mock(() => {}),
28+
setMessages: mock(() => {}),
29+
setUser: mock(() => {}),
30+
...overrides,
31+
})
32+
33+
describe('custom review routing', () => {
34+
afterEach(() => {
35+
useChatStore.getState().reset()
36+
})
37+
38+
test('queues a custom review while a response is in progress', async () => {
39+
const attachment = {
40+
kind: 'text' as const,
41+
id: 'requirements',
42+
content: 'Review the login requirements.',
43+
preview: 'Review the login requirements.',
44+
charCount: 32,
45+
}
46+
const addToQueue = mock(() => {})
47+
const sendMessage = mock(async () => {})
48+
useChatStore.setState({
49+
inputMode: 'review',
50+
pendingAttachments: [attachment],
51+
})
52+
53+
const params = createMockParams({
54+
addToQueue,
55+
isStreaming: true,
56+
sendMessage,
57+
})
58+
59+
await routeUserPrompt(params)
60+
61+
expect(addToQueue).toHaveBeenCalledWith(
62+
buildReviewPrompt('custom', params.inputValue),
63+
[attachment],
64+
)
65+
expect(sendMessage).not.toHaveBeenCalled()
66+
expect(useChatStore.getState().pendingAttachments).toEqual([])
67+
})
68+
69+
test('sends a custom review immediately when idle', async () => {
70+
const addToQueue = mock(() => {})
71+
const sendMessage = mock(async () => {})
72+
useChatStore.setState({ inputMode: 'review' })
73+
74+
const params = createMockParams({ addToQueue, sendMessage })
75+
76+
await routeUserPrompt(params)
77+
78+
expect(sendMessage).toHaveBeenCalledWith({
79+
content: buildReviewPrompt('custom', params.inputValue),
80+
agentMode: params.agentMode,
81+
})
82+
expect(addToQueue).not.toHaveBeenCalled()
83+
})
84+
})

cli/src/commands/router.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,18 @@ export async function routeUserPrompt(
352352
setInputFocused(true)
353353
inputRef.current?.focus()
354354

355-
sendMessage({ content: buildReviewPrompt('custom', trimmed), agentMode })
355+
const reviewPrompt = buildReviewPrompt('custom', trimmed)
356+
if (
357+
isStreaming ||
358+
streamMessageIdRef.current ||
359+
isChainInProgressRef.current
360+
) {
361+
const pendingAttachmentsForQueue = capturePendingAttachments()
362+
addToQueue(reviewPrompt, pendingAttachmentsForQueue)
363+
return
364+
}
365+
366+
sendMessage({ content: reviewPrompt, agentMode })
356367
setTimeout(() => {
357368
scrollToLatest()
358369
}, 0)

0 commit comments

Comments
 (0)