diff --git a/packages/types/src/__tests__/experiment.test.ts b/packages/types/src/__tests__/experiment.test.ts new file mode 100644 index 0000000000..0ef4ed2e02 --- /dev/null +++ b/packages/types/src/__tests__/experiment.test.ts @@ -0,0 +1,19 @@ +import { experimentIds, experimentIdsSchema, experimentsSchema } from "../experiment.js" + +describe("dynamicThinkingEffort experiment", () => { + it("is part of the experiment id enum", () => { + expect(experimentIds).toContain("dynamicThinkingEffort") + expect(experimentIdsSchema.safeParse("dynamicThinkingEffort").success).toBe(true) + }) + + it("parses enabled and disabled states", () => { + expect(experimentsSchema.parse({ dynamicThinkingEffort: true })).toEqual({ dynamicThinkingEffort: true }) + expect(experimentsSchema.parse({ dynamicThinkingEffort: false })).toEqual({ dynamicThinkingEffort: false }) + expect(experimentsSchema.parse({})).toEqual({}) + }) + + it("rejects non-boolean values", () => { + expect(experimentsSchema.safeParse({ dynamicThinkingEffort: "yes" }).success).toBe(false) + expect(experimentIdsSchema.safeParse("dynamic-thinking-effort").success).toBe(false) + }) +}) diff --git a/packages/types/src/experiment.ts b/packages/types/src/experiment.ts index 5d511859b1..f4b3a1c0a8 100644 --- a/packages/types/src/experiment.ts +++ b/packages/types/src/experiment.ts @@ -12,6 +12,7 @@ export const experimentIds = [ "runSlashCommand", "customTools", "parallelToolExecution", + "dynamicThinkingEffort", ] as const export const experimentIdsSchema = z.enum(experimentIds) @@ -28,6 +29,7 @@ export const experimentsSchema = z.object({ runSlashCommand: z.boolean().optional(), customTools: z.boolean().optional(), parallelToolExecution: z.boolean().optional(), + dynamicThinkingEffort: z.boolean().optional(), }) export type Experiments = z.infer diff --git a/scripts/stryker-diff.mjs b/scripts/stryker-diff.mjs index dd64f4e774..a6efa72b54 100644 --- a/scripts/stryker-diff.mjs +++ b/scripts/stryker-diff.mjs @@ -57,8 +57,15 @@ export const PACKAGE_CONFIGS = [ root: "src", sourceRoot: "src/", vitestConfig: "vitest.config.ts", - vitestRelated: false, - discoverRelatedTests: true, + + // Use plugin-side related-test discovery: with an explicit STRYKER_TEST_FILES + // list, stryker-js 10.0.0 plans static mutants with runtime activation + // (stryker-mutator/stryker-js#6144, #6209), which the vitest plugin can only + // apply after top-level code has run, producing false Survived results. + // Revert to vitestRelated: false / discoverRelatedTests: true once the + // upstream planner fix lands. + vitestRelated: true, + discoverRelatedTests: false, // CI build/coverage tooling under src/scripts is excluded like the other build scripts: // it is not shipped runtime code and is covered by src/scripts/__tests__/merge-lcov.spec.mjs. excludedPaths: [ diff --git a/scripts/stryker-diff.test.mjs b/scripts/stryker-diff.test.mjs index 22284e598d..ef1a55509d 100644 --- a/scripts/stryker-diff.test.mjs +++ b/scripts/stryker-diff.test.mjs @@ -254,8 +254,12 @@ describe("buildManifest", () => { assert.equal(webview.runRoot, ".") assert.equal(webview.discoverRelatedTests, true) assert.equal(webview.vitestRelated, false) - assert.equal(extension.discoverRelatedTests, true) - assert.equal(extension.vitestRelated, false) + + // The extension entry uses plugin-side related discovery while stryker-js 10.0.0 + // plans static mutants with runtime activation when given explicit test files + // (stryker-mutator/stryker-js#6144, #6209); see the entry comment in stryker-diff.mjs. + assert.equal(extension.discoverRelatedTests, false) + assert.equal(extension.vitestRelated, true) const types = manifest.packages.find(({ id }) => id === "types") assert.equal(types.discoverRelatedTests, undefined) assert.equal(types.vitestRelated, undefined) diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index 93543435e2..07ce47f53e 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -2168,6 +2168,38 @@ describe("ClineProvider", () => { expect(state.destructiveCommandGuardEnabled).toBe(false) }) + test("getStateToPostToWebview returns the saved dynamicThinkingEffort experiment when enabled", async () => { + await provider.resolveWebviewView(mockWebviewView) + await provider.contextProxy.setValue("experiments", { + ...experimentDefault, + dynamicThinkingEffort: true, + }) + + const state = await provider.getStateToPostToWebview() + + expect(state.experiments).toEqual({ ...experimentDefault, dynamicThinkingEffort: true }) + }) + + test("getStateToPostToWebview returns the saved dynamicThinkingEffort experiment when explicitly disabled", async () => { + await provider.resolveWebviewView(mockWebviewView) + await provider.contextProxy.setValue("experiments", { + ...experimentDefault, + dynamicThinkingEffort: false, + }) + + const state = await provider.getStateToPostToWebview() + + expect(state.experiments).toEqual({ ...experimentDefault, dynamicThinkingEffort: false }) + }) + + test("getStateToPostToWebview defaults dynamicThinkingEffort to false when experiments are unset", async () => { + await provider.resolveWebviewView(mockWebviewView) + + const state = await provider.getStateToPostToWebview() + + expect(state.experiments).toEqual({ ...experimentDefault, dynamicThinkingEffort: false }) + }) + test("getStateToPostToWebview returns the saved blanket auto-deny setting", async () => { await provider.resolveWebviewView(mockWebviewView) await provider.contextProxy.setValue("alwaysDenyUnapprovedCommands", true) diff --git a/src/core/webview/__tests__/webviewMessageHandler.spec.ts b/src/core/webview/__tests__/webviewMessageHandler.spec.ts index d5c72de742..b96ef7fd4d 100644 --- a/src/core/webview/__tests__/webviewMessageHandler.spec.ts +++ b/src/core/webview/__tests__/webviewMessageHandler.spec.ts @@ -84,6 +84,7 @@ import * as copilotProvider from "../../../api/providers/github-copilot" import { webviewMessageHandler } from "../webviewMessageHandler" import { registerCopilotModelBroadcast } from "../../../services/language-models/copilotModelBroadcast" import type { ClineProvider } from "../ClineProvider" +import { experimentDefault } from "../../../shared/experiments" import { flushModels, getModels } from "../../../api/providers/fetchers/modelCache" import { getLMStudioModels } from "../../../api/providers/fetchers/lmstudio" import { getCommands } from "../../../services/command/commands" @@ -2971,6 +2972,60 @@ describe("webviewMessageHandler - telemetrySetting", () => { }) }) +describe("webviewMessageHandler - experiments", () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it("persists dynamicThinkingEffort true merged with the saved experiments", async () => { + vi.mocked(mockClineProvider.contextProxy.getValue).mockImplementation((key: string) => + key === "experiments" ? { preventFocusDisruption: true } : undefined, + ) + + await webviewMessageHandler(mockClineProvider, { + type: "updateSettings", + updatedSettings: { experiments: { dynamicThinkingEffort: true } }, + }) + + expect(mockClineProvider.contextProxy.setValue).toHaveBeenCalledWith("experiments", { + preventFocusDisruption: true, + dynamicThinkingEffort: true, + }) + expect(mockClineProvider.postStateToWebview).toHaveBeenCalledTimes(1) + }) + + it("persists dynamicThinkingEffort false over a previously enabled value", async () => { + vi.mocked(mockClineProvider.contextProxy.getValue).mockImplementation((key: string) => + key === "experiments" ? { dynamicThinkingEffort: true } : undefined, + ) + + await webviewMessageHandler(mockClineProvider, { + type: "updateSettings", + updatedSettings: { experiments: { dynamicThinkingEffort: false } }, + }) + + expect(mockClineProvider.contextProxy.setValue).toHaveBeenCalledWith("experiments", { + dynamicThinkingEffort: false, + }) + expect(mockClineProvider.postStateToWebview).toHaveBeenCalledTimes(1) + }) + + it("persists the experiment defaults when no experiments are saved yet", async () => { + vi.mocked(mockClineProvider.contextProxy.getValue).mockReturnValue(undefined) + + await webviewMessageHandler(mockClineProvider, { + type: "updateSettings", + updatedSettings: { experiments: {} }, + }) + + expect(mockClineProvider.contextProxy.setValue).toHaveBeenCalledWith("experiments", { + ...experimentDefault, + dynamicThinkingEffort: false, + }) + expect(mockClineProvider.postStateToWebview).toHaveBeenCalledTimes(1) + }) +}) + describe("webviewMessageHandler - collapseCommandOutputByDefault", () => { beforeEach(() => { vi.clearAllMocks() diff --git a/src/shared/__tests__/experiments.spec.ts b/src/shared/__tests__/experiments.spec.ts index f2261a5c09..b6e8993df4 100644 --- a/src/shared/__tests__/experiments.spec.ts +++ b/src/shared/__tests__/experiments.spec.ts @@ -2,7 +2,7 @@ import type { ExperimentId } from "@roo-code/types" -import { EXPERIMENT_IDS, experimentConfigsMap, experiments as Experiments } from "../experiments" +import { EXPERIMENT_IDS, experimentConfigsMap, experimentDefault, experiments as Experiments } from "../experiments" describe("experiments", () => { describe("PREVENT_FOCUS_DISRUPTION", () => { @@ -22,6 +22,7 @@ describe("experiments", () => { runSlashCommand: false, customTools: false, parallelToolExecution: false, + dynamicThinkingEffort: false, } expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION)).toBe(false) }) @@ -33,6 +34,7 @@ describe("experiments", () => { runSlashCommand: false, customTools: false, parallelToolExecution: false, + dynamicThinkingEffort: false, } expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION)).toBe(true) }) @@ -44,6 +46,7 @@ describe("experiments", () => { runSlashCommand: false, customTools: false, parallelToolExecution: false, + dynamicThinkingEffort: false, } expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION)).toBe(false) }) @@ -66,4 +69,28 @@ describe("experiments", () => { expect(Experiments.isEnabled({ parallelToolExecution: true }, "parallelToolExecution")).toBe(true) }) }) + + describe("DYNAMIC_THINKING_EFFORT", () => { + it("is configured correctly", () => { + expect(EXPERIMENT_IDS.DYNAMIC_THINKING_EFFORT).toBe("dynamicThinkingEffort") + expect(experimentConfigsMap.DYNAMIC_THINKING_EFFORT).toMatchObject({ + enabled: false, + }) + // Visible in the Settings panel (showInSettings defaults to true). + expect(experimentConfigsMap.DYNAMIC_THINKING_EFFORT.showInSettings).toBeUndefined() + }) + + it("is disabled by default", () => { + expect(experimentDefault.dynamicThinkingEffort).toBe(false) + expect(Experiments.isEnabled({}, "dynamicThinkingEffort")).toBe(false) + }) + + it("returns true when enabled", () => { + expect(Experiments.isEnabled({ dynamicThinkingEffort: true }, "dynamicThinkingEffort")).toBe(true) + }) + + it("returns false when explicitly disabled", () => { + expect(Experiments.isEnabled({ dynamicThinkingEffort: false }, "dynamicThinkingEffort")).toBe(false) + }) + }) }) diff --git a/src/shared/experiments.ts b/src/shared/experiments.ts index ae538b9138..c0d461a454 100644 --- a/src/shared/experiments.ts +++ b/src/shared/experiments.ts @@ -6,6 +6,7 @@ export const EXPERIMENT_IDS = { RUN_SLASH_COMMAND: "runSlashCommand", CUSTOM_TOOLS: "customTools", PARALLEL_TOOL_EXECUTION: "parallelToolExecution", + DYNAMIC_THINKING_EFFORT: "dynamicThinkingEffort", } as const satisfies Record type _AssertExperimentIds = AssertEqual>> @@ -25,6 +26,7 @@ export const experimentConfigsMap: Record = { CUSTOM_TOOLS: { enabled: false }, // TODO: add i18n keys (settings:experimental.PARALLEL_TOOL_EXECUTION.name/.description) in the same PR that sets showInSettings: true PARALLEL_TOOL_EXECUTION: { enabled: false, showInSettings: false }, + DYNAMIC_THINKING_EFFORT: { enabled: false }, } export const experimentDefault = Object.fromEntries( diff --git a/webview-ui/playwright/gallery/stories.tsx b/webview-ui/playwright/gallery/stories.tsx index 08d680678a..b72f06a830 100644 --- a/webview-ui/playwright/gallery/stories.tsx +++ b/webview-ui/playwright/gallery/stories.tsx @@ -377,6 +377,11 @@ export const stories: Record = { const { UISettingsStory } = await import("@/components/settings/__tests__/UISettings.visual.fixture") return }, + "experimental-settings": async () => { + const { ExperimentalSettingsStory } = + await import("@/components/settings/__tests__/ExperimentalSettings.visual.fixture") + return + }, "ui-settings-long-locale": async () => { const [{ UISettingsStory }, { default: i18next }] = await Promise.all([ import("@/components/settings/__tests__/UISettings.visual.fixture"), diff --git a/webview-ui/src/components/settings/__tests__/ExperimentalSettings.spec.tsx b/webview-ui/src/components/settings/__tests__/ExperimentalSettings.spec.tsx index b31f87dc7e..3feddad1d4 100644 --- a/webview-ui/src/components/settings/__tests__/ExperimentalSettings.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/ExperimentalSettings.spec.tsx @@ -1,4 +1,4 @@ -import { render, screen } from "@testing-library/react" +import { fireEvent, render, screen } from "@testing-library/react" import { experimentDefault } from "@roo/experiments" @@ -32,4 +32,78 @@ describe("ExperimentalSettings", () => { expect(screen.getByText("settings:experimental.CUSTOM_TOOLS.name")).toBeInTheDocument() expect(screen.queryByText("settings:experimental.PARALLEL_TOOL_EXECUTION.name")).not.toBeInTheDocument() }) + + it("renders the dynamic thinking effort toggle", () => { + render() + + expect(screen.getByText("settings:experimental.DYNAMIC_THINKING_EFFORT.name")).toBeInTheDocument() + }) + + it("leaves the dynamic thinking effort toggle unchecked when the value is false or omitted", () => { + const getCheckbox = () => { + const label = screen.getByText("settings:experimental.DYNAMIC_THINKING_EFFORT.name").closest("label") + return label?.querySelector("input[type='checkbox']") + } + + // Explicit false + let result = render( + , + ) + expect(getCheckbox()).not.toBeNull() + expect(getCheckbox()).not.toBeChecked() + result.unmount() + + // Omitted (absent from the persisted config) + const omitted: Record = { ...experimentDefault } + delete omitted.dynamicThinkingEffort + result = render() + expect(getCheckbox()).not.toBeNull() + expect(getCheckbox()).not.toBeChecked() + result.unmount() + }) + + it("binds the dynamic thinking effort toggle to setExperimentEnabled", () => { + const setExperimentEnabled = vi.fn() + render( + , + ) + + const label = screen.getByText("settings:experimental.DYNAMIC_THINKING_EFFORT.name").closest("label") + const checkbox = label?.querySelector("input[type='checkbox']") + expect(checkbox).not.toBeNull() + expect(checkbox).toBeChecked() + + fireEvent.click(checkbox!) + + expect(setExperimentEnabled).toHaveBeenCalledTimes(1) + expect(setExperimentEnabled).toHaveBeenCalledWith("dynamicThinkingEffort", false) + }) + + it("toggles the dynamic thinking effort on when clicked from the unchecked state", () => { + const setExperimentEnabled = vi.fn() + render( + , + ) + + const label = screen.getByText("settings:experimental.DYNAMIC_THINKING_EFFORT.name").closest("label") + const checkbox = label?.querySelector("input[type='checkbox']") + expect(checkbox).not.toBeNull() + expect(checkbox).not.toBeChecked() + + fireEvent.click(checkbox!) + + expect(setExperimentEnabled).toHaveBeenCalledTimes(1) + expect(setExperimentEnabled).toHaveBeenCalledWith("dynamicThinkingEffort", true) + }) }) diff --git a/webview-ui/src/components/settings/__tests__/ExperimentalSettings.visual.fixture.tsx b/webview-ui/src/components/settings/__tests__/ExperimentalSettings.visual.fixture.tsx new file mode 100644 index 0000000000..f28038aa6d --- /dev/null +++ b/webview-ui/src/components/settings/__tests__/ExperimentalSettings.visual.fixture.tsx @@ -0,0 +1,28 @@ +import { useState } from "react" + +import type { Experiments } from "@roo-code/types" + +import { EXPERIMENT_IDS, experimentDefault } from "@roo/experiments" + +import { ExperimentalSettings } from "../ExperimentalSettings" +import { AppProviders } from "../../../../playwright/AppProviders" + +export function ExperimentalSettingsStory() { + const [experiments, setExperiments] = useState({ + ...experimentDefault, + [EXPERIMENT_IDS.DYNAMIC_THINKING_EFFORT]: true, + }) + + return ( + +
+ setExperiments((current) => ({ ...current, [id]: enabled }))} + /> +
+
+ ) +} diff --git a/webview-ui/src/components/settings/__tests__/ExperimentalSettings.visual.tsx b/webview-ui/src/components/settings/__tests__/ExperimentalSettings.visual.tsx new file mode 100644 index 0000000000..8a12ebf3ae --- /dev/null +++ b/webview-ui/src/components/settings/__tests__/ExperimentalSettings.visual.tsx @@ -0,0 +1,12 @@ +import { expect, test } from "../../../../playwright/coverage-fixture" +import { mountedStory } from "../../../../playwright/mounted-story" +import { applyVisualTheme, visualThemes } from "../../../../playwright/themes" + +for (const theme of visualThemes) { + test(`renders the experimental settings section in the VS Code ${theme.name} theme`, async ({ mount, page }) => { + const component = mountedStory(await mount("experimental-settings")) + await applyVisualTheme(page, theme) + const story = component.getByTestId("experimental-settings-story") + await expect(story).toHaveScreenshot(`experimental-settings-${theme.name}.png`) + }) +} diff --git a/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx b/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx index 0835f255f9..63e0bbc843 100644 --- a/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx @@ -5,6 +5,7 @@ import { act } from "@testing-library/react" import { vscode } from "@/utils/vscode" import { DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, type ProviderSettings } from "@roo-code/types" +import { experimentDefault } from "@roo/experiments" import type { ApiOptionsProps } from "../ApiOptions" import SettingsView from "../SettingsView" @@ -873,6 +874,53 @@ describe("SettingsView - Duplicate Commands", () => { }) }) +describe("SettingsView - Experimental Settings", () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it("includes the dynamic thinking effort toggle in the updateSettings payload on save", () => { + const { activateTab, getSettingsContent } = renderSettingsView({ experiments: experimentDefault }) + activateTab("experimental") + const content = getSettingsContent() + const label = within(content).getByText("settings:experimental.DYNAMIC_THINKING_EFFORT.name").closest("label")! + const checkbox = within(label).getByRole("checkbox") + expect(checkbox).not.toBeChecked() + fireEvent.click(checkbox) + fireEvent.click(screen.getByTestId("save-button")) + expect(vscode.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ + type: "updateSettings", + updatedSettings: expect.objectContaining({ + experiments: expect.objectContaining({ dynamicThinkingEffort: true }), + }), + }), + ) + }) + + it("persists the unset representation of dynamicThinkingEffort as false on save", () => { + const experiments: Record = { ...experimentDefault } + delete experiments.dynamicThinkingEffort + const { activateTab, getSettingsContent } = renderSettingsView({ experiments }) + activateTab("experimental") + const content = getSettingsContent() + const label = within(content).getByText("settings:experimental.DYNAMIC_THINKING_EFFORT.name").closest("label")! + const checkbox = within(label).getByRole("checkbox") + expect(checkbox).not.toBeChecked() + fireEvent.click(checkbox) + fireEvent.click(checkbox) + fireEvent.click(screen.getByTestId("save-button")) + expect(vscode.postMessage).toHaveBeenCalledWith( + expect.objectContaining({ + type: "updateSettings", + updatedSettings: expect.objectContaining({ + experiments: expect.objectContaining({ dynamicThinkingEffort: false }), + }), + }), + ) + }) +}) + describe("SettingsView - Blanket Auto-Deny", () => { beforeEach(() => { vi.clearAllMocks() diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-dark.png b/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-dark.png new file mode 100644 index 0000000000..f7b15dc14b Binary files /dev/null and b/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-dark.png differ diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-high-contrast-light.png b/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-high-contrast-light.png new file mode 100644 index 0000000000..4f1b090fdf Binary files /dev/null and b/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-high-contrast-light.png differ diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-high-contrast.png b/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-high-contrast.png new file mode 100644 index 0000000000..348dab9629 Binary files /dev/null and b/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-high-contrast.png differ diff --git a/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-light.png b/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-light.png new file mode 100644 index 0000000000..a148e2c5d9 Binary files /dev/null and b/webview-ui/src/components/settings/__tests__/__screenshots__/experimental-settings-light.png differ diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index d39d8edd6a..bc89e2c3e1 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Eines actualitzades correctament", "refreshError": "Error en actualitzar les eines", "toolParameters": "Paràmetres" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Esforç de pensament dinàmic", + "description": "Prepara l'eina set_thinking_effort per a un suport posterior: aquest paràmetre només desa la preferència i el comportament per sol·licitud arribarà en una feina posterior. El control manual al xat sempre està disponible. (experimental)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 983db1df5d..af5dbfc4d9 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Tools erfolgreich aktualisiert", "refreshError": "Fehler beim Aktualisieren der Tools", "toolParameters": "Parameter" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Dynamische Denkintensität", + "description": "Bereitet das set_thinking_effort-Tool für spätere Unterstützung vor: Diese Einstellung speichert nur die Präferenz, das Verhalten pro Anfrage folgt in späterer Arbeit. Die manuelle Anpassung im Chat ist immer verfügbar. (experimentell)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index ea924ce79e..af89b8ea1d 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -1090,6 +1090,10 @@ "refreshSuccess": "Tools refreshed successfully", "refreshError": "Failed to refresh tools", "toolParameters": "Parameters" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Dynamic thinking effort", + "description": "Prepares the set_thinking_effort tool for later support: this setting stores the preference only, and the tool's per-request behavior arrives in follow-up work. The manual in-chat control is always available. (experimental)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index 57612bf3e5..af8172823e 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Herramientas actualizadas correctamente", "refreshError": "Error al actualizar las herramientas", "toolParameters": "Parámetros" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Esfuerzo de pensamiento dinámico", + "description": "Prepara la herramienta set_thinking_effort para un soporte posterior: esta opción solo guarda la preferencia y el comportamiento por solicitud llegará en trabajo posterior. El control manual en el chat siempre está disponible. (experimental)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index a91a5137d3..2385f110a1 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Outils actualisés avec succès", "refreshError": "Échec de l'actualisation des outils", "toolParameters": "Paramètres" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Effort de réflexion dynamique", + "description": "Prépare l'outil set_thinking_effort pour une prise en charge ultérieure : ce réglage ne stocke que la préférence, le comportement par requête arrivera dans un travail ultérieur. Le contrôle manuel dans le chat reste toujours disponible. (expérimental)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index bc6e973623..977abe5fb7 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "टूल्स सफलतापूर्वक रिफ्रेश हुए", "refreshError": "टूल्स रिफ्रेश करने में विफल", "toolParameters": "पैरामीटर्स" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "डायनामिक चिंतन प्रयास", + "description": "set_thinking_effort टूल को बाद के समर्थन के लिए तैयार करता है: यह सेटिंग केवल प्राथमिकता सहेजती है, प्रति-अनुरोध व्यवहार आगे के काम में आएगा। चैट में मैन्युअल नियंत्रण हमेशा उपलब्ध है। (प्रयोगात्मक)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index 3ed57f373e..b2cf07e4a0 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Tool berhasil direfresh", "refreshError": "Gagal merefresh tool", "toolParameters": "Parameter" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Usaha berpikir dinamis", + "description": "Menyiapkan alat set_thinking_effort untuk dukungan berikutnya: pengaturan ini hanya menyimpan preferensi, perilaku per permintaan akan datang pada pekerjaan lanjutan. Kontrol manual di obrolan selalu tersedia. (eksperimental)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index b708304e63..1b9a94f81b 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Strumenti aggiornati con successo", "refreshError": "Impossibile aggiornare gli strumenti", "toolParameters": "Parametri" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Sforzo di pensiero dinamico", + "description": "Prepara lo strumento set_thinking_effort per un supporto successivo: questa impostazione salva solo la preferenza, il comportamento per richiesta arriverà in un lavoro successivo. Il controllo manuale nella chat è sempre disponibile. (sperimentale)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index f6959b50dc..03232d9d06 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "ツールが正常に更新されました", "refreshError": "ツールの更新に失敗しました", "toolParameters": "パラメーター" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "ダイナミック思考強度", + "description": "set_thinking_effort ツールを将来のサポートに備えて準備します。この設定は選好を保存するだけで、リクエストごとの動作は後続の作業で提供されます。チャット内での手動調整は常に利用可能です。(実験的機能)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 6cadbd8a3b..f616f7d008 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "도구가 성공적으로 새로고침되었습니다", "refreshError": "도구 새로고침에 실패했습니다", "toolParameters": "매개변수" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "동적 사고 노력", + "description": "set_thinking_effort 도구를 이후 지원을 위해 준비합니다. 이 설정은 선호도만 저장하며, 요청별 동작은 후속 작업에서 제공됩니다. 채팅에서 수동 조정은 항상 사용 가능합니다. (실험적 기능)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 992e9c53e0..fa908960b7 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Tools succesvol vernieuwd", "refreshError": "Fout bij vernieuwen van tools", "toolParameters": "Parameters" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Dynamisch denkwerk", + "description": "Bereidt het set_thinking_effort-gereedschap voor op latere ondersteuning: deze instelling slaat alleen de voorkeur op, het gedrag per verzoek volgt in later werk. De handmatige aanpassing in het gesprek blijft altijd beschikbaar. (experimenteel)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 459675b0e1..4b0e9ba619 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Narzędzia odświeżone pomyślnie", "refreshError": "Nie udało się odświeżyć narzędzi", "toolParameters": "Parametry" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Dynamiczny wysiłek myślowy", + "description": "Przygotowuje narzędzie set_thinking_effort do późniejszego wsparcia: to ustawienie zapisuje tylko preferencję, zachowanie na żądanie pojawi się w kolejnych pracach. Ręczna regulacja w czacie jest zawsze dostępna. (eksperymentalne)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 500babaaa8..19d954131d 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Ferramentas atualizadas com sucesso", "refreshError": "Falha ao atualizar ferramentas", "toolParameters": "Parâmetros" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Esforço de pensamento dinâmico", + "description": "Prepara a ferramenta set_thinking_effort para suporte posterior: esta configuração apenas salva a preferência, o comportamento por solicitação chegará em trabalho futuro. O controle manual na conversa está sempre disponível. (experimental)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 053ff0684d..a212e02378 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Инструменты успешно обновлены", "refreshError": "Не удалось обновить инструменты", "toolParameters": "Параметры" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Динамическое усилие размышления", + "description": "Подготавливает инструмент set_thinking_effort к последующей поддержке: этот параметр сохраняет только предпочтение, поведение для каждого запроса появится в дальнейшей работе. Ручное управление в чате всегда доступно. (экспериментально)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index b37f28d44d..c93edff53b 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Araçlar başarıyla yenilendi", "refreshError": "Araçlar yenilenemedi", "toolParameters": "Parametreler" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Dinamik düşünme çabası", + "description": "set_thinking_effort aracını sonraki destek için hazırlar: bu ayar yalnızca tercihi saklar, istek başına davranış sonraki çalışmada gelir. Sohbetteki manuel kontrol her zaman kullanılabilir. (deneysel)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 94843217ae..93637944b3 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "Làm mới công cụ thành công", "refreshError": "Không thể làm mới công cụ", "toolParameters": "Thông số" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "Nỗ lực suy nghĩ động", + "description": "Chuẩn bị công cụ set_thinking_effort cho hỗ trợ sau này: cài đặt này chỉ lưu tùy chọn, hành vi theo từng yêu cầu sẽ đến trong công việc tiếp theo. Điều chỉnh thủ công trong trò chuyện luôn khả dụng. (thử nghiệm)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 8be0fe1532..51c489dbd6 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -1010,6 +1010,10 @@ "refreshSuccess": "工具刷新成功", "refreshError": "工具刷新失败", "toolParameters": "参数" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "动态思考强度", + "description": "为后续支持准备 set_thinking_effort 工具:此设置仅保存偏好,按请求的工具行为将在后续工作中提供。对话中的手动调整随时可用。(实验性功能)" } }, "promptCaching": { diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 65eb5c67a5..39a1e962ee 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -1037,6 +1037,10 @@ "refreshSuccess": "工具重新整理成功", "refreshError": "工具重新整理失敗", "toolParameters": "參數" + }, + "DYNAMIC_THINKING_EFFORT": { + "name": "動態思考強度", + "description": "為後續支援準備 set_thinking_effort 工具:此設定僅儲存偏好,逐次請求的工具行為會在後續工作中提供。對話中的手動調整隨時可用。(實驗性)" } }, "promptCaching": {