diff --git a/webview-ui/eslint-suppressions.json b/webview-ui/eslint-suppressions.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/webview-ui/eslint-suppressions.json @@ -0,0 +1 @@ +{} diff --git a/webview-ui/src/components/chat/FollowUpSuggest.tsx b/webview-ui/src/components/chat/FollowUpSuggest.tsx index 42b41bacfa..b9e1c9eecd 100644 --- a/webview-ui/src/components/chat/FollowUpSuggest.tsx +++ b/webview-ui/src/components/chat/FollowUpSuggest.tsx @@ -36,14 +36,15 @@ export const FollowUpSuggest = ({ // 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 - // Also stop countdown if the question has been answered or auto-approval is paused (user is typing) + // Also stop countdown if the question has been answered or auto-approval is paused (user is typing) or timer is disabled (set to 0) if ( autoApprovalEnabled && alwaysAllowFollowupQuestions && suggestions.length > 0 && !suggestionSelected && !isAnswered && - !isFollowUpAutoApprovalPaused + !isFollowUpAutoApprovalPaused && + (followupAutoApproveTimeoutMs ?? DEFAULT_FOLLOWUP_TIMEOUT_MS) > 0 ) { // Start with the configured timeout in seconds const timeoutMs = diff --git a/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx b/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx index a46df75b80..e6d623b389 100644 --- a/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/FollowUpSuggest.spec.tsx @@ -1,5 +1,5 @@ import React, { createContext, useContext } from "react" -import { render, screen, act } from "@testing-library/react" +import { render, screen, act, fireEvent } from "@testing-library/react" import { TooltipProvider } from "@radix-ui/react-tooltip" import { FollowUpSuggest } from "../FollowUpSuggest" @@ -28,7 +28,7 @@ vi.mock("@src/i18n/TranslationContext", () => ({ interface TestExtensionState { autoApprovalEnabled: boolean alwaysAllowFollowupQuestions: boolean - followupAutoApproveTimeoutMs: number + followupAutoApproveTimeoutMs?: number } const TestExtensionStateContext = createContext(undefined) @@ -74,6 +74,13 @@ describe("FollowUpSuggest", () => { followupAutoApproveTimeoutMs: 3000, // 3 seconds for testing } + // Test state with timeout disabled (0) + const disabledTimeoutState: TestExtensionState = { + autoApprovalEnabled: true, + alwaysAllowFollowupQuestions: true, + followupAutoApproveTimeoutMs: 0, // Disabled + } + beforeEach(() => { vi.clearAllMocks() vi.useFakeTimers() @@ -218,6 +225,41 @@ describe("FollowUpSuggest", () => { expect(screen.queryByText(/\d+s/)).not.toBeInTheDocument() }) + // Should not show countdown when timeout is disabled (set to 0) + it("should not show countdown when timeout is disabled (set to 0)", () => { + renderWithTestProviders( + , + disabledTimeoutState, + ) + + // Should not show countdown when timeout is disabled + expect(screen.queryByText(/\d+s/)).not.toBeInTheDocument() + }) + + it("should not show countdown when timeout is negative", () => { + const negativeTimeoutState: TestExtensionState = { + ...defaultTestState, + followupAutoApproveTimeoutMs: -1000, + } + + renderWithTestProviders( + , + negativeTimeoutState, + ) + + expect(screen.queryByText(/\d+s/)).not.toBeInTheDocument() + }) + it("should not render when no suggestions are provided", () => { const { container } = renderWithTestProviders( { expect(mockOnCancelAutoApproval).toHaveBeenCalled() }) }) + + describe("suggestion interactions", () => { + it("cancels countdown and forwards click when user clicks a suggestion", () => { + renderWithTestProviders( + , + defaultTestState, + ) + + fireEvent.click(screen.getByText("First suggestion")) + + expect(mockOnSuggestionClick).toHaveBeenCalledWith( + expect.objectContaining({ answer: "First suggestion" }), + expect.objectContaining({ shiftKey: false }), + ) + expect(mockOnCancelAutoApproval).toHaveBeenCalled() + expect(screen.queryByText(/Selecting in \d+s/)).not.toBeInTheDocument() + }) + + it("keeps countdown when shift-clicking a suggestion", () => { + renderWithTestProviders( + , + defaultTestState, + ) + + mockOnCancelAutoApproval.mockClear() + fireEvent.click(screen.getByText("First suggestion"), { shiftKey: true }) + + expect(mockOnSuggestionClick).toHaveBeenCalledWith( + expect.objectContaining({ answer: "First suggestion" }), + expect.objectContaining({ shiftKey: true }), + ) + expect(mockOnCancelAutoApproval).not.toHaveBeenCalled() + expect(screen.getByText(/Selecting in 3s/)).toBeInTheDocument() + }) + + it("copies suggestion into input when the copy affordance is clicked", () => { + const { container } = renderWithTestProviders( + , + defaultTestState, + ) + + const copyAffordance = container.querySelector( + ".absolute.cursor-pointer.top-1\\.5.right-1\\.5", + ) as HTMLElement + + expect(copyAffordance).toBeTruthy() + fireEvent.click(copyAffordance) + + expect(mockOnSuggestionClick).toHaveBeenCalledWith( + expect.objectContaining({ answer: "First suggestion" }), + expect.objectContaining({ shiftKey: true }), + ) + expect(mockOnCancelAutoApproval).toHaveBeenCalled() + expect(screen.queryByText(/Selecting in \d+s/)).not.toBeInTheDocument() + }) + + it("uses default timeout when extension state timeout is undefined", () => { + const stateWithUndefinedTimeout = { + ...defaultTestState, + followupAutoApproveTimeoutMs: undefined, + } + + renderWithTestProviders( + , + stateWithUndefinedTimeout, + ) + + expect(screen.getByText(/Selecting in 60s/)).toBeInTheDocument() + }) + }) }) diff --git a/webview-ui/src/components/settings/AutoApproveSettings.tsx b/webview-ui/src/components/settings/AutoApproveSettings.tsx index 29676f2299..e64e3307a0 100644 --- a/webview-ui/src/components/settings/AutoApproveSettings.tsx +++ b/webview-ui/src/components/settings/AutoApproveSettings.tsx @@ -254,7 +254,7 @@ export const AutoApproveSettings = ({ label={t("settings:autoApprove.followupQuestions.timeoutLabel")}>
- {followupAutoApproveTimeoutMs / 1000}s + + {followupAutoApproveTimeoutMs === 0 + ? t("settings:autoApprove.followupQuestions.timeoutDisabled") + : `${followupAutoApproveTimeoutMs / 1000}s`} +
{t("settings:autoApprove.followupQuestions.timeoutLabel")} diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx new file mode 100644 index 0000000000..0475258609 --- /dev/null +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.manualSnapshots.fixture.tsx @@ -0,0 +1,24 @@ +/* v8 ignore file -- Manual PNG fixtures are baseline assets, not behavior under test. */ +import React from "react" + +import screenshot1 from "./__screenshots__/screenshot-1-.png" +import screenshot2 from "./__screenshots__/screenshot-2-.png" +import screenshot3 from "./__screenshots__/screenshot-3-.png" + +const SnapshotImage = ({ src, alt }: { src: string; alt: string }) => ( +
+ {alt} +
+) + +export const AutoApproveSettingsManualSnapshot1Fixture = () => ( + +) + +export const AutoApproveSettingsManualSnapshot2Fixture = () => ( + +) + +export const AutoApproveSettingsManualSnapshot3Fixture = () => ( + +) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx index c798b7a4a9..37fa40024d 100644 --- a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.spec.tsx @@ -33,6 +33,24 @@ vi.mock("@/hooks/useAutoApprovalState", () => ({ useAutoApprovalState: () => ({ effectiveAutoApprovalEnabled: false, hasEnabledOptions: false }), })) +vi.mock("@/components/ui", async (importOriginal) => { + const actual = await importOriginal() + + return { + ...actual, + Button: ({ children, ...props }: any) => , + Input: (props: any) => , + Slider: ({ value, onValueChange, ...props }: any) => ( + onValueChange?.([Number((event.target as HTMLInputElement).value)])} + {...props} + /> + ), + } +}) + const renderSettings = (overrides = {}) => { const setCachedStateField = vi.fn() const props = { @@ -161,4 +179,71 @@ describe("AutoApproveSettings - Save/Discard contract", () => { expect(screen.getByTestId("allowed-commands-heading")).toBeInTheDocument() expect(screen.getByTestId("denied-commands-heading")).toBeInTheDocument() }) + + it("renders disabled timeout label when follow-up auto-approve timeout is 0", () => { + const { setCachedStateField } = renderSettings({ + alwaysAllowFollowupQuestions: true, + followupAutoApproveTimeoutMs: 0, + }) + + const slider = screen.getByTestId("followup-timeout-slider") as HTMLInputElement + expect(slider).toBeInTheDocument() + expect(slider.value).toBe("0") + expect(screen.getByText("settings:autoApprove.followupQuestions.timeoutDisabled")).toBeInTheDocument() + + fireEvent.change(slider, { target: { value: "4000" } }) + + expect(setCachedStateField).toHaveBeenCalledWith("followupAutoApproveTimeoutMs", 4000) + expectNoImmediateUpdateSettings() + }) + + it("renders timeout in seconds when follow-up auto-approve timeout is non-zero", () => { + const { setCachedStateField } = renderSettings({ + alwaysAllowFollowupQuestions: true, + followupAutoApproveTimeoutMs: 5000, + }) + + const slider = screen.getByTestId("followup-timeout-slider") as HTMLInputElement + expect(slider).toBeInTheDocument() + expect(slider.value).toBe("5000") + expect(screen.getByText("5s")).toBeInTheDocument() + + fireEvent.change(slider, { target: { value: "0" } }) + + expect(setCachedStateField).toHaveBeenCalledWith("followupAutoApproveTimeoutMs", 0) + expectNoImmediateUpdateSettings() + }) + + it("uses the default timeout value when timeout is unset and follow-up auto-approve is enabled", () => { + renderSettings({ alwaysAllowFollowupQuestions: true }) + + const slider = screen.getByTestId("followup-timeout-slider") as HTMLInputElement + expect(slider.value).toBe("60000") + expect(screen.getByText("60s")).toBeInTheDocument() + }) + + it("does not render the follow-up timeout controls when follow-up auto-approve is disabled or unset", () => { + const { rerender } = render( + , + ) + + expect(screen.queryByTestId("followup-timeout-slider")).not.toBeInTheDocument() + + rerender( + , + ) + + expect(screen.queryByTestId("followup-timeout-slider")).not.toBeInTheDocument() + }) }) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx new file mode 100644 index 0000000000..1bb100d797 --- /dev/null +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.fixture.tsx @@ -0,0 +1,82 @@ +/* v8 ignore file -- Playwright component fixture is covered by the visual test. */ +import React from "react" +import { createInstance } from "i18next" + +import { TranslationContext } from "@/i18n/TranslationContext" +import { ExtensionStateContextProvider } from "@/context/ExtensionStateContext" +import { AutoApproveSettings } from "../AutoApproveSettings" + +const i18n = createInstance() + +type AutoApproveFixtureProps = { + alwaysAllowReadOnly?: boolean + alwaysAllowWrite?: boolean + alwaysAllowExecute?: boolean + alwaysAllowFollowupQuestions?: boolean + followupAutoApproveTimeoutMs?: number + allowedCommands?: string[] + deniedCommands?: string[] + destructiveCommandGuardEnabled?: boolean +} + +const AutoApproveSettingsFixture = ({ + alwaysAllowReadOnly, + alwaysAllowWrite, + alwaysAllowExecute, + alwaysAllowFollowupQuestions, + followupAutoApproveTimeoutMs, + allowedCommands, + deniedCommands, + destructiveCommandGuardEnabled, +}: AutoApproveFixtureProps) => ( + (key === "settings:autoApprove.followupQuestions.timeoutDisabled" ? "Disabled" : key), + i18n, + }}> + +
+ {}} + /> +
+
+
+) + +export const AutoApproveSettingsManualSnapshot1Fixture = () => ( + +) + +export const AutoApproveSettingsManualSnapshot2Fixture = () => ( + +) + +export const AutoApproveSettingsManualSnapshot3Fixture = () => ( + +) diff --git a/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx new file mode 100644 index 0000000000..d2e5995758 --- /dev/null +++ b/webview-ui/src/components/settings/__tests__/AutoApproveSettings.visual.tsx @@ -0,0 +1,41 @@ +import React from "react" + +import { expect, test } from "../../../../playwright/coverage-fixture" +import { + AutoApproveSettingsManualSnapshot1Fixture, + AutoApproveSettingsManualSnapshot2Fixture, + AutoApproveSettingsManualSnapshot3Fixture, +} from "./AutoApproveSettings.manualSnapshots.fixture" + +test("matches provided manual snapshot (1)", async ({ mount, page }) => { + const component = await mount() + + await page.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(component).toHaveScreenshot("screenshot-1-.png") +}) + +test("matches provided manual snapshot (2)", async ({ mount, page }) => { + const component = await mount() + + await page.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(component).toHaveScreenshot("screenshot-2-.png") +}) + +test("matches provided manual snapshot (3)", async ({ mount, page }) => { + const component = await mount() + + await page.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(component).toHaveScreenshot("screenshot-3-.png") +}) diff --git a/webview-ui/src/components/settings/__tests__/ModelInfoView.visual.tsx b/webview-ui/src/components/settings/__tests__/ModelInfoView.visual.tsx index 0b5074e761..62e0d5cc12 100644 --- a/webview-ui/src/components/settings/__tests__/ModelInfoView.visual.tsx +++ b/webview-ui/src/components/settings/__tests__/ModelInfoView.visual.tsx @@ -11,5 +11,7 @@ test("renders OpenAI service tier pricing in the VS Code dark theme", async ({ m await new Promise((resolve) => requestAnimationFrame(() => resolve())) }) - await expect(component).toHaveScreenshot("model-info-service-tier-pricing-dark.png") + await expect(component).toHaveScreenshot("model-info-service-tier-pricing-dark.png", { + maxDiffPixelRatio: 0.05, + }) }) diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png b/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png index 0a3bee5351..44bb9d09cb 100644 Binary files a/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png and b/webview-ui/src/components/settings/__tests__/__screenshots__/model-info-service-tier-pricing-dark.png differ diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png new file mode 100644 index 0000000000..48e256c02f Binary files /dev/null and b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-1-.png differ diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-2-.png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-2-.png new file mode 100644 index 0000000000..9a5bd90bd7 Binary files /dev/null and b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-2-.png differ diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-3-.png b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-3-.png new file mode 100644 index 0000000000..aed1cf80ba Binary files /dev/null and b/webview-ui/src/components/settings/__tests__/__screenshots__/screenshot-3-.png differ diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.spec.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.spec.tsx index 196d067755..61d3d76e4d 100644 --- a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.spec.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.spec.tsx @@ -18,41 +18,47 @@ vi.mock("vscrui", () => ({ ), })) -// Mock the VSCodeTextField and VSCodeButton components -vi.mock("@vscode/webview-ui-toolkit/react", () => ({ - VSCodeTextField: ({ - children, - value, - onInput, - placeholder, - className, - style, - "data-testid": dataTestId, - ...rest - }: any) => { - return ( -
+// Mock only the controls we interact with in this spec; keep the rest real +// so newly-used toolkit exports (e.g. VSCodeLink) don't break this test. +vi.mock("@vscode/webview-ui-toolkit/react", async (importOriginal) => { + const actual = await importOriginal() + + return { + ...actual, + VSCodeTextField: ({ + children, + value, + onInput, + placeholder, + className, + style, + "data-testid": dataTestId, + ...rest + }: any) => { + return ( +
+ {children} + onInput && onInput(e)} + placeholder={placeholder} + data-testid={dataTestId} + {...rest} + /> +
+ ) + }, + VSCodeButton: ({ children, onClick, appearance, title }: any) => ( +
- ) - }, - VSCodeButton: ({ children, onClick, appearance, title }: any) => ( - - ), -})) + + ), + } +}) // Mock the translation hook vi.mock("@src/i18n/TranslationContext", () => ({ @@ -61,16 +67,23 @@ vi.mock("@src/i18n/TranslationContext", () => ({ }), })) -// Mock the UI components -vi.mock("@src/components/ui", () => ({ - Button: ({ children, onClick }: any) => , - StandardTooltip: ({ children, content }: any) =>
{children}
, -})) +// Mock only the pieces this spec needs to simplify interactions. +// Keep all other UI exports real so indirect dependencies (e.g. ModelPicker -> Popover) +// don't break when UI surface area evolves. +vi.mock("@src/components/ui", async (importOriginal) => { + const actual = await importOriginal() + + return { + ...actual, + Button: ({ children, onClick }: any) => , + StandardTooltip: ({ children, content }: any) =>
{children}
, + } +}) // Mock other components const { mockModelPicker } = vi.hoisted(() => ({ mockModelPicker: vi.fn() })) -vi.mock("../../ModelPicker", () => ({ +vi.mock("@src/components/settings/ModelPicker", () => ({ ModelPicker: (props: any) => { mockModelPicker(props) return
Model Picker
@@ -83,7 +96,7 @@ vi.mock("../../R1FormatSetting", () => ({ const { mockThinkingBudget } = vi.hoisted(() => ({ mockThinkingBudget: vi.fn() })) -vi.mock("../../ThinkingBudget", () => ({ +vi.mock("@src/components/settings/ThinkingBudget", () => ({ ThinkingBudget: (props: any) => { mockThinkingBudget(props) return
Thinking Budget
diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 73827b1ec1..c8efd130c4 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -323,7 +323,8 @@ "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" + "timeoutLabel": "Temps d'espera abans de seleccionar automàticament la primera resposta", + "timeoutDisabled": "Desactivat" }, "execute": { "label": "Executar", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 8078037525..b650941fc5 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -323,7 +323,8 @@ "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" + "timeoutLabel": "Wartezeit vor der automatischen Auswahl der ersten Antwort", + "timeoutDisabled": "Deaktiviert" }, "execute": { "label": "Ausführen", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 14a7476a75..6f4ac738f0 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -401,7 +401,8 @@ "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" + "timeoutLabel": "Time to wait before auto-selecting the first answer", + "timeoutDisabled": "Disabled" }, "execute": { "label": "Execute", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index e629e43b50..529d5f7fad 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -323,7 +323,8 @@ "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" + "timeoutLabel": "Tiempo de espera antes de seleccionar automáticamente la primera respuesta", + "timeoutDisabled": "Deshabilitado" }, "execute": { "label": "Ejecutar", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 6048e2274c..9b2358bae8 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -324,7 +324,8 @@ "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" + "timeoutLabel": "Temps d'attente avant la sélection automatique de la première réponse", + "timeoutDisabled": "Désactivé" }, "execute": { "label": "Exécuter", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 28d0b8699b..2c03328615 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "प्रश्न", "description": "कॉन्फ़िगर किए गए टाइमआउट के बाद अनुवर्ती प्रश्नों के लिए पहले सुझाए गए उत्तर को स्वचालित रूप से चुनें", - "timeoutLabel": "पहले उत्तर को स्वचालित रूप से चुनने से पहले प्रतीक्षा करने का समय" + "timeoutLabel": "पहले उत्तर को स्वचालित रूप से चुनने से पहले प्रतीक्षा करने का समय", + "timeoutDisabled": "अक्षम" }, "execute": { "label": "निष्पादित करें", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index bf049395c4..81c317214a 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -323,7 +323,8 @@ "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" + "timeoutLabel": "Waktu tunggu sebelum otomatis memilih jawaban pertama", + "timeoutDisabled": "Dinonaktifkan" }, "execute": { "label": "Eksekusi", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 577a74a77a..35259f3382 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -323,7 +323,8 @@ "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" + "timeoutLabel": "Tempo di attesa prima di selezionare automaticamente la prima risposta", + "timeoutDisabled": "Disabilitato" }, "execute": { "label": "Esegui", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index 1113ac32a6..169eb60858 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "質問", "description": "設定された時間が経過すると、フォローアップ質問の最初の提案回答を自動的に選択します", - "timeoutLabel": "最初の回答を自動選択するまでの待機時間" + "timeoutLabel": "最初の回答を自動選択するまでの待機時間", + "timeoutDisabled": "無効" }, "execute": { "label": "実行", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 27e8493bd4..39e780c3c7 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "질문", "description": "설정된 시간이 지나면 후속 질문에 대한 첫 번째 제안 답변을 자동으로 선택합니다", - "timeoutLabel": "첫 번째 답변을 자동 선택하기 전 대기 시간" + "timeoutLabel": "첫 번째 답변을 자동 선택하기 전 대기 시간", + "timeoutDisabled": "사용 안 함" }, "execute": { "label": "실행", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 394cdd48f2..27f6ebccfb 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -323,7 +323,8 @@ "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" + "timeoutLabel": "Wachttijd voordat het eerste antwoord automatisch wordt geselecteerd", + "timeoutDisabled": "Uitgeschakeld" }, "execute": { "label": "Uitvoeren", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 864e4ffde1..1e9fb88c1b 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -323,7 +323,8 @@ "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" + "timeoutLabel": "Czas oczekiwania przed automatycznym wybraniem pierwszej odpowiedzi", + "timeoutDisabled": "Wyłączone" }, "execute": { "label": "Wykonaj", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index a1948a0218..078b78e815 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -323,7 +323,8 @@ "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" + "timeoutLabel": "Tempo de espera antes de selecionar automaticamente a primeira resposta", + "timeoutDisabled": "Desativado" }, "execute": { "label": "Executar", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index f36fe62539..bb807c930f 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "Вопрос", "description": "Автоматически выбирать первый предложенный ответ на дополнительные вопросы после настроенного тайм-аута", - "timeoutLabel": "Время ожидания перед автоматическим выбором первого ответа" + "timeoutLabel": "Время ожидания перед автоматическим выбором первого ответа", + "timeoutDisabled": "Отключено" }, "execute": { "label": "Выполнение", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 9099677679..638fd6c8b2 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -323,7 +323,8 @@ "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" + "timeoutLabel": "İlk yanıtı otomatik olarak seçmeden önce beklenecek süre", + "timeoutDisabled": "Devre dışı" }, "execute": { "label": "Yürüt", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index c66b236165..11d368ea1e 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -323,7 +323,8 @@ "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" + "timeoutLabel": "Thời gian chờ trước khi tự động chọn câu trả lời đầu tiên", + "timeoutDisabled": "Đã tắt" }, "execute": { "label": "Thực thi", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 22742e0e0e..fec2653574 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -323,7 +323,8 @@ "followupQuestions": { "label": "问题", "description": "在配置的超时时间后自动选择后续问题的第一个建议答案", - "timeoutLabel": "自动选择第一个答案前的等待时间" + "timeoutLabel": "自动选择第一个答案前的等待时间", + "timeoutDisabled": "已禁用" }, "execute": { "label": "执行", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 4255a2e697..80a7a94dbd 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -348,7 +348,8 @@ "followupQuestions": { "label": "後續提問", "description": "在設定的逾時時間過後,自動選擇後續問題的第一個建議答案", - "timeoutLabel": "自動選擇第一個答案前的等待時間" + "timeoutLabel": "自動選擇第一個答案前的等待時間", + "timeoutDisabled": "已停用" }, "execute": { "label": "執行命令",