diff --git a/packages/types/src/followup.ts b/packages/types/src/followup.ts new file mode 100644 index 0000000000..1a5424cd11 --- /dev/null +++ b/packages/types/src/followup.ts @@ -0,0 +1,41 @@ +import { z } from "zod" + +/** + * Interface for follow-up data structure used in follow-up questions + * This represents the data structure for follow-up questions that the LLM can ask + * to gather more information needed to complete a task. + */ +export interface FollowUpData { + /** The question being asked by the LLM */ + question?: string + /** Array of suggested answers that the user can select */ + suggest?: Array +} + +/** + * Interface for a suggestion item with optional mode switching + */ +export interface SuggestionItem { + /** The text of the suggestion */ + answer: string + /** Optional mode to switch to when selecting this suggestion */ + mode?: string +} + +/** + * Zod schema for SuggestionItem + */ +export const suggestionItemSchema = z.object({ + answer: z.string(), + mode: z.string().optional(), +}) + +/** + * Zod schema for FollowUpData + */ +export const followUpDataSchema = z.object({ + question: z.string().optional(), + suggest: z.array(suggestionItemSchema).optional(), +}) + +export type FollowUpDataType = z.infer diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index e713cafa4c..7cd051c6bf 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -45,6 +45,8 @@ export const globalSettingsSchema = z.object({ alwaysAllowModeSwitch: z.boolean().optional(), alwaysAllowSubtasks: z.boolean().optional(), alwaysAllowExecute: z.boolean().optional(), + alwaysAllowFollowupQuestions: z.boolean().optional(), + followupAutoApproveTimeoutMs: z.number().optional(), allowedCommands: z.array(z.string()).optional(), allowedMaxRequests: z.number().nullish(), autoCondenseContext: z.boolean().optional(), @@ -189,6 +191,8 @@ export const EVALS_SETTINGS: RooCodeSettings = { alwaysAllowModeSwitch: true, alwaysAllowSubtasks: true, alwaysAllowExecute: true, + alwaysAllowFollowupQuestions: true, + followupAutoApproveTimeoutMs: 0, allowedCommands: ["*"], browserToolEnabled: false, diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 345bc3e311..6c6db9ccd5 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -4,6 +4,7 @@ export * from "./api.js" export * from "./codebase-index.js" export * from "./cloud.js" export * from "./experiment.js" +export * from "./followup.js" export * from "./global-settings.js" export * from "./history.js" export * from "./ipc.js" diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 51cb9a275b..9d99eea1d4 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1411,6 +1411,8 @@ export class ClineProvider codebaseIndexConfig, codebaseIndexModels, profileThresholds, + alwaysAllowFollowupQuestions, + followupAutoApproveTimeoutMs, } = await this.getState() const telemetryKey = process.env.POSTHOG_API_KEY @@ -1521,6 +1523,8 @@ export class ClineProvider profileThresholds: profileThresholds ?? {}, cloudApiUrl: getRooCodeApiUrl(), hasOpenedModeSelector: this.getGlobalState("hasOpenedModeSelector") ?? false, + alwaysAllowFollowupQuestions: alwaysAllowFollowupQuestions ?? false, + followupAutoApproveTimeoutMs: followupAutoApproveTimeoutMs ?? 60000, } } @@ -1601,6 +1605,8 @@ export class ClineProvider alwaysAllowMcp: stateValues.alwaysAllowMcp ?? false, alwaysAllowModeSwitch: stateValues.alwaysAllowModeSwitch ?? false, alwaysAllowSubtasks: stateValues.alwaysAllowSubtasks ?? false, + alwaysAllowFollowupQuestions: stateValues.alwaysAllowFollowupQuestions ?? false, + followupAutoApproveTimeoutMs: stateValues.followupAutoApproveTimeoutMs ?? 60000, allowedMaxRequests: stateValues.allowedMaxRequests, autoCondenseContext: stateValues.autoCondenseContext ?? true, autoCondenseContextPercent: stateValues.autoCondenseContextPercent ?? 100, diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index cac94aa0ce..af053044b2 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -1100,6 +1100,14 @@ export const webviewMessageHandler = async ( await updateGlobalState("maxWorkspaceFiles", fileCount) await provider.postStateToWebview() break + case "alwaysAllowFollowupQuestions": + await updateGlobalState("alwaysAllowFollowupQuestions", message.bool ?? false) + await provider.postStateToWebview() + break + case "followupAutoApproveTimeoutMs": + await updateGlobalState("followupAutoApproveTimeoutMs", message.value) + await provider.postStateToWebview() + break case "browserToolEnabled": await updateGlobalState("browserToolEnabled", message.bool ?? true) await provider.postStateToWebview() diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index 7efc97e8c7..42718595c3 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -37,6 +37,8 @@ export interface WebviewMessage { | "alwaysAllowWriteOutsideWorkspace" | "alwaysAllowWriteProtected" | "alwaysAllowExecute" + | "alwaysAllowFollowupQuestions" + | "followupAutoApproveTimeoutMs" | "webviewDidLaunch" | "newTask" | "askResponse" diff --git a/webview-ui/src/components/chat/AutoApproveMenu.tsx b/webview-ui/src/components/chat/AutoApproveMenu.tsx index ac02d6b8c4..8d838f0a18 100644 --- a/webview-ui/src/components/chat/AutoApproveMenu.tsx +++ b/webview-ui/src/components/chat/AutoApproveMenu.tsx @@ -25,6 +25,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => { alwaysAllowModeSwitch, alwaysAllowSubtasks, alwaysApproveResubmit, + alwaysAllowFollowupQuestions, allowedMaxRequests, setAlwaysAllowReadOnly, setAlwaysAllowWrite, @@ -34,6 +35,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => { setAlwaysAllowModeSwitch, setAlwaysAllowSubtasks, setAlwaysApproveResubmit, + setAlwaysAllowFollowupQuestions, setAllowedMaxRequests, } = useExtensionState() @@ -68,6 +70,9 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => { case "alwaysApproveResubmit": setAlwaysApproveResubmit(value) break + case "alwaysAllowFollowupQuestions": + setAlwaysAllowFollowupQuestions(value) + break } }, [ @@ -79,6 +84,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => { setAlwaysAllowModeSwitch, setAlwaysAllowSubtasks, setAlwaysApproveResubmit, + setAlwaysAllowFollowupQuestions, ], ) @@ -94,6 +100,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => { alwaysAllowModeSwitch: alwaysAllowModeSwitch, alwaysAllowSubtasks: alwaysAllowSubtasks, alwaysApproveResubmit: alwaysApproveResubmit, + alwaysAllowFollowupQuestions: alwaysAllowFollowupQuestions, }), [ alwaysAllowReadOnly, @@ -104,6 +111,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => { alwaysAllowModeSwitch, alwaysAllowSubtasks, alwaysApproveResubmit, + alwaysAllowFollowupQuestions, ], ) diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index 43824c5902..f61eb8c5e0 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -10,6 +10,7 @@ import type { ClineMessage } from "@roo-code/types" import { ClineApiReqInfo, ClineAskUseMcpServer, ClineSayTool } from "@roo/ExtensionMessage" import { COMMAND_OUTPUT_STRING } from "@roo/combineCommandSequences" import { safeJsonParse } from "@roo/safeJsonParse" +import { FollowUpData, SuggestionItem } from "@roo-code/types" import { useCopyToClipboard } from "@src/utils/clipboard" import { useExtensionState } from "@src/context/ExtensionStateContext" @@ -48,8 +49,9 @@ interface ChatRowProps { isStreaming: boolean onToggleExpand: (ts: number) => void onHeightChange: (isTaller: boolean) => void - onSuggestionClick?: (answer: string, event?: React.MouseEvent) => void + onSuggestionClick?: (suggestion: SuggestionItem, event?: React.MouseEvent) => void onBatchFileResponse?: (response: { [key: string]: boolean }) => void + onFollowUpUnmount?: () => void } // eslint-disable-next-line @typescript-eslint/no-empty-object-type @@ -98,6 +100,7 @@ export const ChatRowContent = ({ isStreaming, onToggleExpand, onSuggestionClick, + onFollowUpUnmount, onBatchFileResponse, }: ChatRowContentProps) => { const { t } = useTranslation() @@ -279,7 +282,7 @@ export const ChatRowContent = ({ const followUpData = useMemo(() => { if (message.type === "ask" && message.ask === "followup" && !message.partial) { - return safeJsonParse(message.text) + return safeJsonParse(message.text) } return null }, [message.type, message.ask, message.partial, message.text]) @@ -1215,6 +1218,7 @@ export const ChatRowContent = ({ suggestions={followUpData?.suggest} onSuggestionClick={onSuggestionClick} ts={message?.ts} + onUnmount={onFollowUpUnmount} /> ) diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index e9c5a17415..5c2e2277fb 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -15,6 +15,7 @@ import type { ClineAsk, ClineMessage } from "@roo-code/types" import { ClineSayBrowserAction, ClineSayTool, ExtensionMessage } from "@roo/ExtensionMessage" import { McpServer, McpTool } from "@roo/mcp" import { findLast } from "@roo/array" +import { FollowUpData, SuggestionItem } from "@roo-code/types" import { combineApiRequests } from "@roo/combineApiRequests" import { combineCommandSequences } from "@roo/combineCommandSequences" import { getApiMetrics } from "@roo/getApiMetrics" @@ -88,11 +89,13 @@ const ChatViewComponent: React.ForwardRefRenderFunction { + // Update local state and notify extension to sync mode change + setMode(modeSlug) + + // Send the mode switch message + vscode.postMessage({ + type: "mode", + text: modeSlug, + }) + }, + [setMode], + ) + const handleSuggestionClickInRow = useCallback( - (answer: string, event?: React.MouseEvent) => { + (suggestion: SuggestionItem, event?: React.MouseEvent) => { + // Check if we need to switch modes + if (suggestion.mode) { + // Only switch modes if it's a manual click (event exists) or auto-approval is allowed + const isManualClick = !!event + if (isManualClick || alwaysAllowModeSwitch) { + // Switch mode without waiting + switchToMode(suggestion.mode) + } + } + if (event?.shiftKey) { // Always append to existing text, don't overwrite setInputValue((currentValue) => { - return currentValue !== "" ? `${currentValue} \n${answer}` : answer + return currentValue !== "" ? `${currentValue} \n${suggestion.answer}` : suggestion.answer }) } else { - handleSendMessage(answer, []) + handleSendMessage(suggestion.answer, []) } }, - [handleSendMessage, setInputValue], // setInputValue is stable, handleSendMessage depends on clineAsk + [handleSendMessage, setInputValue, switchToMode, alwaysAllowModeSwitch], ) const handleBatchFileResponse = useCallback((response: { [key: string]: boolean }) => { @@ -1208,6 +1241,15 @@ const ChatViewComponent: React.ForwardRefRenderFunction { + // Clear the auto-approve timeout to prevent race conditions + if (autoApproveTimeoutRef.current) { + clearTimeout(autoApproveTimeoutRef.current) + autoApproveTimeoutRef.current = null + } + }, []) + const itemContent = useCallback( (index: number, messageOrGroup: ClineMessage | ClineMessage[]) => { // browser session group @@ -1243,6 +1285,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction ) }, @@ -1255,6 +1298,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction { if (lastMessage?.ask && isAutoApproved(lastMessage)) { - if (lastMessage.ask === "tool" && isWriteToolAction(lastMessage)) { + // Special handling for follow-up questions + if (lastMessage.ask === "followup") { + // Handle invalid JSON + let followUpData: FollowUpData = {} + try { + followUpData = JSON.parse(lastMessage.text || "{}") as FollowUpData + } catch (error) { + console.error("Failed to parse follow-up data:", error) + return + } + + if (followUpData && followUpData.suggest && followUpData.suggest.length > 0) { + // Wait for the configured timeout before auto-selecting the first suggestion + await new Promise((resolve) => { + autoApproveTimeoutRef.current = setTimeout(resolve, followupAutoApproveTimeoutMs) + }) + + // Get the first suggestion + const firstSuggestion = followUpData.suggest[0] + + // Handle the suggestion click + handleSuggestionClickInRow(firstSuggestion) + return + } + } else if (lastMessage.ask === "tool" && isWriteToolAction(lastMessage)) { await new Promise((resolve) => { autoApproveTimeoutRef.current = setTimeout(resolve, writeDelayMs) }) } - if (autoApproveTimeoutRef.current === null || autoApproveTimeoutRef.current) { - vscode.postMessage({ type: "askResponse", askResponse: "yesButtonClicked" }) + vscode.postMessage({ type: "askResponse", askResponse: "yesButtonClicked" }) - setSendingDisabled(true) - setClineAsk(undefined) - setEnableButtons(false) - } + setSendingDisabled(true) + setClineAsk(undefined) + setEnableButtons(false) } } autoApprove() @@ -1303,6 +1369,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction m.slug === mode) const nextModeIndex = (currentModeIndex + 1) % allModes.length // Update local state and notify extension to sync mode change - setMode(allModes[nextModeIndex].slug) - vscode.postMessage({ - type: "mode", - text: allModes[nextModeIndex].slug, - }) - }, [mode, setMode, customModes]) + switchToMode(allModes[nextModeIndex].slug) + }, [mode, customModes, switchToMode]) // Add keyboard event handler const handleKeyDown = useCallback( diff --git a/webview-ui/src/components/chat/FollowUpSuggest.tsx b/webview-ui/src/components/chat/FollowUpSuggest.tsx index 6e1ec58814..5649da744a 100644 --- a/webview-ui/src/components/chat/FollowUpSuggest.tsx +++ b/webview-ui/src/components/chat/FollowUpSuggest.tsx @@ -1,40 +1,85 @@ -import { useCallback } from "react" +import { useCallback, useEffect, useState } from "react" import { Edit } from "lucide-react" import { Button, StandardTooltip } from "@/components/ui" -import { vscode } from "@/utils/vscode" import { useAppTranslation } from "@src/i18n/TranslationContext" +import { useExtensionState } from "@src/context/ExtensionStateContext" +import { SuggestionItem } from "@roo-code/types" -interface SuggestionItem { - answer: string - mode?: string -} +const DEFAULT_FOLLOWUP_TIMEOUT_MS = 60000 +const COUNTDOWN_INTERVAL_MS = 1000 interface FollowUpSuggestProps { - suggestions?: (string | SuggestionItem)[] - onSuggestionClick?: (answer: string, event?: React.MouseEvent) => void + suggestions?: SuggestionItem[] + onSuggestionClick?: (suggestion: SuggestionItem, event?: React.MouseEvent) => void ts: number + onUnmount?: () => void } -export const FollowUpSuggest = ({ suggestions = [], onSuggestionClick, ts = 1 }: FollowUpSuggestProps) => { +export const FollowUpSuggest = ({ suggestions = [], onSuggestionClick, ts = 1, onUnmount }: FollowUpSuggestProps) => { + const { autoApprovalEnabled, alwaysAllowFollowupQuestions, followupAutoApproveTimeoutMs } = useExtensionState() + const [countdown, setCountdown] = useState(null) + const [suggestionSelected, setSuggestionSelected] = useState(false) const { t } = useAppTranslation() - const handleSuggestionClick = useCallback( - (suggestion: string | SuggestionItem, event: React.MouseEvent) => { - const suggestionText = typeof suggestion === "string" ? suggestion : suggestion.answer - const mode = typeof suggestion === "object" ? suggestion.mode : undefined - // If there's a mode switch and it's not a shift-click (which just copies to input), switch modes first - if (mode && !event.shiftKey) { - vscode.postMessage({ - type: "mode", - text: mode, + // Start countdown timer when auto-approval is enabled for follow-up questions + useEffect(() => { + // Only start countdown if auto-approval is enabled for follow-up questions and no suggestion has been selected + if (autoApprovalEnabled && alwaysAllowFollowupQuestions && suggestions.length > 0 && !suggestionSelected) { + // Start with the configured timeout in seconds + const timeoutMs = + typeof followupAutoApproveTimeoutMs === "number" && !isNaN(followupAutoApproveTimeoutMs) + ? followupAutoApproveTimeoutMs + : DEFAULT_FOLLOWUP_TIMEOUT_MS + + // Convert milliseconds to seconds for the countdown + setCountdown(Math.floor(timeoutMs / 1000)) + + // Update countdown every second + const intervalId = setInterval(() => { + setCountdown((prevCountdown) => { + if (prevCountdown === null || prevCountdown <= 1) { + clearInterval(intervalId) + return null + } + return prevCountdown - 1 }) + }, COUNTDOWN_INTERVAL_MS) + + // Clean up interval on unmount and notify parent component + return () => { + clearInterval(intervalId) + // Notify parent component that this component is unmounting + // so it can clear any related timeouts + onUnmount?.() + } + } else { + setCountdown(null) + } + }, [ + autoApprovalEnabled, + alwaysAllowFollowupQuestions, + suggestions, + followupAutoApproveTimeoutMs, + suggestionSelected, + onUnmount, + ]) + const handleSuggestionClick = useCallback( + (suggestion: SuggestionItem, event: React.MouseEvent) => { + // Mark a suggestion as selected if it's not a shift-click (which just copies to input) + if (!event.shiftKey) { + setSuggestionSelected(true) + // Also notify parent component to cancel auto-approval timeout + // This prevents race conditions between visual countdown and actual timeout + onUnmount?.() } - onSuggestionClick?.(suggestionText, event) + // Pass the suggestion object to the parent component + // The parent component will handle mode switching if needed + onSuggestionClick?.(suggestion, event) }, - [onSuggestionClick], + [onSuggestionClick, onUnmount], ) // Don't render if there are no suggestions or no click handler. @@ -44,23 +89,29 @@ export const FollowUpSuggest = ({ suggestions = [], onSuggestionClick, ts = 1 }: return (
- {suggestions.map((suggestion) => { - const suggestionText = typeof suggestion === "string" ? suggestion : suggestion.answer - const mode = typeof suggestion === "object" ? suggestion.mode : undefined + {suggestions.map((suggestion, index) => { + const isFirstSuggestion = index === 0 return ( -
+
- {mode && ( + {suggestion.mode && (
- {mode} + {suggestion.mode}
)} @@ -69,7 +120,7 @@ export const FollowUpSuggest = ({ suggestions = [], onSuggestionClick, ts = 1 }: onClick={(e) => { e.stopPropagation() // Simulate shift-click by directly calling the handler with shiftKey=true. - onSuggestionClick?.(suggestionText, { ...e, shiftKey: true }) + onSuggestionClick?.(suggestion, { ...e, shiftKey: true }) }}>
)} + {alwaysAllowFollowupQuestions && ( +
+
+ +
{t("settings:autoApprove.followupQuestions.label")}
+
+
+
+ + setCachedStateField("followupAutoApproveTimeoutMs", value) + } + data-testid="followup-timeout-slider" + /> + {followupAutoApproveTimeoutMs / 1000}s +
+
+ {t("settings:autoApprove.followupQuestions.timeoutLabel")} +
+
+
+ )} + {alwaysAllowExecute && (
diff --git a/webview-ui/src/components/settings/AutoApproveToggle.tsx b/webview-ui/src/components/settings/AutoApproveToggle.tsx index d2b6694f75..6c82d3c984 100644 --- a/webview-ui/src/components/settings/AutoApproveToggle.tsx +++ b/webview-ui/src/components/settings/AutoApproveToggle.tsx @@ -14,6 +14,7 @@ type AutoApproveToggles = Pick< | "alwaysAllowModeSwitch" | "alwaysAllowSubtasks" | "alwaysAllowExecute" + | "alwaysAllowFollowupQuestions" > export type AutoApproveSetting = keyof AutoApproveToggles @@ -83,6 +84,13 @@ export const autoApproveSettingsConfig: Record {Object.values(autoApproveSettingsConfig).map(({ key, descriptionKey, labelKey, icon, testId }) => ( diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index 8712b81cf2..c3b9179e37 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -174,6 +174,8 @@ const SettingsView = forwardRef(({ onDone, t codebaseIndexModels, customSupportPrompts, profileThresholds, + alwaysAllowFollowupQuestions, + followupAutoApproveTimeoutMs, } = cachedState const apiConfiguration = useMemo(() => cachedState.apiConfiguration ?? {}, [cachedState.apiConfiguration]) @@ -311,6 +313,8 @@ const SettingsView = forwardRef(({ onDone, t vscode.postMessage({ type: "updateExperimental", values: experiments }) vscode.postMessage({ type: "alwaysAllowModeSwitch", bool: alwaysAllowModeSwitch }) vscode.postMessage({ type: "alwaysAllowSubtasks", bool: alwaysAllowSubtasks }) + vscode.postMessage({ type: "alwaysAllowFollowupQuestions", bool: alwaysAllowFollowupQuestions }) + vscode.postMessage({ type: "followupAutoApproveTimeoutMs", value: followupAutoApproveTimeoutMs }) vscode.postMessage({ type: "condensingApiConfigId", text: condensingApiConfigId || "" }) vscode.postMessage({ type: "updateCondensingPrompt", text: customCondensingPrompt || "" }) vscode.postMessage({ type: "updateSupportPrompt", values: customSupportPrompts || {} }) @@ -599,6 +603,8 @@ const SettingsView = forwardRef(({ onDone, t alwaysAllowModeSwitch={alwaysAllowModeSwitch} alwaysAllowSubtasks={alwaysAllowSubtasks} alwaysAllowExecute={alwaysAllowExecute} + alwaysAllowFollowupQuestions={alwaysAllowFollowupQuestions} + followupAutoApproveTimeoutMs={followupAutoApproveTimeoutMs} allowedCommands={allowedCommands} setCachedStateField={setCachedStateField} /> diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveToggle.spec.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveToggle.spec.tsx index 97e5dcc96b..ac8c054f65 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveToggle.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveToggle.spec.tsx @@ -25,6 +25,7 @@ describe("AutoApproveToggle", () => { alwaysAllowModeSwitch: true, alwaysAllowSubtasks: false, alwaysAllowExecute: true, + alwaysAllowFollowupQuestions: false, onToggle: mockOnToggle, } diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index c87ccdb6e9..ea3c6208d7 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -40,6 +40,10 @@ export interface ExtensionStateContextType extends ExtensionState { mdmCompliant?: boolean hasOpenedModeSelector: boolean // New property to track if user has opened mode selector setHasOpenedModeSelector: (value: boolean) => void // Setter for the new property + alwaysAllowFollowupQuestions: boolean // New property for follow-up questions auto-approve + setAlwaysAllowFollowupQuestions: (value: boolean) => void // Setter for the new property + followupAutoApproveTimeoutMs: number | undefined // Timeout in ms for auto-approving follow-up questions + setFollowupAutoApproveTimeoutMs: (value: number) => void // Setter for the timeout condensingApiConfigId?: string setCondensingApiConfigId: (value: string) => void customCondensingPrompt?: string @@ -226,6 +230,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode const [currentCheckpoint, setCurrentCheckpoint] = useState() const [extensionRouterModels, setExtensionRouterModels] = useState(undefined) const [marketplaceItems, setMarketplaceItems] = useState([]) + const [alwaysAllowFollowupQuestions, setAlwaysAllowFollowupQuestions] = useState(false) // Add state for follow-up questions auto-approve + const [followupAutoApproveTimeoutMs, setFollowupAutoApproveTimeoutMs] = useState(undefined) // Will be set from global settings const [marketplaceInstalledMetadata, setMarketplaceInstalledMetadata] = useState({ project: {}, global: {}, @@ -255,6 +261,14 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setState((prevState) => mergeExtensionState(prevState, newState)) setShowWelcome(!checkExistKey(newState.apiConfiguration)) setDidHydrateState(true) + // Update alwaysAllowFollowupQuestions if present in state message + if ((newState as any).alwaysAllowFollowupQuestions !== undefined) { + setAlwaysAllowFollowupQuestions((newState as any).alwaysAllowFollowupQuestions) + } + // Update followupAutoApproveTimeoutMs if present in state message + if ((newState as any).followupAutoApproveTimeoutMs !== undefined) { + setFollowupAutoApproveTimeoutMs((newState as any).followupAutoApproveTimeoutMs) + } // Handle marketplace data if present in state message if (newState.marketplaceItems !== undefined) { setMarketplaceItems(newState.marketplaceItems) @@ -352,6 +366,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode marketplaceItems, marketplaceInstalledMetadata, profileThresholds: state.profileThresholds ?? {}, + alwaysAllowFollowupQuestions, + followupAutoApproveTimeoutMs, setExperimentEnabled: (id, enabled) => setState((prevState) => ({ ...prevState, experiments: { ...prevState.experiments, [id]: enabled } })), setApiConfiguration, @@ -367,6 +383,9 @@ 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 })), + setAlwaysAllowFollowupQuestions, + setFollowupAutoApproveTimeoutMs: (value) => + setState((prevState) => ({ ...prevState, followupAutoApproveTimeoutMs: value })), setShowAnnouncement: (value) => setState((prevState) => ({ ...prevState, shouldShowAnnouncement: value })), setAllowedCommands: (value) => setState((prevState) => ({ ...prevState, allowedCommands: value })), setAllowedMaxRequests: (value) => setState((prevState) => ({ ...prevState, allowedMaxRequests: value })), diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index 07f1e25b53..74f3c5b972 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -234,7 +234,9 @@ "tokens": "tokens" }, "followUpSuggest": { - "copyToInput": "Copiar a l'entrada (o Shift + clic)" + "copyToInput": "Copiar a l'entrada (o Shift + clic)", + "autoSelectCountdown": "Selecció automàtica en {{count}}s", + "countdownDisplay": "{{count}}s" }, "announcement": { "title": "🎉 Roo Code {{version}} publicat", diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index ea4f974149..e5c14126fb 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -110,6 +110,11 @@ "label": "Subtasques", "description": "Permetre la creació i finalització de subtasques sense requerir aprovació" }, + "followupQuestions": { + "label": "Pregunta", + "description": "Seleccionar automàticament la primera resposta suggerida per a preguntes de seguiment després del temps d'espera configurat", + "timeoutLabel": "Temps d'espera abans de seleccionar automàticament la primera resposta" + }, "execute": { "label": "Executar", "description": "Executar automàticament comandes de terminal permeses sense requerir aprovació", diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index b5c2336e46..c944ff1afd 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -234,7 +234,9 @@ "tokens": "Tokens" }, "followUpSuggest": { - "copyToInput": "In Eingabefeld kopieren (oder Shift + Klick)" + "copyToInput": "In Eingabefeld kopieren (oder Shift + Klick)", + "autoSelectCountdown": "Automatische Auswahl in {{count}}s", + "countdownDisplay": "{{count}}s" }, "announcement": { "title": "🎉 Roo Code {{version}} veröffentlicht", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index c5e161bafe..3e473770bf 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -110,6 +110,11 @@ "label": "Teilaufgaben", "description": "Erstellung und Abschluss von Unteraufgaben ohne Genehmigung erlauben" }, + "followupQuestions": { + "label": "Frage", + "description": "Automatisch die erste vorgeschlagene Antwort für Folgefragen nach der konfigurierten Zeitüberschreitung auswählen", + "timeoutLabel": "Wartezeit vor der automatischen Auswahl der ersten Antwort" + }, "execute": { "label": "Ausführen", "description": "Erlaubte Terminal-Befehle automatisch ohne Genehmigung ausführen", diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index 3e5c2bfc60..838a4b4e52 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -257,7 +257,9 @@ "seconds": "{{count}}s" }, "followUpSuggest": { - "copyToInput": "Copy to input (same as shift + click)" + "copyToInput": "Copy to input (same as shift + click)", + "autoSelectCountdown": "Auto-selecting in {{count}}s", + "countdownDisplay": "{{count}}s" }, "browser": { "rooWantsToUse": "Roo wants to use the browser:", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 14981ea499..f60f0487a6 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -110,6 +110,11 @@ "label": "Subtasks", "description": "Allow creation and completion of subtasks without requiring approval" }, + "followupQuestions": { + "label": "Question", + "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" + }, "execute": { "label": "Execute", "description": "Automatically execute allowed terminal commands without requiring approval", diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index db90a70057..269f9a12f7 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -234,7 +234,9 @@ "tokens": "tokens" }, "followUpSuggest": { - "copyToInput": "Copiar a la entrada (o Shift + clic)" + "copyToInput": "Copiar a la entrada (o Shift + clic)", + "autoSelectCountdown": "Selección automática en {{count}}s", + "countdownDisplay": "{{count}}s" }, "announcement": { "title": "🎉 Roo Code {{version}} publicado", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index 3e3d20cce1..3354dd1c78 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -110,6 +110,11 @@ "label": "Subtareas", "description": "Permitir la creación y finalización de subtareas sin requerir aprobación" }, + "followupQuestions": { + "label": "Pregunta", + "description": "Seleccionar automáticamente la primera respuesta sugerida para preguntas de seguimiento después del tiempo de espera configurado", + "timeoutLabel": "Tiempo de espera antes de seleccionar automáticamente la primera respuesta" + }, "execute": { "label": "Ejecutar", "description": "Ejecutar automáticamente comandos de terminal permitidos sin requerir aprobación", diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index b0d20bc7b2..3eaf0692f9 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -234,7 +234,9 @@ "tokens": "tokens" }, "followUpSuggest": { - "copyToInput": "Copier vers l'entrée (ou Shift + clic)" + "copyToInput": "Copier vers l'entrée (ou Shift + clic)", + "autoSelectCountdown": "Sélection automatique dans {{count}}s", + "countdownDisplay": "{{count}}s" }, "announcement": { "title": "🎉 Roo Code {{version}} est sortie", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 5635251876..da0cda88d3 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -110,6 +110,11 @@ "label": "Sous-tâches", "description": "Permettre la création et l'achèvement des sous-tâches sans nécessiter d'approbation" }, + "followupQuestions": { + "label": "Question", + "description": "Sélectionner automatiquement la première réponse suggérée pour les questions de suivi après le délai configuré", + "timeoutLabel": "Temps d'attente avant la sélection automatique de la première réponse" + }, "execute": { "label": "Exécuter", "description": "Exécuter automatiquement les commandes de terminal autorisées sans nécessiter d'approbation", diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 24e2af1eb7..2f99ab36a3 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -234,7 +234,9 @@ "tokens": "टोकन" }, "followUpSuggest": { - "copyToInput": "इनपुट में कॉपी करें (या Shift + क्लिक)" + "copyToInput": "इनपुट में कॉपी करें (या Shift + क्लिक)", + "autoSelectCountdown": "{{count}}s में स्वचालित रूप से चयन हो रहा है", + "countdownDisplay": "{{count}}सेकंड" }, "announcement": { "title": "🎉 Roo Code {{version}} रिलीज़ हुआ", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 8de5bd1a19..197498aab1 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -110,6 +110,11 @@ "label": "उप-कार्य", "description": "अनुमोदन की आवश्यकता के बिना उप-कार्यों के निर्माण और पूर्णता की अनुमति दें" }, + "followupQuestions": { + "label": "प्रश्न", + "description": "कॉन्फ़िगर किए गए टाइमआउट के बाद अनुवर्ती प्रश्नों के लिए पहले सुझाए गए उत्तर को स्वचालित रूप से चुनें", + "timeoutLabel": "पहले उत्तर को स्वचालित रूप से चुनने से पहले प्रतीक्षा करने का समय" + }, "execute": { "label": "निष्पादित करें", "description": "अनुमोदन की आवश्यकता के बिना स्वचालित रूप से अनुमत टर्मिनल कमांड निष्पादित करें", diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index 0568b58913..0c8ed69279 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -263,7 +263,9 @@ "seconds": "{{count}}d" }, "followUpSuggest": { - "copyToInput": "Salin ke input (sama dengan shift + klik)" + "copyToInput": "Salin ke input (sama dengan shift + klik)", + "autoSelectCountdown": "Pemilihan otomatis dalam {{count}}dtk", + "countdownDisplay": "{{count}}dtk" }, "browser": { "rooWantsToUse": "Roo ingin menggunakan browser:", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index 8def303c05..1b5fa5de5e 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -110,6 +110,11 @@ "label": "Subtugas", "description": "Izinkan pembuatan dan penyelesaian subtugas tanpa memerlukan persetujuan" }, + "followupQuestions": { + "label": "Pertanyaan", + "description": "Secara otomatis memilih jawaban pertama yang disarankan untuk pertanyaan lanjutan setelah batas waktu yang dikonfigurasi", + "timeoutLabel": "Waktu tunggu sebelum otomatis memilih jawaban pertama" + }, "execute": { "label": "Eksekusi", "description": "Secara otomatis mengeksekusi perintah terminal yang diizinkan tanpa memerlukan persetujuan", diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index 1f7d6b463f..fd3680f968 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -234,7 +234,9 @@ "tokens": "token" }, "followUpSuggest": { - "copyToInput": "Copia nell'input (o Shift + clic)" + "copyToInput": "Copia nell'input (o Shift + clic)", + "autoSelectCountdown": "Selezione automatica in {{count}}s", + "countdownDisplay": "{{count}}s" }, "announcement": { "title": "🎉 Rilasciato Roo Code {{version}}", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 572f99cbb0..8dc0c60040 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -110,6 +110,11 @@ "label": "Sottoattività", "description": "Consenti la creazione e il completamento di attività secondarie senza richiedere approvazione" }, + "followupQuestions": { + "label": "Domanda", + "description": "Seleziona automaticamente la prima risposta suggerita per le domande di follow-up dopo il timeout configurato", + "timeoutLabel": "Tempo di attesa prima di selezionare automaticamente la prima risposta" + }, "execute": { "label": "Esegui", "description": "Esegui automaticamente i comandi del terminale consentiti senza richiedere approvazione", diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index 255acb717f..1fe357d973 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -234,7 +234,9 @@ "tokens": "トークン" }, "followUpSuggest": { - "copyToInput": "入力欄にコピー(またはShift + クリック)" + "copyToInput": "入力欄にコピー(またはShift + クリック)", + "autoSelectCountdown": "{{count}}秒後に自動選択します", + "countdownDisplay": "{{count}}秒" }, "announcement": { "title": "🎉 Roo Code {{version}} リリース", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index c6a681e549..dcafa94aeb 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -110,6 +110,11 @@ "label": "サブタスク", "description": "承認なしでサブタスクの作成と完了を許可" }, + "followupQuestions": { + "label": "質問", + "description": "設定された時間が経過すると、フォローアップ質問の最初の提案回答を自動的に選択します", + "timeoutLabel": "最初の回答を自動選択するまでの待機時間" + }, "execute": { "label": "実行", "description": "承認なしで自動的に許可されたターミナルコマンドを実行", diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index b83c400574..5e46b95dee 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -234,7 +234,9 @@ "tokens": "토큰" }, "followUpSuggest": { - "copyToInput": "입력창에 복사 (또는 Shift + 클릭)" + "copyToInput": "입력창에 복사 (또는 Shift + 클릭)", + "autoSelectCountdown": "{{count}}초 후 자동 선택", + "countdownDisplay": "{{count}}초" }, "announcement": { "title": "🎉 Roo Code {{version}} 출시", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 6ae68428bd..a21ce5ea2f 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -110,6 +110,11 @@ "label": "하위 작업", "description": "승인 없이 하위 작업 생성 및 완료 허용" }, + "followupQuestions": { + "label": "질문", + "description": "설정된 시간이 지나면 후속 질문에 대한 첫 번째 제안 답변을 자동으로 선택합니다", + "timeoutLabel": "첫 번째 답변을 자동 선택하기 전 대기 시간" + }, "execute": { "label": "실행", "description": "승인 없이 자동으로 허용된 터미널 명령 실행", diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index 4b6877389d..0863f0e497 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -244,7 +244,9 @@ "tokens": "tokens" }, "followUpSuggest": { - "copyToInput": "Kopiëren naar invoer (zelfde als shift + klik)" + "copyToInput": "Kopiëren naar invoer (zelfde als shift + klik)", + "autoSelectCountdown": "Automatische selectie in {{count}}s", + "countdownDisplay": "{{count}}s" }, "browser": { "rooWantsToUse": "Roo wil de browser gebruiken:", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index c6d1bb7992..dfae50456e 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -110,6 +110,11 @@ "label": "Subtaken", "description": "Subtaken aanmaken en afronden zonder goedkeuring" }, + "followupQuestions": { + "label": "Vraag", + "description": "Selecteer automatisch het eerste voorgestelde antwoord voor vervolgvragen na de geconfigureerde time-out", + "timeoutLabel": "Wachttijd voordat het eerste antwoord automatisch wordt geselecteerd" + }, "execute": { "label": "Uitvoeren", "description": "Automatisch toegestane terminalcommando's uitvoeren zonder goedkeuring", diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index fe1a47156a..df042806bf 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -234,7 +234,9 @@ "tokens": "tokeny" }, "followUpSuggest": { - "copyToInput": "Kopiuj do pola wprowadzania (lub Shift + kliknięcie)" + "copyToInput": "Kopiuj do pola wprowadzania (lub Shift + kliknięcie)", + "autoSelectCountdown": "Automatyczny wybór za {{count}}s", + "countdownDisplay": "{{count}}s" }, "announcement": { "title": "🎉 Roo Code {{version}} wydany", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index b702d7b5a5..a86c832322 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -110,6 +110,11 @@ "label": "Podzadania", "description": "Zezwalaj na tworzenie i ukończenie podzadań bez konieczności zatwierdzania" }, + "followupQuestions": { + "label": "Pytanie", + "description": "Automatycznie wybierz pierwszą sugerowaną odpowiedź na pytania uzupełniające po skonfigurowanym limicie czasu", + "timeoutLabel": "Czas oczekiwania przed automatycznym wybraniem pierwszej odpowiedzi" + }, "execute": { "label": "Wykonaj", "description": "Automatycznie wykonuj dozwolone polecenia terminala bez konieczności zatwierdzania", diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index f8dd3542c0..f77ace0249 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -234,7 +234,9 @@ "tokens": "tokens" }, "followUpSuggest": { - "copyToInput": "Copiar para entrada (ou Shift + clique)" + "copyToInput": "Copiar para entrada (ou Shift + clique)", + "autoSelectCountdown": "Seleção automática em {{count}}s", + "countdownDisplay": "{{count}}s" }, "announcement": { "title": "🎉 Roo Code {{version}} Lançado", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index be7bfe2d0d..9a4ceeb561 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -110,6 +110,11 @@ "label": "Subtarefas", "description": "Permitir a criação e conclusão de subtarefas sem exigir aprovação" }, + "followupQuestions": { + "label": "Pergunta", + "description": "Selecionar automaticamente a primeira resposta sugerida para perguntas de acompanhamento após o tempo limite configurado", + "timeoutLabel": "Tempo de espera antes de selecionar automaticamente a primeira resposta" + }, "execute": { "label": "Executar", "description": "Executar automaticamente comandos de terminal permitidos sem exigir aprovação", diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index b07d8d49f7..4cf6b3937d 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -244,7 +244,9 @@ "tokens": "токены" }, "followUpSuggest": { - "copyToInput": "Скопировать во ввод (то же, что shift + клик)" + "copyToInput": "Скопировать во ввод (то же, что shift + клик)", + "autoSelectCountdown": "Автовыбор через {{count}}с", + "countdownDisplay": "{{count}}с" }, "browser": { "rooWantsToUse": "Roo хочет использовать браузер:", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index b0693f4532..712e7f4e01 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -110,6 +110,11 @@ "label": "Подзадачи", "description": "Разрешить создание и выполнение подзадач без необходимости одобрения" }, + "followupQuestions": { + "label": "Вопрос", + "description": "Автоматически выбирать первый предложенный ответ на дополнительные вопросы после настроенного тайм-аута", + "timeoutLabel": "Время ожидания перед автоматическим выбором первого ответа" + }, "execute": { "label": "Выполнение", "description": "Автоматически выполнять разрешённые команды терминала без необходимости одобрения", diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index f5625842b1..e0a6bdd701 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -234,7 +234,9 @@ "tokens": "token" }, "followUpSuggest": { - "copyToInput": "Giriş alanına kopyala (veya Shift + tıklama)" + "copyToInput": "Giriş alanına kopyala (veya Shift + tıklama)", + "autoSelectCountdown": "{{count}}s içinde otomatik seçilecek", + "countdownDisplay": "{{count}}sn" }, "announcement": { "title": "🎉 Roo Code {{version}} Yayınlandı", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 06bd626406..93c14bd326 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -110,6 +110,11 @@ "label": "Alt Görevler", "description": "Onay gerektirmeden alt görevlerin oluşturulmasına ve tamamlanmasına izin ver" }, + "followupQuestions": { + "label": "Soru", + "description": "Yapılandırılan zaman aşımından sonra takip sorularına ilişkin ilk önerilen yanıtı otomatik olarak seç", + "timeoutLabel": "İlk yanıtı otomatik olarak seçmeden önce beklenecek süre" + }, "execute": { "label": "Yürüt", "description": "Onay gerektirmeden otomatik olarak izin verilen terminal komutlarını yürüt", diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index 05f9ed8a3d..f936bcd56f 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -234,7 +234,9 @@ "tokens": "token" }, "followUpSuggest": { - "copyToInput": "Sao chép vào ô nhập liệu (hoặc Shift + nhấp chuột)" + "copyToInput": "Sao chép vào ô nhập liệu (hoặc Shift + nhấp chuột)", + "autoSelectCountdown": "Tự động chọn sau {{count}}s", + "countdownDisplay": "{{count}}s" }, "announcement": { "title": "🎉 Roo Code {{version}} Đã phát hành", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index c434276b3b..bbfc984261 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -110,6 +110,11 @@ "label": "Công việc phụ", "description": "Cho phép tạo và hoàn thành các công việc phụ mà không cần phê duyệt" }, + "followupQuestions": { + "label": "Câu hỏi", + "description": "Tự động chọn câu trả lời đầu tiên được đề xuất cho các câu hỏi tiếp theo sau thời gian chờ đã cấu hình", + "timeoutLabel": "Thời gian chờ trước khi tự động chọn câu trả lời đầu tiên" + }, "execute": { "label": "Thực thi", "description": "Tự động thực thi các lệnh terminal được phép mà không cần phê duyệt", diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index d85c633699..6b3b40c2d6 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -234,7 +234,9 @@ "tokens": "tokens" }, "followUpSuggest": { - "copyToInput": "复制到输入框(或按住Shift点击)" + "copyToInput": "复制到输入框(或按住Shift点击)", + "autoSelectCountdown": "{{count}}秒后自动选择", + "countdownDisplay": "{{count}}秒" }, "announcement": { "title": "🎉 Roo Code {{version}} 已发布", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 80bcab26eb..999ba44351 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -110,6 +110,11 @@ "label": "子任务", "description": "允许创建和完成子任务而无需批准" }, + "followupQuestions": { + "label": "问题", + "description": "在配置的超时时间后自动选择后续问题的第一个建议答案", + "timeoutLabel": "自动选择第一个答案前的等待时间" + }, "execute": { "label": "执行", "description": "自动执行白名单中的命令而无需批准", diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index b3659f6869..ac7688adde 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -234,7 +234,9 @@ "tokens": "tokens" }, "followUpSuggest": { - "copyToInput": "複製到輸入框(或按住 Shift 並點選)" + "copyToInput": "複製到輸入框(或按住 Shift 並點選)", + "autoSelectCountdown": "{{count}}秒後自動選擇", + "countdownDisplay": "{{count}}秒" }, "announcement": { "title": "🎉 Roo Code {{version}} 已發布", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 033230ebb4..3b3a92991c 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -110,6 +110,11 @@ "label": "子工作", "description": "允許建立和完成子工作而無需核准" }, + "followupQuestions": { + "label": "問題", + "description": "在設定的逾時時間後自動選擇後續問題的第一個建議答案", + "timeoutLabel": "自動選擇第一個答案前的等待時間" + }, "execute": { "label": "執行", "description": "自動執行允許的終端機命令而無需核准",