feat: make retry and todo list auto-approval implicit

Remove alwaysApproveResubmit and alwaysAllowUpdateTodoList from
user-configurable auto-approve settings. These actions now behave
as implicitly approved when autoApprovalEnabled is true.

- Retry: auto-retries with backoff when auto-approval is enabled
- Todo List: auto-approved when auto-approval is enabled
- Removed UI toggles and configuration options for these settings
- Updated related tests
This commit is contained in:
Hannes Rudolph 2025-12-12 10:34:40 -07:00
parent d976a9b296
commit 7f99cc4f2e
19 changed files with 15 additions and 178 deletions

View file

@ -74,7 +74,6 @@ export const globalSettingsSchema = z.object({
alwaysAllowWriteProtected: z.boolean().optional(),
writeDelayMs: z.number().min(0).optional(),
alwaysAllowBrowser: z.boolean().optional(),
alwaysApproveResubmit: z.boolean().optional(),
requestDelaySeconds: z.number().optional(),
alwaysAllowMcp: z.boolean().optional(),
alwaysAllowModeSwitch: z.boolean().optional(),
@ -82,7 +81,6 @@ export const globalSettingsSchema = z.object({
alwaysAllowExecute: z.boolean().optional(),
alwaysAllowFollowupQuestions: z.boolean().optional(),
followupAutoApproveTimeoutMs: z.number().optional(),
alwaysAllowUpdateTodoList: z.boolean().optional(),
allowedCommands: z.array(z.string()).optional(),
deniedCommands: z.array(z.string()).optional(),
commandExecutionTimeout: z.number().optional(),
@ -307,14 +305,12 @@ export const EVALS_SETTINGS: RooCodeSettings = {
alwaysAllowWriteProtected: false,
writeDelayMs: 1000,
alwaysAllowBrowser: true,
alwaysApproveResubmit: true,
requestDelaySeconds: 10,
alwaysAllowMcp: true,
alwaysAllowModeSwitch: true,
alwaysAllowSubtasks: true,
alwaysAllowExecute: true,
alwaysAllowFollowupQuestions: true,
alwaysAllowUpdateTodoList: true,
followupAutoApproveTimeoutMs: 0,
allowedCommands: ["*"],
commandExecutionTimeout: 20,

View file

@ -7,18 +7,17 @@ import { isWriteToolAction, isReadOnlyToolAction } from "./tools"
import { isMcpToolAlwaysAllowed } from "./mcp"
import { getCommandDecision } from "./commands"
// We have 10 different actions that can be auto-approved.
// We have 8 different actions that can be auto-approved.
// Note: Retry (resubmit) and updateTodoList are always implicitly approved.
export type AutoApprovalState =
| "alwaysAllowReadOnly"
| "alwaysAllowWrite"
| "alwaysAllowBrowser"
| "alwaysApproveResubmit"
| "alwaysAllowMcp"
| "alwaysAllowModeSwitch"
| "alwaysAllowSubtasks"
| "alwaysAllowExecute"
| "alwaysAllowFollowupQuestions"
| "alwaysAllowUpdateTodoList"
// Some of these actions have additional settings associated with them.
export type AutoApprovalStateOptions =
@ -143,8 +142,9 @@ export async function checkAutoApproval({
return { decision: "ask" }
}
// updateTodoList is always implicitly approved when auto-approval is enabled
if (tool.tool === "updateTodoList") {
return state.alwaysAllowUpdateTodoList === true ? { decision: "approve" } : { decision: "ask" }
return { decision: "approve" }
}
if (tool?.tool === "fetchInstructions") {

View file

@ -2957,9 +2957,10 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
`[Task#${this.taskId}.${this.instanceId}] Stream failed, will retry: ${streamingFailedMessage}`,
)
// Apply exponential backoff similar to first-chunk errors when auto-resubmit is enabled
// Apply exponential backoff similar to first-chunk errors when auto-approval is enabled
// Retry is implicitly approved when autoApprovalEnabled is true
const stateForBackoff = await this.providerRef.deref()?.getState()
if (stateForBackoff?.autoApprovalEnabled && stateForBackoff?.alwaysApproveResubmit) {
if (stateForBackoff?.autoApprovalEnabled) {
await this.backoffAndAnnounce(
currentItem.retryAttempt ?? 0,
error,
@ -3210,7 +3211,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
// Check if we should auto-retry or prompt the user
// Reuse the state variable from above
if (state?.autoApprovalEnabled && state?.alwaysApproveResubmit) {
if (state?.autoApprovalEnabled) {
// Auto-retry with backoff - don't persist failure message when retrying
const errorMsg =
"Unexpected API Response: The language model did not provide any assistant messages. This may indicate an issue with the API or the model's output."
@ -3503,7 +3504,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
const {
apiConfiguration,
autoApprovalEnabled,
alwaysApproveResubmit,
requestDelaySeconds,
mode,
autoCondenseContext = true,
@ -3805,7 +3805,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
}
// note that this api_req_failed ask is unique in that we only present this option if the api hasn't streamed any content yet (ie it fails on the first chunk due), as it would allow them to hit a retry button. However if the api failed mid-stream, it could be in any arbitrary state where some tools may have executed, so that error is handled differently and requires cancelling the task entirely.
if (autoApprovalEnabled && alwaysApproveResubmit) {
if (autoApprovalEnabled) {
let errorMsg
if (error.error?.metadata?.raw) {

View file

@ -697,9 +697,9 @@ describe("Cline", () => {
return mockSuccessStream
})
// Set alwaysApproveResubmit and requestDelaySeconds
// Set autoApprovalEnabled and requestDelaySeconds (retry is always enabled when auto-approval is on)
mockProvider.getState = vi.fn().mockResolvedValue({
alwaysApproveResubmit: true,
autoApprovalEnabled: true,
requestDelaySeconds: 3,
})
@ -821,9 +821,9 @@ describe("Cline", () => {
return mockSuccessStream
})
// Set alwaysApproveResubmit and requestDelaySeconds
// Set autoApprovalEnabled and requestDelaySeconds (retry is always enabled when auto-approval is on)
mockProvider.getState = vi.fn().mockResolvedValue({
alwaysApproveResubmit: true,
autoApprovalEnabled: true,
requestDelaySeconds: 3,
})

View file

@ -1816,7 +1816,6 @@ export class ClineProvider
alwaysAllowMcp,
alwaysAllowModeSwitch,
alwaysAllowSubtasks,
alwaysAllowUpdateTodoList,
allowedMaxRequests,
allowedMaxCost,
autoCondenseContext,
@ -1848,7 +1847,6 @@ export class ClineProvider
fuzzyMatchThreshold,
mcpEnabled,
enableMcpServerCreation,
alwaysApproveResubmit,
requestDelaySeconds,
currentApiConfigName,
listApiConfigMeta,
@ -1948,7 +1946,6 @@ export class ClineProvider
alwaysAllowMcp: alwaysAllowMcp ?? false,
alwaysAllowModeSwitch: alwaysAllowModeSwitch ?? false,
alwaysAllowSubtasks: alwaysAllowSubtasks ?? false,
alwaysAllowUpdateTodoList: alwaysAllowUpdateTodoList ?? false,
isBrowserSessionActive,
allowedMaxRequests,
allowedMaxCost,
@ -1994,7 +1991,6 @@ export class ClineProvider
fuzzyMatchThreshold: fuzzyMatchThreshold ?? 1.0,
mcpEnabled: mcpEnabled ?? true,
enableMcpServerCreation: enableMcpServerCreation ?? true,
alwaysApproveResubmit: alwaysApproveResubmit ?? false,
requestDelaySeconds: requestDelaySeconds ?? 10,
currentApiConfigName: currentApiConfigName ?? "default",
listApiConfigMeta: listApiConfigMeta ?? [],
@ -2189,7 +2185,6 @@ export class ClineProvider
alwaysAllowModeSwitch: stateValues.alwaysAllowModeSwitch ?? false,
alwaysAllowSubtasks: stateValues.alwaysAllowSubtasks ?? false,
alwaysAllowFollowupQuestions: stateValues.alwaysAllowFollowupQuestions ?? false,
alwaysAllowUpdateTodoList: stateValues.alwaysAllowUpdateTodoList ?? false,
isBrowserSessionActive,
followupAutoApproveTimeoutMs: stateValues.followupAutoApproveTimeoutMs ?? 60000,
diagnosticsEnabled: stateValues.diagnosticsEnabled ?? true,
@ -2232,7 +2227,6 @@ export class ClineProvider
mcpEnabled: stateValues.mcpEnabled ?? true,
enableMcpServerCreation: stateValues.enableMcpServerCreation ?? true,
mcpServers: this.mcpHub?.getAllServers() ?? [],
alwaysApproveResubmit: stateValues.alwaysApproveResubmit ?? false,
requestDelaySeconds: Math.max(5, stateValues.requestDelaySeconds ?? 10),
currentApiConfigName: stateValues.currentApiConfigName ?? "default",
listApiConfigMeta: stateValues.listApiConfigMeta ?? [],

View file

@ -848,14 +848,6 @@ describe("ClineProvider", () => {
expect(state.requestDelaySeconds).toBe(10)
})
test("alwaysApproveResubmit defaults to false", async () => {
// Mock globalState.get to return undefined for alwaysApproveResubmit
;(mockContext.globalState.get as any).mockReturnValue(undefined)
const state = await provider.getState()
expect(state.alwaysApproveResubmit).toBe(false)
})
test("autoCondenseContext defaults to true", async () => {
// Mock globalState.get to return undefined for autoCondenseContext
;(mockContext.globalState.get as any).mockImplementation((key: string) =>
@ -1030,12 +1022,6 @@ describe("ClineProvider", () => {
await provider.resolveWebviewView(mockWebviewView)
const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as any).mock.calls[0][0]
// Test alwaysApproveResubmit
await messageHandler({ type: "updateSettings", updatedSettings: { alwaysApproveResubmit: true } })
expect(updateGlobalStateSpy).toHaveBeenCalledWith("alwaysApproveResubmit", true)
expect(mockContext.globalState.update).toHaveBeenCalledWith("alwaysApproveResubmit", true)
expect(mockPostMessage).toHaveBeenCalled()
// Test requestDelaySeconds
await messageHandler({ type: "updateSettings", updatedSettings: { requestDelaySeconds: 10 } })
expect(mockContext.globalState.update).toHaveBeenCalledWith("requestDelaySeconds", 10)

View file

@ -233,13 +233,11 @@ export type ExtensionState = Pick<
| "alwaysAllowWriteOutsideWorkspace"
| "alwaysAllowWriteProtected"
| "alwaysAllowBrowser"
| "alwaysApproveResubmit"
| "alwaysAllowMcp"
| "alwaysAllowModeSwitch"
| "alwaysAllowSubtasks"
| "alwaysAllowFollowupQuestions"
| "alwaysAllowExecute"
| "alwaysAllowUpdateTodoList"
| "followupAutoApproveTimeoutMs"
| "allowedCommands"
| "deniedCommands"

View file

@ -31,7 +31,6 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
const {
autoApprovalEnabled,
setAutoApprovalEnabled,
alwaysApproveResubmit,
setAlwaysAllowReadOnly,
setAlwaysAllowWrite,
setAlwaysAllowExecute,
@ -39,21 +38,10 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
setAlwaysAllowMcp,
setAlwaysAllowModeSwitch,
setAlwaysAllowSubtasks,
setAlwaysApproveResubmit,
setAlwaysAllowFollowupQuestions,
setAlwaysAllowUpdateTodoList,
} = useExtensionState()
const baseToggles = useAutoApprovalToggles()
// Include alwaysApproveResubmit in addition to the base toggles.
const toggles = React.useMemo(
() => ({
...baseToggles,
alwaysApproveResubmit: alwaysApproveResubmit,
}),
[baseToggles, alwaysApproveResubmit],
)
const toggles = useAutoApprovalToggles()
const onAutoApproveToggle = React.useCallback(
(key: AutoApproveSetting, value: boolean) => {
@ -81,15 +69,9 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
case "alwaysAllowSubtasks":
setAlwaysAllowSubtasks(value)
break
case "alwaysApproveResubmit":
setAlwaysApproveResubmit(value)
break
case "alwaysAllowFollowupQuestions":
setAlwaysAllowFollowupQuestions(value)
break
case "alwaysAllowUpdateTodoList":
setAlwaysAllowUpdateTodoList(value)
break
}
// If enabling any option, ensure autoApprovalEnabled is true.
@ -107,9 +89,7 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
setAlwaysAllowMcp,
setAlwaysAllowModeSwitch,
setAlwaysAllowSubtasks,
setAlwaysApproveResubmit,
setAlwaysAllowFollowupQuestions,
setAlwaysAllowUpdateTodoList,
setAutoApprovalEnabled,
],
)

View file

@ -88,7 +88,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
mode,
setMode,
alwaysAllowModeSwitch,
alwaysAllowUpdateTodoList,
customModes,
telemetrySetting,
hasSystemPromptOverride,
@ -1287,24 +1286,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
onBatchFileResponse={handleBatchFileResponse}
isFollowUpAnswered={messageOrGroup.isAnswered === true || messageOrGroup.ts === currentFollowUpTs}
isFollowUpAutoApprovalPaused={isFollowUpAutoApprovalPaused}
editable={
messageOrGroup.type === "ask" &&
messageOrGroup.ask === "tool" &&
(() => {
let tool: any = {}
try {
tool = JSON.parse(messageOrGroup.text || "{}")
} catch (_) {
if (messageOrGroup.text?.includes("updateTodoList")) {
tool = { tool: "updateTodoList" }
}
}
if (tool.tool === "updateTodoList" && alwaysAllowUpdateTodoList) {
return false
}
return tool.tool === "updateTodoList" && enableButtons && !!primaryButtonText
})()
}
editable={false}
hasCheckpoint={hasCheckpoint}
/>
)
@ -1320,9 +1302,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
handleBatchFileResponse,
currentFollowUpTs,
isFollowUpAutoApprovalPaused,
alwaysAllowUpdateTodoList,
enableButtons,
primaryButtonText,
],
)

View file

@ -24,14 +24,11 @@ type AutoApproveSettingsProps = HTMLAttributes<HTMLDivElement> & {
alwaysAllowWriteOutsideWorkspace?: boolean
alwaysAllowWriteProtected?: boolean
alwaysAllowBrowser?: boolean
alwaysApproveResubmit?: boolean
requestDelaySeconds: number
alwaysAllowMcp?: boolean
alwaysAllowModeSwitch?: boolean
alwaysAllowSubtasks?: boolean
alwaysAllowExecute?: boolean
alwaysAllowFollowupQuestions?: boolean
alwaysAllowUpdateTodoList?: boolean
followupAutoApproveTimeoutMs?: number
allowedCommands?: string[]
allowedMaxRequests?: number | undefined
@ -44,8 +41,6 @@ type AutoApproveSettingsProps = HTMLAttributes<HTMLDivElement> & {
| "alwaysAllowWriteOutsideWorkspace"
| "alwaysAllowWriteProtected"
| "alwaysAllowBrowser"
| "alwaysApproveResubmit"
| "requestDelaySeconds"
| "alwaysAllowMcp"
| "alwaysAllowModeSwitch"
| "alwaysAllowSubtasks"
@ -56,7 +51,6 @@ type AutoApproveSettingsProps = HTMLAttributes<HTMLDivElement> & {
| "allowedMaxRequests"
| "allowedMaxCost"
| "deniedCommands"
| "alwaysAllowUpdateTodoList"
>
}
@ -67,15 +61,12 @@ export const AutoApproveSettings = ({
alwaysAllowWriteOutsideWorkspace,
alwaysAllowWriteProtected,
alwaysAllowBrowser,
alwaysApproveResubmit,
requestDelaySeconds,
alwaysAllowMcp,
alwaysAllowModeSwitch,
alwaysAllowSubtasks,
alwaysAllowExecute,
alwaysAllowFollowupQuestions,
followupAutoApproveTimeoutMs = 60000,
alwaysAllowUpdateTodoList,
allowedCommands,
allowedMaxRequests,
allowedMaxCost,
@ -164,13 +155,11 @@ export const AutoApproveSettings = ({
alwaysAllowReadOnly={alwaysAllowReadOnly}
alwaysAllowWrite={alwaysAllowWrite}
alwaysAllowBrowser={alwaysAllowBrowser}
alwaysApproveResubmit={alwaysApproveResubmit}
alwaysAllowMcp={alwaysAllowMcp}
alwaysAllowModeSwitch={alwaysAllowModeSwitch}
alwaysAllowSubtasks={alwaysAllowSubtasks}
alwaysAllowExecute={alwaysAllowExecute}
alwaysAllowFollowupQuestions={alwaysAllowFollowupQuestions}
alwaysAllowUpdateTodoList={alwaysAllowUpdateTodoList}
onToggle={(key, value) => setCachedStateField(key, value)}
/>
@ -245,31 +234,6 @@ export const AutoApproveSettings = ({
</div>
)}
{alwaysApproveResubmit && (
<div className="flex flex-col gap-3 pl-3 border-l-2 border-vscode-button-background">
<div className="flex items-center gap-4 font-bold">
<span className="codicon codicon-refresh" />
<div>{t("settings:autoApprove.retry.label")}</div>
</div>
<div>
<div className="flex items-center gap-2">
<Slider
min={5}
max={100}
step={1}
value={[requestDelaySeconds]}
onValueChange={([value]) => setCachedStateField("requestDelaySeconds", value)}
data-testid="request-delay-slider"
/>
<span className="w-20">{requestDelaySeconds}s</span>
</div>
<div className="text-vscode-descriptionForeground text-sm mt-1">
{t("settings:autoApprove.retry.delayLabel")}
</div>
</div>
</div>
)}
{alwaysAllowFollowupQuestions && (
<div className="flex flex-col gap-3 pl-3 border-l-2 border-vscode-button-background">
<div className="flex items-center gap-4 font-bold">

View file

@ -9,13 +9,11 @@ type AutoApproveToggles = Pick<
| "alwaysAllowReadOnly"
| "alwaysAllowWrite"
| "alwaysAllowBrowser"
| "alwaysApproveResubmit"
| "alwaysAllowMcp"
| "alwaysAllowModeSwitch"
| "alwaysAllowSubtasks"
| "alwaysAllowExecute"
| "alwaysAllowFollowupQuestions"
| "alwaysAllowUpdateTodoList"
>
export type AutoApproveSetting = keyof AutoApproveToggles
@ -50,13 +48,6 @@ export const autoApproveSettingsConfig: Record<AutoApproveSetting, AutoApproveCo
icon: "globe",
testId: "always-allow-browser-toggle",
},
alwaysApproveResubmit: {
key: "alwaysApproveResubmit",
labelKey: "settings:autoApprove.retry.label",
descriptionKey: "settings:autoApprove.retry.description",
icon: "refresh",
testId: "always-approve-resubmit-toggle",
},
alwaysAllowMcp: {
key: "alwaysAllowMcp",
labelKey: "settings:autoApprove.mcp.label",
@ -92,13 +83,6 @@ export const autoApproveSettingsConfig: Record<AutoApproveSetting, AutoApproveCo
icon: "question",
testId: "always-allow-followup-questions-toggle",
},
alwaysAllowUpdateTodoList: {
key: "alwaysAllowUpdateTodoList",
labelKey: "settings:autoApprove.updateTodoList.label",
descriptionKey: "settings:autoApprove.updateTodoList.description",
icon: "checklist",
testId: "always-allow-update-todo-list-toggle",
},
}
type AutoApproveToggleProps = AutoApproveToggles & {

View file

@ -157,7 +157,6 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
alwaysAllowWrite,
alwaysAllowWriteOutsideWorkspace,
alwaysAllowWriteProtected,
alwaysApproveResubmit,
autoCondenseContext,
autoCondenseContextPercent,
browserToolEnabled,
@ -201,7 +200,6 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
customSupportPrompts,
profileThresholds,
alwaysAllowFollowupQuestions,
alwaysAllowUpdateTodoList,
followupAutoApproveTimeoutMs,
includeDiagnosticMessages,
maxDiagnosticMessages,
@ -395,7 +393,6 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
terminalZdotdir,
terminalCompressProgressBar,
mcpEnabled,
alwaysApproveResubmit: alwaysApproveResubmit ?? false,
requestDelaySeconds: requestDelaySeconds ?? 5,
maxOpenTabsContext: Math.min(Math.max(0, maxOpenTabsContext ?? 20), 500),
maxWorkspaceFiles: Math.min(Math.max(0, maxWorkspaceFiles ?? 200), 500),
@ -408,7 +405,6 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
includeDiagnosticMessages !== undefined ? includeDiagnosticMessages : true,
maxDiagnosticMessages: maxDiagnosticMessages ?? 50,
alwaysAllowSubtasks,
alwaysAllowUpdateTodoList,
alwaysAllowFollowupQuestions: alwaysAllowFollowupQuestions ?? false,
followupAutoApproveTimeoutMs,
condensingApiConfigId: condensingApiConfigId || "",
@ -719,14 +715,11 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
alwaysAllowWriteOutsideWorkspace={alwaysAllowWriteOutsideWorkspace}
alwaysAllowWriteProtected={alwaysAllowWriteProtected}
alwaysAllowBrowser={alwaysAllowBrowser}
alwaysApproveResubmit={alwaysApproveResubmit}
requestDelaySeconds={requestDelaySeconds}
alwaysAllowMcp={alwaysAllowMcp}
alwaysAllowModeSwitch={alwaysAllowModeSwitch}
alwaysAllowSubtasks={alwaysAllowSubtasks}
alwaysAllowExecute={alwaysAllowExecute}
alwaysAllowFollowupQuestions={alwaysAllowFollowupQuestions}
alwaysAllowUpdateTodoList={alwaysAllowUpdateTodoList}
followupAutoApproveTimeoutMs={followupAutoApproveTimeoutMs}
allowedCommands={allowedCommands}
allowedMaxRequests={allowedMaxRequests ?? undefined}

View file

@ -20,13 +20,11 @@ describe("AutoApproveToggle", () => {
alwaysAllowReadOnly: true,
alwaysAllowWrite: false,
alwaysAllowBrowser: false,
alwaysApproveResubmit: true,
alwaysAllowMcp: false,
alwaysAllowModeSwitch: true,
alwaysAllowSubtasks: false,
alwaysAllowExecute: true,
alwaysAllowFollowupQuestions: false,
alwaysAllowUpdateTodoList: true,
onToggle: mockOnToggle,
}

View file

@ -136,7 +136,6 @@ describe("SettingsView - Change Detection Fix", () => {
alwaysAllowWrite: false,
alwaysAllowWriteOutsideWorkspace: false,
alwaysAllowWriteProtected: false,
alwaysApproveResubmit: false,
autoCondenseContext: false,
autoCondenseContextPercent: 50,
browserToolEnabled: false,
@ -179,7 +178,6 @@ describe("SettingsView - Change Detection Fix", () => {
customSupportPrompts: {},
profileThresholds: {},
alwaysAllowFollowupQuestions: false,
alwaysAllowUpdateTodoList: false,
followupAutoApproveTimeoutMs: undefined,
includeDiagnosticMessages: false,
maxDiagnosticMessages: 50,

View file

@ -146,7 +146,6 @@ describe("SettingsView - Unsaved Changes Detection", () => {
alwaysAllowWrite: false,
alwaysAllowWriteOutsideWorkspace: false,
alwaysAllowWriteProtected: false,
alwaysApproveResubmit: false,
autoCondenseContext: false,
autoCondenseContextPercent: 50,
browserToolEnabled: false,
@ -189,7 +188,6 @@ describe("SettingsView - Unsaved Changes Detection", () => {
customSupportPrompts: {},
profileThresholds: {},
alwaysAllowFollowupQuestions: false,
alwaysAllowUpdateTodoList: false,
followupAutoApproveTimeoutMs: undefined,
includeDiagnosticMessages: false,
maxDiagnosticMessages: 50,

View file

@ -110,8 +110,6 @@ export interface ExtensionStateContextType extends ExtensionState {
setTaskSyncEnabled: (value: boolean) => void
featureRoomoteControlEnabled: boolean
setFeatureRoomoteControlEnabled: (value: boolean) => void
alwaysApproveResubmit?: boolean
setAlwaysApproveResubmit: (value: boolean) => void
requestDelaySeconds: number
setRequestDelaySeconds: (value: number) => void
setCurrentApiConfigName: (value: string) => void
@ -155,8 +153,6 @@ export interface ExtensionStateContextType extends ExtensionState {
autoCondenseContextPercent: number
setAutoCondenseContextPercent: (value: number) => void
routerModels?: RouterModels
alwaysAllowUpdateTodoList?: boolean
setAlwaysAllowUpdateTodoList: (value: boolean) => void
includeDiagnosticMessages?: boolean
setIncludeDiagnosticMessages: (value: boolean) => void
maxDiagnosticMessages?: number
@ -221,7 +217,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
remoteControlEnabled: false,
taskSyncEnabled: false,
featureRoomoteControlEnabled: false,
alwaysApproveResubmit: false,
requestDelaySeconds: 5,
currentApiConfigName: "default",
listApiConfigMeta: [],
@ -273,7 +268,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
codebaseIndexSearchMinScore: undefined,
},
codebaseIndexModels: { ollama: {}, openai: {} },
alwaysAllowUpdateTodoList: true,
includeDiagnosticMessages: true,
maxDiagnosticMessages: 50,
openRouterImageApiKey: "",
@ -531,7 +525,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
setTaskSyncEnabled: (value) => setState((prevState) => ({ ...prevState, taskSyncEnabled: value }) as any),
setFeatureRoomoteControlEnabled: (value) =>
setState((prevState) => ({ ...prevState, featureRoomoteControlEnabled: value })),
setAlwaysApproveResubmit: (value) => setState((prevState) => ({ ...prevState, alwaysApproveResubmit: value })),
setRequestDelaySeconds: (value) => setState((prevState) => ({ ...prevState, requestDelaySeconds: value })),
setCurrentApiConfigName: (value) => setState((prevState) => ({ ...prevState, currentApiConfigName: value })),
setListApiConfigMeta,
@ -584,10 +577,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
setCustomCondensingPrompt: (value) =>
setState((prevState) => ({ ...prevState, customCondensingPrompt: value })),
setProfileThresholds: (value) => setState((prevState) => ({ ...prevState, profileThresholds: value })),
alwaysAllowUpdateTodoList: state.alwaysAllowUpdateTodoList,
setAlwaysAllowUpdateTodoList: (value) => {
setState((prevState) => ({ ...prevState, alwaysAllowUpdateTodoList: value }))
},
includeDiagnosticMessages: state.includeDiagnosticMessages,
setIncludeDiagnosticMessages: (value) => {
setState((prevState) => ({ ...prevState, includeDiagnosticMessages: value }))

View file

@ -12,9 +12,7 @@ describe("useAutoApprovalState", () => {
alwaysAllowMcp: false,
alwaysAllowModeSwitch: false,
alwaysAllowSubtasks: false,
alwaysApproveResubmit: false,
alwaysAllowFollowupQuestions: false,
alwaysAllowUpdateTodoList: false,
}
const { result } = renderHook(() => useAutoApprovalState(toggles, true))
@ -31,9 +29,7 @@ describe("useAutoApprovalState", () => {
alwaysAllowMcp: undefined,
alwaysAllowModeSwitch: undefined,
alwaysAllowSubtasks: undefined,
alwaysApproveResubmit: undefined,
alwaysAllowFollowupQuestions: undefined,
alwaysAllowUpdateTodoList: undefined,
}
const { result } = renderHook(() => useAutoApprovalState(toggles, true))
@ -50,9 +46,7 @@ describe("useAutoApprovalState", () => {
alwaysAllowMcp: false,
alwaysAllowModeSwitch: false,
alwaysAllowSubtasks: false,
alwaysApproveResubmit: false,
alwaysAllowFollowupQuestions: false,
alwaysAllowUpdateTodoList: false,
}
const { result } = renderHook(() => useAutoApprovalState(toggles, true))
@ -69,9 +63,7 @@ describe("useAutoApprovalState", () => {
alwaysAllowMcp: false,
alwaysAllowModeSwitch: false,
alwaysAllowSubtasks: false,
alwaysApproveResubmit: false,
alwaysAllowFollowupQuestions: false,
alwaysAllowUpdateTodoList: false,
}
const { result } = renderHook(() => useAutoApprovalState(toggles, true))
@ -88,9 +80,7 @@ describe("useAutoApprovalState", () => {
alwaysAllowMcp: true,
alwaysAllowModeSwitch: true,
alwaysAllowSubtasks: true,
alwaysApproveResubmit: true,
alwaysAllowFollowupQuestions: true,
alwaysAllowUpdateTodoList: true,
}
const { result } = renderHook(() => useAutoApprovalState(toggles, true))
@ -133,9 +123,7 @@ describe("useAutoApprovalState", () => {
alwaysAllowMcp: false,
alwaysAllowModeSwitch: false,
alwaysAllowSubtasks: false,
alwaysApproveResubmit: false,
alwaysAllowFollowupQuestions: false,
alwaysAllowUpdateTodoList: false,
}
const { result } = renderHook(() => useAutoApprovalState(toggles, true))

View file

@ -8,9 +8,7 @@ interface AutoApprovalToggles {
alwaysAllowMcp?: boolean
alwaysAllowModeSwitch?: boolean
alwaysAllowSubtasks?: boolean
alwaysApproveResubmit?: boolean
alwaysAllowFollowupQuestions?: boolean
alwaysAllowUpdateTodoList?: boolean
}
export function useAutoApprovalState(toggles: AutoApprovalToggles, autoApprovalEnabled?: boolean) {

View file

@ -14,9 +14,7 @@ export function useAutoApprovalToggles() {
alwaysAllowMcp,
alwaysAllowModeSwitch,
alwaysAllowSubtasks,
alwaysApproveResubmit,
alwaysAllowFollowupQuestions,
alwaysAllowUpdateTodoList,
} = useExtensionState()
const toggles = useMemo(
@ -28,9 +26,7 @@ export function useAutoApprovalToggles() {
alwaysAllowMcp,
alwaysAllowModeSwitch,
alwaysAllowSubtasks,
alwaysApproveResubmit,
alwaysAllowFollowupQuestions,
alwaysAllowUpdateTodoList,
}),
[
alwaysAllowReadOnly,
@ -40,9 +36,7 @@ export function useAutoApprovalToggles() {
alwaysAllowMcp,
alwaysAllowModeSwitch,
alwaysAllowSubtasks,
alwaysApproveResubmit,
alwaysAllowFollowupQuestions,
alwaysAllowUpdateTodoList,
],
)