diff --git a/.changeset/six-guests-admire.md b/.changeset/six-guests-admire.md new file mode 100644 index 00000000000..4ddbf49d4ed --- /dev/null +++ b/.changeset/six-guests-admire.md @@ -0,0 +1,5 @@ +--- +"kilo-code": minor +--- + +feat(retry): implement configurable delay and max retries diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index 1568bc2af92..e133c1a4759 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -79,7 +79,9 @@ export const globalSettingsSchema = z.object({ alwaysAllowDelete: z.boolean().optional(), // kilocode_change writeDelayMs: z.number().min(0).optional(), alwaysAllowBrowser: z.boolean().optional(), + alwaysApproveResubmit: z.boolean().optional(), // kilocode_change requestDelaySeconds: z.number().optional(), + requestRetryMax: z.number().optional(), // kilocode_change alwaysAllowMcp: z.boolean().optional(), alwaysAllowModeSwitch: z.boolean().optional(), alwaysAllowSubtasks: z.boolean().optional(), @@ -363,7 +365,9 @@ export const EVALS_SETTINGS: RooCodeSettings = { alwaysAllowDelete: true, // kilocode_change writeDelayMs: 1000, alwaysAllowBrowser: true, + alwaysApproveResubmit: true, // kilocode_change requestDelaySeconds: 10, + requestRetryMax: 0, // kilocode_change alwaysAllowMcp: true, alwaysAllowModeSwitch: true, alwaysAllowSubtasks: true, diff --git a/src/core/auto-approval/index.ts b/src/core/auto-approval/index.ts index 47f552a0f3b..340e7ab579e 100644 --- a/src/core/auto-approval/index.ts +++ b/src/core/auto-approval/index.ts @@ -18,6 +18,7 @@ export type AutoApprovalState = | "alwaysAllowSubtasks" | "alwaysAllowExecute" | "alwaysAllowFollowupQuestions" + | "alwaysApproveResubmit" // kilocode_change // Some of these actions have additional settings associated with them. export type AutoApprovalStateOptions = diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index 92af0fca97b..2b723bd4f27 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -146,7 +146,6 @@ import { AutoApprovalHandler, checkAutoApproval } from "../auto-approval" import { MessageManager } from "../message-manager" import { validateAndFixToolResultIds } from "./validateToolResultIds" -const MAX_EXPONENTIAL_BACKOFF_SECONDS = 600 // 10 minutes const DEFAULT_USAGE_COLLECTION_TIMEOUT_MS = 5000 // 5 seconds const FORCED_CONTEXT_REDUCTION_PERCENT = 75 // Keep 75% of context (remove 25%) on context window errors const MAX_CONTEXT_WINDOW_RETRIES = 3 // Maximum retries for context window errors @@ -3389,9 +3388,14 @@ export class Task extends EventEmitter 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 backoff similar to first-chunk errors when auto-resubmit is enabled const stateForBackoff = await this.providerRef.deref()?.getState() - if (stateForBackoff?.autoApprovalEnabled) { + const retryMax = stateForBackoff?.requestRetryMax ?? 0 + if ( + stateForBackoff?.autoApprovalEnabled && + stateForBackoff?.alwaysApproveResubmit && // kilocode_change + (retryMax === 0 || (currentItem.retryAttempt ?? 0) < retryMax) + ) { await this.backoffAndAnnounce(currentItem.retryAttempt ?? 0, error) // Check if task was aborted during the backoff @@ -3672,7 +3676,12 @@ export class Task extends EventEmitter implements TaskLike { // Check if we should auto-retry or prompt the user // Reuse the state variable from above - if (state?.autoApprovalEnabled) { + const retryMax = state?.requestRetryMax ?? 0 + if ( + state?.autoApprovalEnabled && + state?.alwaysApproveResubmit && // kilocode_change + (retryMax === 0 || (currentItem.retryAttempt ?? 0) < retryMax) + ) { // Auto-retry with backoff - don't persist failure message when retrying await this.backoffAndAnnounce( currentItem.retryAttempt ?? 0, @@ -4425,8 +4434,9 @@ export class Task extends EventEmitter implements TaskLike { } // kilocode_change end // 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) { - // Apply shared exponential backoff and countdown UX + const retryMax = state?.requestRetryMax ?? 0 // kilocode_change + if (autoApprovalEnabled && state?.alwaysApproveResubmit && (retryMax === 0 || retryAttempt < retryMax)) { + // Apply shared backoff and countdown UX await this.backoffAndAnnounce(retryAttempt, error) // CRITICAL: Check if task was aborted during the backoff countdown @@ -4486,16 +4496,11 @@ export class Task extends EventEmitter implements TaskLike { } } - // Shared exponential backoff for retries (first-chunk and mid-stream) + // Shared backoff for retries (first-chunk and mid-stream) private async backoffAndAnnounce(retryAttempt: number, error: any): Promise { try { const state = await this.providerRef.deref()?.getState() - const baseDelay = state?.requestDelaySeconds || 5 - - let exponentialDelay = Math.min( - Math.ceil(baseDelay * Math.pow(2, retryAttempt)), - MAX_EXPONENTIAL_BACKOFF_SECONDS, - ) + let requestDelaySeconds = state?.requestDelaySeconds ?? 10 // Respect provider rate limit window let rateLimitDelay = 0 @@ -4512,11 +4517,11 @@ export class Task extends EventEmitter implements TaskLike { ) const match = retryInfo?.retryDelay?.match?.(/^(\d+)s$/) if (match) { - exponentialDelay = Number(match[1]) + 1 + requestDelaySeconds = Number(match[1]) + 1 } } - const finalDelay = Math.max(exponentialDelay, rateLimitDelay) + const finalDelay = Math.max(requestDelaySeconds, rateLimitDelay) if (finalDelay <= 0) { return } diff --git a/src/core/task/__tests__/auto-retry.spec.ts b/src/core/task/__tests__/auto-retry.spec.ts new file mode 100644 index 00000000000..4cc74b0bfdd --- /dev/null +++ b/src/core/task/__tests__/auto-retry.spec.ts @@ -0,0 +1,125 @@ +import * as os from "os" +import * as path from "path" +import * as vscode from "vscode" +import { Task } from "../Task" + +// Mock dependencies +vi.mock("delay", () => ({ + __esModule: true, + default: vi.fn().mockResolvedValue(undefined), +})) + +vi.mock("p-wait-for", () => ({ + default: vi.fn().mockImplementation(async () => Promise.resolve()), +})) + +vi.mock("vscode", () => { + return { + workspace: { + getConfiguration: vi.fn(() => ({ get: vi.fn() })), + }, + env: { + uriScheme: "vscode", + language: "en", + }, + EventEmitter: vi.fn().mockImplementation(() => ({ + event: vi.fn(), + fire: vi.fn(), + })), + } +}) + +describe("Auto-Retry Logic", () => { + let mockProvider: any + let mockApiConfig: any + let mockExtensionContext: any + + beforeEach(() => { + mockExtensionContext = { + globalState: { + get: vi.fn(), + update: vi.fn(), + keys: vi.fn().mockReturnValue([]), + }, + globalStorageUri: { fsPath: path.join(os.tmpdir(), "test-storage") }, + secrets: { + get: vi.fn().mockResolvedValue(undefined), + store: vi.fn().mockResolvedValue(undefined), + }, + extensionUri: { fsPath: "/mock/path" }, + extension: { packageJSON: { version: "1.0.0" } }, + } + + mockProvider = { + getState: vi.fn().mockResolvedValue({ + autoApprovalEnabled: true, + requestDelaySeconds: 1, + requestRetryMax: 3, + }), + postMessageToWebview: vi.fn().mockResolvedValue(undefined), + postStateToWebview: vi.fn().mockResolvedValue(undefined), + } + + mockApiConfig = { + apiProvider: "anthropic", + apiModelId: "claude-3-5-sonnet-20241022", + } + }) + + it("should calculate correct delay", async () => { + const task = new Task({ + context: mockExtensionContext, + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "test", + startTask: false, + }) + + const delay = (task as any).backoffAndAnnounce(1, new Error("test")) + // We can't easily await this because it has a loop with delay() + // but we can check the internal logic if we expose it or mock delay better + }) + + it("should respect requestRetryMax and alwaysApproveResubmit", async () => { + const state = { + autoApprovalEnabled: true, + alwaysApproveResubmit: true, + requestRetryMax: 2 + } + + const shouldRetry = (attempt: number) => + state.autoApprovalEnabled && + state.alwaysApproveResubmit && + (state.requestRetryMax === 0 || attempt < state.requestRetryMax) + + // retryAttempt 0 < 2 -> should retry + expect(shouldRetry(0)).toBe(true) + // retryAttempt 1 < 2 -> should retry + expect(shouldRetry(1)).toBe(true) + // retryAttempt 2 == 2 -> should NOT retry + expect(shouldRetry(2)).toBe(false) + + // If alwaysApproveResubmit is false, should NOT retry + state.alwaysApproveResubmit = false + expect(shouldRetry(0)).toBe(false) + }) + + it("should handle unlimited retries when requestRetryMax is 0", async () => { + const state = { + autoApprovalEnabled: true, + alwaysApproveResubmit: true, + requestRetryMax: 0 + } + + const shouldRetry = (attempt: number) => + state.autoApprovalEnabled && + state.alwaysApproveResubmit && + (state.requestRetryMax === 0 || attempt < state.requestRetryMax) + + expect(shouldRetry(100)).toBe(true) + + // If alwaysApproveResubmit is false, should NOT retry even with unlimited retries + state.alwaysApproveResubmit = false + expect(shouldRetry(100)).toBe(false) + }) +}) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index f896a382c5c..24ae0eafaff 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -2126,6 +2126,7 @@ export class ClineProvider enhancementApiConfigId, commitMessageApiConfigId, // kilocode_change terminalCommandApiConfigId, // kilocode_change + requestRetryMax, // kilocode_change autoApprovalEnabled, customModes, experiments, @@ -2166,6 +2167,7 @@ export class ClineProvider dismissedNotificationIds, // kilocode_change morphApiKey, // kilocode_change fastApplyModel, // kilocode_change: Fast Apply model selection + alwaysApproveResubmit, // kilocode_change fastApplyApiProvider, // kilocode_change: Fast Apply model api base url alwaysAllowFollowupQuestions, followupAutoApproveTimeoutMs, @@ -2255,6 +2257,7 @@ export class ClineProvider alwaysAllowMcp: alwaysAllowMcp ?? false, alwaysAllowModeSwitch: alwaysAllowModeSwitch ?? false, alwaysAllowSubtasks: alwaysAllowSubtasks ?? false, + alwaysApproveResubmit: alwaysApproveResubmit ?? true, // kilocode_change isBrowserSessionActive, yoloMode: yoloMode ?? false, // kilocode_change allowedMaxRequests, @@ -2401,6 +2404,8 @@ export class ClineProvider includeCurrentTime: includeCurrentTime ?? true, includeCurrentCost: includeCurrentCost ?? true, maxGitStatusFiles: maxGitStatusFiles ?? 0, + requestDelaySeconds: requestDelaySeconds ?? 10, // kilocode_change + requestRetryMax: requestRetryMax ?? 0, // kilocode_change taskSyncEnabled, remoteControlEnabled, imageGenerationProvider, @@ -2569,6 +2574,9 @@ export class ClineProvider alwaysAllowModeSwitch: stateValues.alwaysAllowModeSwitch ?? true, alwaysAllowSubtasks: stateValues.alwaysAllowSubtasks ?? true, alwaysAllowFollowupQuestions: stateValues.alwaysAllowFollowupQuestions ?? false, + alwaysApproveResubmit: stateValues.alwaysApproveResubmit ?? true, // kilocode_change + requestDelaySeconds: stateValues.requestDelaySeconds ?? 10, // kilocode_change + requestRetryMax: stateValues.requestRetryMax ?? 0, // kilocode_change isBrowserSessionActive, yoloMode: stateValues.yoloMode ?? false, // kilocode_change followupAutoApproveTimeoutMs: stateValues.followupAutoApproveTimeoutMs ?? 60000, diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index f988f2aab5e..28c21b557e0 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -673,6 +673,12 @@ export const webviewMessageHandler = async ( if (!value) { continue } + } else if ( + key === "alwaysApproveResubmit" || + key === "requestRetryMax" || + key === "requestDelaySeconds" + ) { + newValue = value } await provider.contextProxy.setValue(key as keyof RooCodeSettings, newValue) diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 79a9e6628dc..8a9f882f250 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -392,6 +392,7 @@ export type ExtensionState = Pick< | "alwaysAllowModeSwitch" | "alwaysAllowSubtasks" | "alwaysAllowFollowupQuestions" + | "alwaysApproveResubmit" // kilocode_change | "alwaysAllowExecute" | "followupAutoApproveTimeoutMs" | "allowedCommands" @@ -467,6 +468,7 @@ export type ExtensionState = Pick< | "includeCurrentCost" | "maxGitStatusFiles" | "requestDelaySeconds" + | "requestRetryMax" // kilocode_change | "selectedMicrophoneDevice" // kilocode_change: Selected microphone device for STT > & { version: string diff --git a/webview-ui/src/components/settings/AutoApproveSettings.tsx b/webview-ui/src/components/settings/AutoApproveSettings.tsx index 6d5cf173bef..e285e353949 100644 --- a/webview-ui/src/components/settings/AutoApproveSettings.tsx +++ b/webview-ui/src/components/settings/AutoApproveSettings.tsx @@ -27,6 +27,7 @@ type AutoApproveSettingsProps = HTMLAttributes & { alwaysAllowMcp?: boolean alwaysAllowModeSwitch?: boolean alwaysAllowSubtasks?: boolean + alwaysApproveResubmit?: boolean // kilocode_change alwaysAllowExecute?: boolean alwaysAllowFollowupQuestions?: boolean followupAutoApproveTimeoutMs?: number @@ -48,6 +49,7 @@ type AutoApproveSettingsProps = HTMLAttributes & { | "alwaysAllowMcp" | "alwaysAllowModeSwitch" | "alwaysAllowSubtasks" + | "alwaysApproveResubmit" // kilocode_change | "alwaysAllowExecute" | "alwaysAllowFollowupQuestions" | "followupAutoApproveTimeoutMs" @@ -71,6 +73,7 @@ export const AutoApproveSettings = ({ alwaysAllowMcp, alwaysAllowModeSwitch, alwaysAllowSubtasks, + alwaysApproveResubmit, // kilocode_change alwaysAllowExecute, alwaysAllowFollowupQuestions, followupAutoApproveTimeoutMs = 60000, @@ -87,7 +90,16 @@ export const AutoApproveSettings = ({ const { t } = useAppTranslation() const [commandInput, setCommandInput] = useState("") const [deniedCommandInput, setDeniedCommandInput] = useState("") - const { autoApprovalEnabled, setAutoApprovalEnabled, listApiConfigMeta } = useExtensionState() // kilocode_change: Add listApiConfigMeta for gatekeeper + const { + autoApprovalEnabled, + setAutoApprovalEnabled, + alwaysApproveResubmit: alwaysApproveResubmitState, // kilocode_change + listApiConfigMeta, + requestDelaySeconds, + requestRetryMax, + setRequestRetryMax, + setRequestDelaySeconds, + } = useExtensionState() // kilocode_change: Add listApiConfigMeta for gatekeeper const toggles = useAutoApprovalToggles() @@ -195,6 +207,7 @@ export const AutoApproveSettings = ({ alwaysAllowMcp={alwaysAllowMcp} alwaysAllowModeSwitch={alwaysAllowModeSwitch} alwaysAllowSubtasks={alwaysAllowSubtasks} + alwaysApproveResubmit={alwaysApproveResubmit ?? alwaysApproveResubmitState} // kilocode_change alwaysAllowExecute={alwaysAllowExecute} alwaysAllowFollowupQuestions={alwaysAllowFollowupQuestions} onToggle={(key, value) => setCachedStateField(key, value)} @@ -298,6 +311,71 @@ export const AutoApproveSettings = ({ )} + {/* kilocode_change start */} + {(alwaysApproveResubmit ?? alwaysApproveResubmitState) && ( +
+
+ +
{t("settings:autoApprove.retry.label")}
+
+
+
+
+
+ { + setRequestDelaySeconds(value) + vscode.postMessage({ + type: "updateSettings", + updatedSettings: { requestDelaySeconds: value }, + }) + }} + /> + {requestDelaySeconds ?? 5}s +
+
+ {t("settings:autoApprove.retry.delayLabel")} +
+
+ +
+
+ { + setRequestRetryMax(value) + vscode.postMessage({ + type: "updateSettings", + updatedSettings: { requestRetryMax: value }, + }) + }} + /> + + {requestRetryMax === 0 || requestRetryMax === undefined + ? "∞" + : requestRetryMax} + +
+
+ {t("settings:autoApprove.retry.retriesLabel")} +
+
+
+ +
+
+ )} + {/* kilocode_change end */} + {alwaysAllowExecute && (
diff --git a/webview-ui/src/components/settings/AutoApproveToggle.tsx b/webview-ui/src/components/settings/AutoApproveToggle.tsx index 6bdc12bc715..dbfab13ba83 100644 --- a/webview-ui/src/components/settings/AutoApproveToggle.tsx +++ b/webview-ui/src/components/settings/AutoApproveToggle.tsx @@ -13,6 +13,7 @@ type AutoApproveToggles = Pick< | "alwaysAllowMcp" | "alwaysAllowModeSwitch" | "alwaysAllowSubtasks" + | "alwaysApproveResubmit" // kilocode_change | "alwaysAllowExecute" | "alwaysAllowFollowupQuestions" > @@ -79,6 +80,15 @@ export const autoApproveSettingsConfig: Record((props, ref) const { alwaysAllowReadOnly, alwaysAllowReadOnlyOutsideWorkspace, + alwaysAllowDelete, // kilocode_change allowedCommands, deniedCommands, allowedMaxRequests, @@ -178,6 +179,9 @@ const SettingsView = forwardRef((props, ref) alwaysAllowMcp, alwaysAllowModeSwitch, alwaysAllowSubtasks, + alwaysApproveResubmit, // kilocode_change + requestDelaySeconds, // kilocode_change + requestRetryMax, // kilocode_change alwaysAllowWrite, alwaysAllowWriteOutsideWorkspace, alwaysAllowWriteProtected, @@ -522,6 +526,10 @@ const SettingsView = forwardRef((props, ref) alwaysAllowBrowser: alwaysAllowBrowser ?? undefined, alwaysAllowMcp, alwaysAllowModeSwitch, + alwaysAllowDelete, // kilocode_change + alwaysApproveResubmit, // kilocode_change + requestDelaySeconds, // kilocode_change + requestRetryMax, // kilocode_change allowedCommands: allowedCommands ?? [], deniedCommands: deniedCommands ?? [], // Note that we use `null` instead of `undefined` since `JSON.stringify` @@ -1029,6 +1037,7 @@ const SettingsView = forwardRef((props, ref) alwaysAllowMcp={alwaysAllowMcp} alwaysAllowModeSwitch={alwaysAllowModeSwitch} alwaysAllowSubtasks={alwaysAllowSubtasks} + alwaysApproveResubmit={alwaysApproveResubmit} // kilocode_change alwaysAllowExecute={alwaysAllowExecute} alwaysAllowFollowupQuestions={alwaysAllowFollowupQuestions} followupAutoApproveTimeoutMs={followupAutoApproveTimeoutMs} diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveToggle.spec.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveToggle.spec.tsx index bd423e7bf56..bedf1c91566 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveToggle.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveToggle.spec.tsx @@ -24,6 +24,7 @@ describe("AutoApproveToggle", () => { alwaysAllowMcp: false, alwaysAllowModeSwitch: true, alwaysAllowSubtasks: false, + alwaysApproveResubmit: false, // kilocode_change alwaysAllowExecute: true, alwaysAllowFollowupQuestions: false, onToggle: mockOnToggle, diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index 679059f68a1..bfdd7f6e4a1 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -42,6 +42,8 @@ export interface ExtensionStateContextType extends ExtensionState { setShowDiffStats: (value: boolean) => void // kilocode_change hideCostBelowThreshold?: number // kilocode_change setHideCostBelowThreshold: (value: number) => void // kilocode_change + requestRetryMax?: number // kilocode_change + setRequestRetryMax: (value: number) => void // kilocode_change hoveringTaskTimeline?: boolean // kilocode_change setHoveringTaskTimeline: (value: boolean) => void // kilocode_change systemNotificationsEnabled?: boolean // kilocode_change @@ -118,6 +120,8 @@ export interface ExtensionStateContextType extends ExtensionState { setAlwaysAllowMcp: (value: boolean) => void setAlwaysAllowModeSwitch: (value: boolean) => void setAlwaysAllowSubtasks: (value: boolean) => void + alwaysApproveResubmit: boolean // kilocode_change + setAlwaysApproveResubmit: (value: boolean) => void // kilocode_change setBrowserToolEnabled: (value: boolean) => void setShowRooIgnoredFiles: (value: boolean) => void setShowAutoApproveMenu: (value: boolean) => void // kilocode_change @@ -127,6 +131,7 @@ export interface ExtensionStateContextType extends ExtensionState { setDeniedCommands: (value: string[]) => void setAllowedMaxRequests: (value: number | undefined) => void setAllowedMaxCost: (value: number | undefined) => void + setRequestDelaySeconds: (value: number) => void // kilocode_change setSoundEnabled: (value: boolean) => void setSoundVolume: (value: number) => void terminalShellIntegrationTimeout?: number @@ -273,7 +278,9 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode featureRoomoteControlEnabled: false, alwaysAllowWrite: true, // kilocode_change alwaysAllowReadOnly: true, // kilocode_change - requestDelaySeconds: 5, + alwaysApproveResubmit: true, // kilocode_change + requestDelaySeconds: 10, + requestRetryMax: 0, // kilocode_change currentApiConfigName: "default", listApiConfigMeta: [], mode: defaultModeSlug, @@ -385,6 +392,11 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode const [prevCloudIsAuthenticated, setPrevCloudIsAuthenticated] = useState(false) const [includeCurrentTime, setIncludeCurrentTime] = useState(true) const [includeCurrentCost, setIncludeCurrentCost] = useState(true) + // kilocode_change start + const [alwaysApproveResubmit, setAlwaysApproveResubmit] = useState(true) + const [requestDelaySeconds, setRequestDelaySeconds] = useState(10) + const [requestRetryMax, setRequestRetryMax] = useState(0) + // kilocode_change end const setListApiConfigMeta = useCallback( (value: ProviderSettingsEntry[]) => setState((prevState) => ({ ...prevState, listApiConfigMeta: value })), @@ -430,6 +442,17 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode if ((newState as any).includeCurrentCost !== undefined) { setIncludeCurrentCost((newState as any).includeCurrentCost) } + // kilocode_change start + if (newState.alwaysApproveResubmit !== undefined) { + setAlwaysApproveResubmit(newState.alwaysApproveResubmit) + } + if (newState.requestDelaySeconds !== undefined) { + setRequestDelaySeconds(newState.requestDelaySeconds) + } + if (newState.requestRetryMax !== undefined) { + setRequestRetryMax(newState.requestRetryMax) + } + // kilocode_change end // Handle marketplace data if present in state message if (newState.marketplaceItems !== undefined) { setMarketplaceItems(newState.marketplaceItems) @@ -601,6 +624,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setAlwaysAllowMcp: (value) => setState((prevState) => ({ ...prevState, alwaysAllowMcp: value })), setAlwaysAllowModeSwitch: (value) => setState((prevState) => ({ ...prevState, alwaysAllowModeSwitch: value })), setAlwaysAllowSubtasks: (value) => setState((prevState) => ({ ...prevState, alwaysAllowSubtasks: value })), + alwaysApproveResubmit, // kilocode_change + setAlwaysApproveResubmit, // kilocode_change setAlwaysAllowFollowupQuestions, setFollowupAutoApproveTimeoutMs: (value) => setState((prevState) => ({ ...prevState, followupAutoApproveTimeoutMs: value })), @@ -609,6 +634,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setDeniedCommands: (value) => setState((prevState) => ({ ...prevState, deniedCommands: value })), setAllowedMaxRequests: (value) => setState((prevState) => ({ ...prevState, allowedMaxRequests: value })), setAllowedMaxCost: (value) => setState((prevState) => ({ ...prevState, allowedMaxCost: value })), + requestDelaySeconds, // kilocode_change + setRequestDelaySeconds, // kilocode_change setSoundEnabled: (value) => setState((prevState) => ({ ...prevState, soundEnabled: value })), setSoundVolume: (value) => setState((prevState) => ({ ...prevState, soundVolume: value })), setTtsEnabled: (value) => setState((prevState) => ({ ...prevState, ttsEnabled: value })), @@ -661,6 +688,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setSendMessageOnEnter: (value) => setState((prevState) => ({ ...prevState, sendMessageOnEnter: value })), // kilocode_change setHideCostBelowThreshold: (value) => setState((prevState) => ({ ...prevState, hideCostBelowThreshold: value })), + requestRetryMax, // kilocode_change + setRequestRetryMax, // kilocode_change setHoveringTaskTimeline: (value) => setState((prevState) => ({ ...prevState, hoveringTaskTimeline: value })), setShowTimestamps: (value) => setState((prevState) => ({ ...prevState, showTimestamps: value })), setShowDiffStats: (value) => setState((prevState) => ({ ...prevState, showDiffStats: value })), // kilocode_change diff --git a/webview-ui/src/hooks/useAutoApprovalToggles.ts b/webview-ui/src/hooks/useAutoApprovalToggles.ts index d52ad373b69..f262187dd36 100644 --- a/webview-ui/src/hooks/useAutoApprovalToggles.ts +++ b/webview-ui/src/hooks/useAutoApprovalToggles.ts @@ -16,6 +16,7 @@ export function useAutoApprovalToggles() { alwaysAllowModeSwitch, alwaysAllowSubtasks, alwaysAllowFollowupQuestions, + alwaysApproveResubmit, // kilocode_change } = useExtensionState() const toggles = useMemo( @@ -29,6 +30,7 @@ export function useAutoApprovalToggles() { alwaysAllowModeSwitch, alwaysAllowSubtasks, alwaysAllowFollowupQuestions, + alwaysApproveResubmit, // kilocode_change }), [ alwaysAllowReadOnly, @@ -40,6 +42,7 @@ export function useAutoApprovalToggles() { alwaysAllowModeSwitch, alwaysAllowSubtasks, alwaysAllowFollowupQuestions, + alwaysApproveResubmit, // kilocode_change ], ) diff --git a/webview-ui/src/i18n/locales/ar/settings.json b/webview-ui/src/i18n/locales/ar/settings.json index a9633496af6..70279ad4ddf 100644 --- a/webview-ui/src/i18n/locales/ar/settings.json +++ b/webview-ui/src/i18n/locales/ar/settings.json @@ -243,7 +243,8 @@ "retry": { "label": "إعادة المحاولة", "description": "إعادة محاولة طلبات API الفاشلة تلقائيًا", - "delayLabel": "تأخير قبل الإعادة" + "delayLabel": "تأخير قبل الإعادة", + "retriesLabel": "الحد الأقصى لعدد مرات إعادة المحاولة التلقائية لطلبات API" }, "mcp": { "label": "MCP", diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index ecf29893c58..de90681d20a 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -210,6 +210,12 @@ "label": "Navegador", "description": "Realitzar accions del navegador automàticament sense requerir aprovació. Nota: Només s'aplica quan el model admet l'ús de l'ordinador" }, + "retry": { + "label": "Reintentar", + "description": "Torna a provar automàticament les sol·licituds quan el model no proporciona una resposta o quan s'assoleix un límit de taxa.", + "delayLabel": "Retard base entre reintents (segons)", + "retriesLabel": "Nombre màxim de reintents automàtics per a sol·licituds d'API" + }, "mcp": { "label": "MCP", "description": "Habilitar l'aprovació automàtica d'eines MCP individuals a la vista de Servidors MCP (requereix tant aquesta configuració com la casella \"Permetre sempre\" de l'eina)" diff --git a/webview-ui/src/i18n/locales/cs/settings.json b/webview-ui/src/i18n/locales/cs/settings.json index 26513fdcf39..a1d0e4e2976 100644 --- a/webview-ui/src/i18n/locales/cs/settings.json +++ b/webview-ui/src/i18n/locales/cs/settings.json @@ -228,8 +228,9 @@ }, "retry": { "label": "Zkusit znovu", - "description": "Automaticky opakovat neúspěšné požadavky API, když server vrátí chybovou odpověď", - "delayLabel": "Zpoždění před opakováním požadavku" + "description": "Automaticky opakovat požadavky, když model neposkytne odpověď nebo když je dosaženo limitu sazeb.", + "delayLabel": "Základní zpoždění mezi pokusy (sekundy)", + "retriesLabel": "Maximální počet automatických opakování pro požadavky API" }, "mcp": { "label": "MCP", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 0a3cda94989..cfaf98e262f 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -210,6 +210,12 @@ "label": "Browser", "description": "Browser-Aktionen automatisch ohne Genehmigung durchführen. Hinweis: Gilt nur, wenn das Modell Computer-Nutzung unterstützt" }, + "retry": { + "label": "Wiederholen", + "description": "Anfragen automatisch wiederholen, wenn das Modell keine Antwort liefert oder wenn ein Ratenlimit erreicht wird.", + "delayLabel": "Basisverzögerung zwischen Wiederholungsversuchen (Sekunden)", + "retriesLabel": "Maximale automatische Wiederholungsversuche für API-Anfragen" + }, "mcp": { "label": "MCP", "description": "Automatische Genehmigung einzelner MCP-Tools in der MCP-Server-Ansicht aktivieren (erfordert sowohl diese Einstellung als auch das 'Immer erlauben'-Kontrollkästchen des Tools)" diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 9e487e9b312..e29db12a6bb 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -239,6 +239,12 @@ "description": "Automatically select the first suggested answer for follow-up questions after the configured timeout", "timeoutLabel": "Time to wait before auto-selecting the first answer" }, + "retry": { + "label": "Retry", + "description": "Automatically retry requests when the model fails to provide a response or when a rate limit is reached.", + "delayLabel": "Base delay between retries (seconds)", + "retriesLabel": "Maximum auto-retries for API requests" + }, "execute": { "label": "Execute", "description": "Automatically execute allowed terminal commands without requiring approval", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index 95efa64153c..8232771e111 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -214,6 +214,12 @@ "label": "Navegador", "description": "Realizar acciones del navegador automáticamente sin requerir aprobación. Nota: Solo se aplica cuando el modelo admite el uso del ordenador" }, + "retry": { + "label": "Reintentar", + "description": "Reintentar automáticamente las solicitudes cuando el modelo no proporciona una respuesta o cuando se alcanza un límite de tasa.", + "delayLabel": "Retraso base entre reintentos (segundos)", + "retriesLabel": "Máximo de reintentos automáticos para solicitudes de API" + }, "mcp": { "label": "MCP", "description": "Habilitar la aprobación automática de herramientas MCP individuales en la vista de Servidores MCP (requiere tanto esta configuración como la casilla \"Permitir siempre\" de la herramienta)" diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 17551bd6c7f..ab65bdac127 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -211,6 +211,12 @@ "label": "Navigateur", "description": "Effectuer automatiquement des actions du navigateur sans nécessiter d'approbation. Remarque : S'applique uniquement lorsque le modèle prend en charge l'utilisation de l'ordinateur" }, + "retry": { + "label": "Réessayer", + "description": "Réessayer automatiquement les requêtes lorsque le modèle ne fournit pas de réponse ou lorsqu'une limite de débit est atteinte.", + "delayLabel": "Délai de base entre les tentatives (secondes)", + "retriesLabel": "Nombre maximal de tentatives automatiques pour les requêtes API" + }, "mcp": { "label": "MCP", "description": "Activer l'approbation automatique des outils MCP individuels dans la vue des serveurs MCP (nécessite à la fois ce paramètre et la case à cocher \"Toujours autoriser\" de l'outil)" diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index adf8b7e3b02..39b41b4e458 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -210,6 +210,12 @@ "label": "हटाएं", "description": "अनुमोदन की आवश्यकता के बिना स्वचालित रूप से फाइलें और निर्देशिकाएं हटाएं" }, + "retry": { + "label": "पुनः प्रयास करें", + "description": "जब मॉडल प्रतिक्रिया देने में विफल रहता है या जब दर सीमा तक पहुँच जाती है तो स्वचालित रूप से अनुरोधों का पुनः प्रयास करें।", + "delayLabel": "पुनः प्रयासों के बीच आधार विलंब (सेकंड)", + "retriesLabel": "API अनुरोधों के लिए अधिकतम स्वतः-पुनः प्रयास" + }, "browser": { "label": "ब्राउज़र", "description": "अनुमोदन की आवश्यकता के बिना स्वचालित रूप से ब्राउज़र क्रियाएँ करें — नोट: केवल तभी लागू होता है जब मॉडल कंप्यूटर उपयोग का समर्थन करता है" diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index c8a9423af68..34df8baccb6 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -214,6 +214,12 @@ "label": "Browser", "description": "Secara otomatis melakukan aksi browser tanpa memerlukan persetujuan. Catatan: Hanya berlaku ketika model mendukung computer use" }, + "retry": { + "label": "Coba Lagi", + "description": "Secara otomatis mencoba kembali permintaan saat model gagal memberikan respons atau saat batas laju tercapai.", + "delayLabel": "Penundaan dasar antar percobaan ulang (detik)", + "retriesLabel": "Maksimum percobaan ulang otomatis untuk permintaan API" + }, "mcp": { "label": "MCP", "description": "Aktifkan auto-approval tool MCP individual di tampilan Server MCP (memerlukan pengaturan ini dan checkbox \"Selalu izinkan\" tool tersebut)" diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 779e6fcbdd8..1702f944e6b 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -217,8 +217,9 @@ }, "retry": { "label": "Riprova", - "description": "Riprova automaticamente le richieste API fallite quando il server restituisce una risposta di errore", - "delayLabel": "Ritardo prima di riprovare la richiesta" + "description": "Riprova automaticamente le richieste quando il modello non fornisce una risposta o quando viene raggiunto un limite di frequenza.", + "delayLabel": "Ritardo di base tra i tentativi (secondi)", + "retriesLabel": "Numero massimo di tentativi automatici per le richieste API" }, "mcp": { "label": "MCP", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index b35add6fcc7..b622448d08f 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -217,8 +217,9 @@ }, "retry": { "label": "再試行", - "description": "サーバーがエラーレスポンスを返した場合、自動的に失敗したAPIリクエストを再試行", - "delayLabel": "リクエスト再試行前の遅延" + "description": "モデルが応答を返さない場合や、レート制限に達した場合に、リクエストを自動的に再試行します。", + "delayLabel": "再試行間の基本遅延(秒)", + "retriesLabel": "APIリクエストの最大自動再試行回数" }, "mcp": { "label": "MCP", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index ffb6c92024a..67800f0d942 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -210,6 +210,12 @@ "label": "브라우저", "description": "승인 없이 자동으로 브라우저 작업 수행 — 참고: 모델이 컴퓨터 사용을 지원할 때만 적용됩니다" }, + "retry": { + "label": "재시도", + "description": "모델이 응답을 제공하지 못하거나 속도 제한에 도달했을 때 요청을 자동으로 재시도합니다.", + "delayLabel": "재시도 간 기본 지연 시간(초)", + "retriesLabel": "API 요청에 대한 최대 자동 재시도 횟수" + }, "mcp": { "label": "MCP", "description": "MCP 서버 보기에서 개별 MCP 도구의 자동 승인 활성화(이 설정과 도구의 \"항상 허용\" 체크박스 모두 필요)" diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 90d01fb4fe9..9c72418e08e 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -214,6 +214,12 @@ "label": "Browser", "description": "Automatisch browseracties uitvoeren zonder goedkeuring. Let op: geldt alleen als het model computergebruik ondersteunt." }, + "retry": { + "label": "Opnieuw proberen", + "description": "Aanvragen automatisch opnieuw proberen wanneer het model geen antwoord geeft of wanneer een snelheidslimiet is bereikt.", + "delayLabel": "Basisvertraging tussen pogingen (seconden)", + "retriesLabel": "Maximaal aantal automatische herpogingen voor API-aanvragen" + }, "mcp": { "label": "MCP", "description": "Automatische goedkeuring van individuele MCP-tools in het MCP-serversoverzicht inschakelen (vereist zowel deze instelling als het selectievakje 'Altijd toestaan' bij de tool)" diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index a4484a5389d..d30b30a4551 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -214,6 +214,12 @@ "label": "Przeglądarka", "description": "Automatycznie wykonuj akcje przeglądarki bez konieczności zatwierdzania. Uwaga: Dotyczy tylko gdy model obsługuje używanie komputera" }, + "retry": { + "label": "Ponów", + "description": "Automatycznie ponawiaj żądania, gdy model nie dostarczy odpowiedzi lub gdy zostanie osiągnięty limit szybkości.", + "delayLabel": "Podstawowe opóźnienie między próbami (sekundy)", + "retriesLabel": "Maksymalna liczba automatycznych powtórzeń dla żądań API" + }, "mcp": { "label": "MCP", "description": "Włącz automatyczne zatwierdzanie poszczególnych narzędzi MCP w widoku Serwerów MCP (wymaga zarówno tego ustawienia, jak i pola wyboru \"Zawsze zezwalaj\" narzędzia)" diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 0b826365bf7..bfe4c3eef11 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -214,6 +214,12 @@ "label": "Navegador", "description": "Realizar ações do navegador automaticamente sem exigir aprovação. Nota: Aplica-se apenas quando o modelo suporta uso do computador" }, + "retry": { + "label": "Repetir", + "description": "Repetir solicitações automaticamente quando o modelo falha em fornecer uma resposta ou quando um limite de taxa é atingido.", + "delayLabel": "Atraso base entre repetições (segundos)", + "retriesLabel": "Máximo de repetições automáticas para solicitações de API" + }, "mcp": { "label": "MCP", "description": "Ativar aprovação automática de ferramentas MCP individuais na visualização de Servidores MCP (requer tanto esta configuração quanto a caixa de seleção \"Permitir sempre\" da ferramenta)" diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 4a7f783c049..8cf61c03693 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -214,6 +214,12 @@ "label": "Браузер", "description": "Автоматически выполнять действия в браузере без необходимости одобрения. Применяется только, если модель поддерживает использование компьютера" }, + "retry": { + "label": "Повторить", + "description": "Автоматически повторять запросы, если модель не дает ответа или достигнут лимит частоты запросов.", + "delayLabel": "Базовая задержка между повторами (секунды)", + "retriesLabel": "Максимальное количество автоповторов для API-запросов" + }, "mcp": { "label": "MCP", "description": "Включить автоодобрение отдельных инструментов MCP в представлении MCP Servers (требуется включить как этот параметр, так и индивидуальный чекбокс инструмента \"Всегда разрешать\")" diff --git a/webview-ui/src/i18n/locales/th/settings.json b/webview-ui/src/i18n/locales/th/settings.json index 128d387bee1..2428900db27 100644 --- a/webview-ui/src/i18n/locales/th/settings.json +++ b/webview-ui/src/i18n/locales/th/settings.json @@ -243,8 +243,9 @@ }, "retry": { "label": "ลองใหม่", - "description": "ลองส่งคำขอ API ที่ล้มเหลวอีกครั้งโดยอัตโนมัติเมื่อเซิร์ฟเวอร์ส่งคืนการตอบสนองที่ผิดพลาด", - "delayLabel": "หน่วงเวลาก่อนลองส่งคำขออีกครั้ง" + "description": "ลองส่งคำขอโดยอัตโนมัติเมื่อโมเดลไม่ตอบสนองหรือเมื่อถึงขีดจำกัดอัตรา", + "delayLabel": "การหน่วงเวลาพื้นฐานระหว่างการลองใหม่ (วินาที)", + "retriesLabel": "จำนวนการลองใหม่อัตโนมัติสูงสุดสำหรับคำขอ API" }, "mcp": { "label": "MCP", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index d7923a9d0d6..fadab817625 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -215,6 +215,12 @@ "label": "Tarayıcı", "description": "Onay gerektirmeden otomatik olarak tarayıcı eylemleri gerçekleştir. Not: Yalnızca model bilgisayar kullanımını desteklediğinde geçerlidir" }, + "retry": { + "label": "Yeniden Dene", + "description": "Model yanıt vermediğinde veya bir hız sınırına ulaşıldığında istekleri otomatik olarak yeniden deneyin.", + "delayLabel": "Yeniden denemeler arasındaki temel gecikme (saniye)", + "retriesLabel": "API istekleri için maksimum otomatik yeniden deneme sayısı" + }, "mcp": { "label": "MCP", "description": "MCP Sunucuları görünümünde bireysel MCP araçlarının otomatik onayını etkinleştir (hem bu ayar hem de aracın \"Her zaman izin ver\" onay kutusu gerekir)" diff --git a/webview-ui/src/i18n/locales/uk/settings.json b/webview-ui/src/i18n/locales/uk/settings.json index 5a999828dd4..030e3e22725 100644 --- a/webview-ui/src/i18n/locales/uk/settings.json +++ b/webview-ui/src/i18n/locales/uk/settings.json @@ -249,8 +249,9 @@ }, "retry": { "label": "Повторити", - "description": "Автоматично повторювати невдалі запити API, коли сервер повертає відповідь про помилку", - "delayLabel": "Затримка перед повторним запитом" + "description": "Автоматично повторювати запити, коли модель не надає відповідь або коли досягнуто ліміту частоти запитів.", + "delayLabel": "Базова затримка між спробами (секунди)", + "retriesLabel": "Максимальна кількість автоматичних повторів для запитів API" }, "mcp": { "label": "MCP", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 7c104bde29b..037201df9ae 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -214,6 +214,12 @@ "label": "Trình duyệt", "description": "Tự động thực hiện các hành động trình duyệt mà không cần phê duyệt. Lưu ý: Chỉ áp dụng khi mô hình hỗ trợ sử dụng máy tính" }, + "retry": { + "label": "Thử lại", + "description": "Tự động thử lại các yêu cầu khi mô hình không cung cấp phản hồi hoặc khi đạt đến giới hạn tốc độ.", + "delayLabel": "Độ trễ cơ bản giữa các lần thử lại (giây)", + "retriesLabel": "Số lần tự động thử lại tối đa cho các yêu cầu API" + }, "mcp": { "label": "MCP", "description": "Bật tự động phê duyệt các công cụ MCP riêng lẻ trong chế độ xem Máy chủ MCP (yêu cầu cả cài đặt này và hộp kiểm \"Luôn cho phép\" của công cụ)" diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 419198ec64b..77660fb0f61 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -214,6 +214,12 @@ "label": "浏览器", "description": "自动执行浏览器操作而无需批准 — 注意:仅当模型支持计算机功能调用时适用" }, + "retry": { + "label": "重试", + "description": "当模型未能提供响应或达到速率限制时,自动重试请求。", + "delayLabel": "重试之间的基础延迟(秒)", + "retriesLabel": "API 请求的最大自动重试次数" + }, "mcp": { "label": "MCP", "description": "允许自动调用MCP服务而无需批准" diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 9746890711b..9ce1a0cdcdb 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -211,6 +211,12 @@ "label": "瀏覽器", "description": "自動執行瀏覽器操作而無需核准 — 注意:僅適用於模型支援電腦使用時" }, + "retry": { + "label": "重試", + "description": "當模型未能提供回應或達到速率限制時,自動重試請求。", + "delayLabel": "重試之間的基礎延遲(秒)", + "retriesLabel": "API 請求的最大自動重試次數" + }, "mcp": { "label": "MCP", "description": "在 MCP 伺服器檢視中啟用個別 MCP 工具的自動核准(需要此設定和工具的「始終允許」核取方塊)"