diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index 205812c796..145c0bcf54 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -29,6 +29,21 @@ export const DEFAULT_WRITE_DELAY_MS = 1000 */ export const DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT = 50_000 +/** + * Minimum checkpoint timeout in seconds. + */ +export const MIN_CHECKPOINT_TIMEOUT_SECONDS = 10 + +/** + * Maximum checkpoint timeout in seconds. + */ +export const MAX_CHECKPOINT_TIMEOUT_SECONDS = 60 + +/** + * Default checkpoint timeout in seconds. + */ +export const DEFAULT_CHECKPOINT_TIMEOUT_SECONDS = 15 + /** * GlobalSettings */ @@ -97,7 +112,12 @@ export const globalSettingsSchema = z.object({ cachedChromeHostUrl: z.string().optional(), enableCheckpoints: z.boolean().optional(), - checkpointTimeout: z.number().optional(), + checkpointTimeout: z + .number() + .int() + .min(MIN_CHECKPOINT_TIMEOUT_SECONDS) + .max(MAX_CHECKPOINT_TIMEOUT_SECONDS) + .optional(), ttsEnabled: z.boolean().optional(), ttsSpeed: z.number().optional(), diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index cc4fe55dd0..b9c6c9fcde 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -35,6 +35,7 @@ import { isInteractiveAsk, isResumableAsk, QueuedMessage, + DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, } from "@roo-code/types" import { TelemetryService } from "@roo-code/telemetry" import { CloudService, BridgeOrchestrator } from "@roo-code/cloud" @@ -304,7 +305,7 @@ export class Task extends EventEmitter implements TaskLike { apiConfiguration, enableDiff = false, enableCheckpoints = true, - checkpointTimeout = 15, + checkpointTimeout = DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, enableBridge = false, fuzzyMatchThreshold = 1.0, consecutiveMistakeLimit = DEFAULT_CONSECUTIVE_MISTAKE_LIMIT, diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 99a2db6171..b7ba78d90f 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -40,6 +40,7 @@ import { DEFAULT_WRITE_DELAY_MS, ORGANIZATION_ALLOW_ALL, DEFAULT_MODES, + DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, } from "@roo-code/types" import { TelemetryService } from "@roo-code/telemetry" import { CloudService, BridgeOrchestrator, getRooCodeApiUrl } from "@roo-code/cloud" @@ -1832,7 +1833,7 @@ export class ClineProvider ttsSpeed: ttsSpeed ?? 1.0, diffEnabled: diffEnabled ?? true, enableCheckpoints: enableCheckpoints ?? true, - checkpointTimeout: checkpointTimeout ?? 15, + checkpointTimeout: checkpointTimeout ?? DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, shouldShowAnnouncement: telemetrySetting !== "unset" && lastShownAnnouncementId !== this.latestAnnouncementId, allowedCommands: mergedAllowedCommands, @@ -2053,7 +2054,7 @@ export class ClineProvider ttsSpeed: stateValues.ttsSpeed ?? 1.0, diffEnabled: stateValues.diffEnabled ?? true, enableCheckpoints: stateValues.enableCheckpoints ?? true, - checkpointTimeout: stateValues.checkpointTimeout ?? 15, + checkpointTimeout: stateValues.checkpointTimeout ?? DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, soundVolume: stateValues.soundVolume, browserViewportSize: stateValues.browserViewportSize ?? "900x600", screenshotQuality: stateValues.screenshotQuality ?? 75, diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index e362535282..fbb69787e9 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -4,7 +4,12 @@ import Anthropic from "@anthropic-ai/sdk" import * as vscode from "vscode" import axios from "axios" -import { type ProviderSettingsEntry, type ClineMessage, ORGANIZATION_ALLOW_ALL } from "@roo-code/types" +import { + type ProviderSettingsEntry, + type ClineMessage, + ORGANIZATION_ALLOW_ALL, + DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, +} from "@roo-code/types" import { TelemetryService } from "@roo-code/telemetry" import { ExtensionMessage, ExtensionState } from "../../../shared/ExtensionMessage" @@ -557,7 +562,7 @@ describe("ClineProvider", () => { remoteControlEnabled: false, taskSyncEnabled: false, featureRoomoteControlEnabled: false, - checkpointTimeout: 15, + checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, } const message: ExtensionMessage = { diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 22515ccd81..583073dbe6 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -12,6 +12,7 @@ import { type TelemetrySetting, TelemetryEventName, UserSettingsConfig, + DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, } from "@roo-code/types" import { CloudService } from "@roo-code/cloud" import { TelemetryService } from "@roo-code/telemetry" @@ -1260,7 +1261,7 @@ export const webviewMessageHandler = async ( await provider.postStateToWebview() break case "checkpointTimeout": - const checkpointTimeout = message.value ?? 15 + const checkpointTimeout = message.value ?? DEFAULT_CHECKPOINT_TIMEOUT_SECONDS await updateGlobalState("checkpointTimeout", checkpointTimeout) await provider.postStateToWebview() break diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index 1bc5810a5e..47bb0b85c3 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -31,7 +31,7 @@ "git_not_installed": "Git is required for the checkpoints feature. Please install Git to enable checkpoints.", "nested_git_repos_warning": "Checkpoints are disabled because a nested git repository was detected at: {{path}}. To use checkpoints, please remove or relocate this nested git repository.", "wait_checkpoint_long_time": "Checkpoint initialization is taking longer than expected. This may indicate a large repository or slow Git operations.", - "init_checkpoint_fail_long_time": "Checkpoint initialization failed after taking long time. Checkpoints have been disabled for this task. You can disable checkpoints entirely or increase the timeout in settings.", + "init_checkpoint_fail_long_time": "Checkpoint initialization failed after taking a long time. Checkpoints have been disabled for this task. You can disable checkpoints entirely or increase the timeout in settings.", "no_workspace": "Please open a project folder first", "update_support_prompt": "Failed to update support prompt", "reset_support_prompt": "Failed to reset support prompt", diff --git a/src/i18n/locales/hi/common.json b/src/i18n/locales/hi/common.json index 25d6601e88..e0c49a370d 100644 --- a/src/i18n/locales/hi/common.json +++ b/src/i18n/locales/hi/common.json @@ -27,7 +27,7 @@ "could_not_open_file": "फ़ाइल नहीं खोली जा सकी: {{errorMessage}}", "could_not_open_file_generic": "फ़ाइल नहीं खोली जा सकी!", "checkpoint_timeout": "चेकपॉइंट को पुनर्स्थापित करने का प्रयास करते समय टाइमआउट हो गया।", - "wait_checkpoint_long_time": "चेकपॉइंट इनिशियलाइज़ेशन अपेक्षा से अधिक समय ले रहा है। यह बड़े रिपॉजिटरी या धीमी Git ऑपरेशन्स का संकेत हो सकता है।", + "wait_checkpoint_long_time": "चेकपॉइंट इनिशियलाइज़ेशन अपेक्षा से अधिक समय ले रहा है। यह बड़ी रिपॉजिटरी या धीमी Git ऑपरेशन्स का संकेत हो सकता है।", "init_checkpoint_fail_long_time": "चेकपॉइंट इनिशियलाइज़ेशन लंबे समय बाद विफल हो गया। इस कार्य के लिए चेकपॉइंट्स अक्षम कर दिए गए हैं। तुम चेकपॉइंट्स पूरी तरह अक्षम कर सकते हो या सेटिंग्स में टाइमआउट बढ़ा सकते हो।", "checkpoint_failed": "चेकपॉइंट पुनर्स्थापित करने में विफल।", "git_not_installed": "चेकपॉइंट सुविधा के लिए Git आवश्यक है। कृपया चेकपॉइंट সক্ষম करने के लिए Git इंस्टॉल करें।", diff --git a/webview-ui/src/components/chat/CheckpointWarning.tsx b/webview-ui/src/components/chat/CheckpointWarning.tsx index 1a8ff62045..b909f638db 100644 --- a/webview-ui/src/components/chat/CheckpointWarning.tsx +++ b/webview-ui/src/components/chat/CheckpointWarning.tsx @@ -1,41 +1,48 @@ import { Trans } from "react-i18next" import { VSCodeLink } from "@vscode/webview-ui-toolkit/react" -import { useMemo } from "react" interface CheckpointWarningProps { text?: string } export const CheckpointWarning = ({ text }: CheckpointWarningProps) => { - const warningText = useMemo(() => { - return text || "chat:checkpoint.initializingWarning" - }, [text]) + const settingsLink = ( + { + e.preventDefault() + window.postMessage( + { + type: "action", + action: "settingsButtonClicked", + values: { section: "checkpoints" }, + }, + "*", + ) + }} + className="inline px-0.5" + /> + ) + return (
- { - e.preventDefault() - window.postMessage( - { - type: "action", - action: "settingsButtonClicked", - values: { section: "checkpoints" }, - }, - "*", - ) - }} - className="inline px-0.5" - /> - ), - }} - /> + {text ? ( + + {text} + + ) : ( + + )}
) diff --git a/webview-ui/src/components/marketplace/__tests__/MarketplaceView.spec.tsx b/webview-ui/src/components/marketplace/__tests__/MarketplaceView.spec.tsx index 94772da066..57fc62ece0 100644 --- a/webview-ui/src/components/marketplace/__tests__/MarketplaceView.spec.tsx +++ b/webview-ui/src/components/marketplace/__tests__/MarketplaceView.spec.tsx @@ -5,6 +5,7 @@ import { vscode } from "@/utils/vscode" import { MarketplaceView } from "../MarketplaceView" import { MarketplaceViewStateManager } from "../MarketplaceViewStateManager" +import { DEFAULT_CHECKPOINT_TIMEOUT_SECONDS } from "@roo-code/types" vi.mock("@/utils/vscode", () => ({ vscode: { @@ -66,7 +67,7 @@ describe("MarketplaceView", () => { setFollowupAutoApproveTimeoutMs: vi.fn(), profileThresholds: {}, setProfileThresholds: vi.fn(), - checkpointTimeout: 15, + checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, // ... other required context properties } }) @@ -87,7 +88,7 @@ describe("MarketplaceView", () => { mockExtensionState = { ...mockExtensionState, organizationSettingsVersion: 2, - checkpointTimeout: 15, + checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, } // Re-render with updated context diff --git a/webview-ui/src/components/settings/CheckpointSettings.tsx b/webview-ui/src/components/settings/CheckpointSettings.tsx index 2f9ee78e9e..d992eb0313 100644 --- a/webview-ui/src/components/settings/CheckpointSettings.tsx +++ b/webview-ui/src/components/settings/CheckpointSettings.tsx @@ -9,6 +9,11 @@ import { Slider } from "@/components/ui" import { SetCachedStateField } from "./types" import { SectionHeader } from "./SectionHeader" import { Section } from "./Section" +import { + DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, + MAX_CHECKPOINT_TIMEOUT_SECONDS, + MIN_CHECKPOINT_TIMEOUT_SECONDS, +} from "@roo-code/types" type CheckpointSettingsProps = HTMLAttributes & { enableCheckpoints?: boolean @@ -59,19 +64,19 @@ export const CheckpointSettings = ({
{ - if (value >= 10 && value <= 60) { - setCachedStateField("checkpointTimeout", value) - } + setCachedStateField("checkpointTimeout", value) }} className="flex-1" data-testid="checkpoint-timeout-slider" /> - {checkpointTimeout ?? 15} + + {checkpointTimeout ?? DEFAULT_CHECKPOINT_TIMEOUT_SECONDS} +
{t("settings:checkpoints.timeout.description")} diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index 4cdabdb121..f3f04553d6 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -10,6 +10,7 @@ import { type TelemetrySetting, type OrganizationAllowList, ORGANIZATION_ALLOW_ALL, + DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, } from "@roo-code/types" import { ExtensionMessage, ExtensionState, MarketplaceInstalledMetadata, Command } from "@roo/ExtensionMessage" @@ -196,7 +197,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode ttsSpeed: 1.0, diffEnabled: false, enableCheckpoints: true, - checkpointTimeout: 15, // Default to 15 seconds + checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, // Default to 15 seconds fuzzyMatchThreshold: 1.0, language: "en", // Default language code writeDelayMs: 1000, diff --git a/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx b/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx index efef8bfcd1..92652733dd 100644 --- a/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx +++ b/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx @@ -1,6 +1,6 @@ import { render, screen, act } from "@/utils/test-utils" -import { ProviderSettings, ExperimentId } from "@roo-code/types" +import { ProviderSettings, ExperimentId, DEFAULT_CHECKPOINT_TIMEOUT_SECONDS } from "@roo-code/types" import { ExtensionState } from "@roo/ExtensionMessage" @@ -214,14 +214,14 @@ describe("mergeExtensionState", () => { remoteControlEnabled: false, taskSyncEnabled: false, featureRoomoteControlEnabled: false, - checkpointTimeout: 15, // Add the checkpoint timeout property + checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, // Add the checkpoint timeout property } const prevState: ExtensionState = { ...baseState, apiConfiguration: { modelMaxTokens: 1234, modelMaxThinkingTokens: 123 }, experiments: {} as Record, - checkpointTimeout: 10, + checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS - 5, } const newState: ExtensionState = { @@ -238,7 +238,7 @@ describe("mergeExtensionState", () => { imageGeneration: false, runSlashCommand: false, } as Record, - checkpointTimeout: 20, + checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS + 5, } const result = mergeExtensionState(prevState, newState)