Skip to content

Commit 781beeb

Browse files
Auto approve follow up questions (RooCodeInc#5296)
1 parent a348a2a commit 781beeb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+453
-68
lines changed

packages/types/src/followup.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { z } from "zod"
2+
3+
/**
4+
* Interface for follow-up data structure used in follow-up questions
5+
* This represents the data structure for follow-up questions that the LLM can ask
6+
* to gather more information needed to complete a task.
7+
*/
8+
export interface FollowUpData {
9+
/** The question being asked by the LLM */
10+
question?: string
11+
/** Array of suggested answers that the user can select */
12+
suggest?: Array<SuggestionItem>
13+
}
14+
15+
/**
16+
* Interface for a suggestion item with optional mode switching
17+
*/
18+
export interface SuggestionItem {
19+
/** The text of the suggestion */
20+
answer: string
21+
/** Optional mode to switch to when selecting this suggestion */
22+
mode?: string
23+
}
24+
25+
/**
26+
* Zod schema for SuggestionItem
27+
*/
28+
export const suggestionItemSchema = z.object({
29+
answer: z.string(),
30+
mode: z.string().optional(),
31+
})
32+
33+
/**
34+
* Zod schema for FollowUpData
35+
*/
36+
export const followUpDataSchema = z.object({
37+
question: z.string().optional(),
38+
suggest: z.array(suggestionItemSchema).optional(),
39+
})
40+
41+
export type FollowUpDataType = z.infer<typeof followUpDataSchema>

packages/types/src/global-settings.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ export const globalSettingsSchema = z.object({
4545
alwaysAllowModeSwitch: z.boolean().optional(),
4646
alwaysAllowSubtasks: z.boolean().optional(),
4747
alwaysAllowExecute: z.boolean().optional(),
48+
alwaysAllowFollowupQuestions: z.boolean().optional(),
49+
followupAutoApproveTimeoutMs: z.number().optional(),
4850
allowedCommands: z.array(z.string()).optional(),
4951
allowedMaxRequests: z.number().nullish(),
5052
autoCondenseContext: z.boolean().optional(),
@@ -189,6 +191,8 @@ export const EVALS_SETTINGS: RooCodeSettings = {
189191
alwaysAllowModeSwitch: true,
190192
alwaysAllowSubtasks: true,
191193
alwaysAllowExecute: true,
194+
alwaysAllowFollowupQuestions: true,
195+
followupAutoApproveTimeoutMs: 0,
192196
allowedCommands: ["*"],
193197

194198
browserToolEnabled: false,

packages/types/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from "./api.js"
44
export * from "./codebase-index.js"
55
export * from "./cloud.js"
66
export * from "./experiment.js"
7+
export * from "./followup.js"
78
export * from "./global-settings.js"
89
export * from "./history.js"
910
export * from "./ipc.js"

src/core/webview/ClineProvider.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,8 @@ export class ClineProvider
14111411
codebaseIndexConfig,
14121412
codebaseIndexModels,
14131413
profileThresholds,
1414+
alwaysAllowFollowupQuestions,
1415+
followupAutoApproveTimeoutMs,
14141416
} = await this.getState()
14151417

14161418
const telemetryKey = process.env.POSTHOG_API_KEY
@@ -1521,6 +1523,8 @@ export class ClineProvider
15211523
profileThresholds: profileThresholds ?? {},
15221524
cloudApiUrl: getRooCodeApiUrl(),
15231525
hasOpenedModeSelector: this.getGlobalState("hasOpenedModeSelector") ?? false,
1526+
alwaysAllowFollowupQuestions: alwaysAllowFollowupQuestions ?? false,
1527+
followupAutoApproveTimeoutMs: followupAutoApproveTimeoutMs ?? 60000,
15241528
}
15251529
}
15261530

@@ -1601,6 +1605,8 @@ export class ClineProvider
16011605
alwaysAllowMcp: stateValues.alwaysAllowMcp ?? false,
16021606
alwaysAllowModeSwitch: stateValues.alwaysAllowModeSwitch ?? false,
16031607
alwaysAllowSubtasks: stateValues.alwaysAllowSubtasks ?? false,
1608+
alwaysAllowFollowupQuestions: stateValues.alwaysAllowFollowupQuestions ?? false,
1609+
followupAutoApproveTimeoutMs: stateValues.followupAutoApproveTimeoutMs ?? 60000,
16041610
allowedMaxRequests: stateValues.allowedMaxRequests,
16051611
autoCondenseContext: stateValues.autoCondenseContext ?? true,
16061612
autoCondenseContextPercent: stateValues.autoCondenseContextPercent ?? 100,

src/core/webview/webviewMessageHandler.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,14 @@ export const webviewMessageHandler = async (
11001100
await updateGlobalState("maxWorkspaceFiles", fileCount)
11011101
await provider.postStateToWebview()
11021102
break
1103+
case "alwaysAllowFollowupQuestions":
1104+
await updateGlobalState("alwaysAllowFollowupQuestions", message.bool ?? false)
1105+
await provider.postStateToWebview()
1106+
break
1107+
case "followupAutoApproveTimeoutMs":
1108+
await updateGlobalState("followupAutoApproveTimeoutMs", message.value)
1109+
await provider.postStateToWebview()
1110+
break
11031111
case "browserToolEnabled":
11041112
await updateGlobalState("browserToolEnabled", message.bool ?? true)
11051113
await provider.postStateToWebview()

src/shared/WebviewMessage.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ export interface WebviewMessage {
3737
| "alwaysAllowWriteOutsideWorkspace"
3838
| "alwaysAllowWriteProtected"
3939
| "alwaysAllowExecute"
40+
| "alwaysAllowFollowupQuestions"
41+
| "followupAutoApproveTimeoutMs"
4042
| "webviewDidLaunch"
4143
| "newTask"
4244
| "askResponse"

webview-ui/src/components/chat/AutoApproveMenu.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
2525
alwaysAllowModeSwitch,
2626
alwaysAllowSubtasks,
2727
alwaysApproveResubmit,
28+
alwaysAllowFollowupQuestions,
2829
allowedMaxRequests,
2930
setAlwaysAllowReadOnly,
3031
setAlwaysAllowWrite,
@@ -34,6 +35,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
3435
setAlwaysAllowModeSwitch,
3536
setAlwaysAllowSubtasks,
3637
setAlwaysApproveResubmit,
38+
setAlwaysAllowFollowupQuestions,
3739
setAllowedMaxRequests,
3840
} = useExtensionState()
3941

@@ -68,6 +70,9 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
6870
case "alwaysApproveResubmit":
6971
setAlwaysApproveResubmit(value)
7072
break
73+
case "alwaysAllowFollowupQuestions":
74+
setAlwaysAllowFollowupQuestions(value)
75+
break
7176
}
7277
},
7378
[
@@ -79,6 +84,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
7984
setAlwaysAllowModeSwitch,
8085
setAlwaysAllowSubtasks,
8186
setAlwaysApproveResubmit,
87+
setAlwaysAllowFollowupQuestions,
8288
],
8389
)
8490

@@ -94,6 +100,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
94100
alwaysAllowModeSwitch: alwaysAllowModeSwitch,
95101
alwaysAllowSubtasks: alwaysAllowSubtasks,
96102
alwaysApproveResubmit: alwaysApproveResubmit,
103+
alwaysAllowFollowupQuestions: alwaysAllowFollowupQuestions,
97104
}),
98105
[
99106
alwaysAllowReadOnly,
@@ -104,6 +111,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
104111
alwaysAllowModeSwitch,
105112
alwaysAllowSubtasks,
106113
alwaysApproveResubmit,
114+
alwaysAllowFollowupQuestions,
107115
],
108116
)
109117

webview-ui/src/components/chat/ChatRow.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type { ClineMessage } from "@roo-code/types"
1010
import { ClineApiReqInfo, ClineAskUseMcpServer, ClineSayTool } from "@roo/ExtensionMessage"
1111
import { COMMAND_OUTPUT_STRING } from "@roo/combineCommandSequences"
1212
import { safeJsonParse } from "@roo/safeJsonParse"
13+
import { FollowUpData, SuggestionItem } from "@roo-code/types"
1314

1415
import { useCopyToClipboard } from "@src/utils/clipboard"
1516
import { useExtensionState } from "@src/context/ExtensionStateContext"
@@ -48,8 +49,9 @@ interface ChatRowProps {
4849
isStreaming: boolean
4950
onToggleExpand: (ts: number) => void
5051
onHeightChange: (isTaller: boolean) => void
51-
onSuggestionClick?: (answer: string, event?: React.MouseEvent) => void
52+
onSuggestionClick?: (suggestion: SuggestionItem, event?: React.MouseEvent) => void
5253
onBatchFileResponse?: (response: { [key: string]: boolean }) => void
54+
onFollowUpUnmount?: () => void
5355
}
5456

5557
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
@@ -98,6 +100,7 @@ export const ChatRowContent = ({
98100
isStreaming,
99101
onToggleExpand,
100102
onSuggestionClick,
103+
onFollowUpUnmount,
101104
onBatchFileResponse,
102105
}: ChatRowContentProps) => {
103106
const { t } = useTranslation()
@@ -279,7 +282,7 @@ export const ChatRowContent = ({
279282

280283
const followUpData = useMemo(() => {
281284
if (message.type === "ask" && message.ask === "followup" && !message.partial) {
282-
return safeJsonParse<any>(message.text)
285+
return safeJsonParse<FollowUpData>(message.text)
283286
}
284287
return null
285288
}, [message.type, message.ask, message.partial, message.text])
@@ -1215,6 +1218,7 @@ export const ChatRowContent = ({
12151218
suggestions={followUpData?.suggest}
12161219
onSuggestionClick={onSuggestionClick}
12171220
ts={message?.ts}
1221+
onUnmount={onFollowUpUnmount}
12181222
/>
12191223
</>
12201224
)

0 commit comments

Comments
 (0)