diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index b4819d9683..99caceffc2 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -89,6 +89,7 @@ type GlobalStateKey = | "lmStudioModelId" | "lmStudioBaseUrl" | "anthropicBaseUrl" + | "anthropicThinking" | "azureApiVersion" | "openAiStreamingEnabled" | "openRouterModelId" @@ -1654,6 +1655,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { lmStudioModelId, lmStudioBaseUrl, anthropicBaseUrl, + anthropicThinking, geminiApiKey, openAiNativeApiKey, deepSeekApiKey, @@ -1701,6 +1703,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { this.updateGlobalState("lmStudioModelId", lmStudioModelId), this.updateGlobalState("lmStudioBaseUrl", lmStudioBaseUrl), this.updateGlobalState("anthropicBaseUrl", anthropicBaseUrl), + this.updateGlobalState("anthropicThinking", anthropicThinking), this.storeSecret("geminiApiKey", geminiApiKey), this.storeSecret("openAiNativeApiKey", openAiNativeApiKey), this.storeSecret("deepSeekApiKey", deepSeekApiKey), @@ -2510,6 +2513,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { lmStudioModelId, lmStudioBaseUrl, anthropicBaseUrl, + anthropicThinking, geminiApiKey, openAiNativeApiKey, deepSeekApiKey, @@ -2592,6 +2596,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { this.getGlobalState("lmStudioModelId") as Promise, this.getGlobalState("lmStudioBaseUrl") as Promise, this.getGlobalState("anthropicBaseUrl") as Promise, + this.getGlobalState("anthropicThinking") as Promise, this.getSecret("geminiApiKey") as Promise, this.getSecret("openAiNativeApiKey") as Promise, this.getSecret("deepSeekApiKey") as Promise, @@ -2691,6 +2696,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { lmStudioModelId, lmStudioBaseUrl, anthropicBaseUrl, + anthropicThinking, geminiApiKey, openAiNativeApiKey, deepSeekApiKey, diff --git a/src/shared/__tests__/checkExistApiConfig.test.ts b/src/shared/__tests__/checkExistApiConfig.test.ts index 914f4933d6..62517d6958 100644 --- a/src/shared/__tests__/checkExistApiConfig.test.ts +++ b/src/shared/__tests__/checkExistApiConfig.test.ts @@ -32,6 +32,7 @@ describe("checkExistKey", () => { apiKey: "test-key", apiProvider: undefined, anthropicBaseUrl: undefined, + anthropicThinking: undefined, } expect(checkExistKey(config)).toBe(true) }) diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index 48529d4852..3761ddce50 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -2,9 +2,10 @@ import { memo, useCallback, useMemo, useState } from "react" import { useDebounce, useEvent } from "react-use" import { Checkbox, Dropdown, Pane, type DropdownOption } from "vscrui" import { VSCodeLink, VSCodeRadio, VSCodeRadioGroup, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" -import { TemperatureControl } from "./TemperatureControl" import * as vscodemodels from "vscode" +import { Slider } from "@/components/ui" + import { ApiConfiguration, ModelInfo, @@ -34,6 +35,7 @@ import { requestyDefaultModelInfo, } from "../../../../src/shared/api" import { ExtensionMessage } from "../../../../src/shared/ExtensionMessage" + import { vscode } from "../../utils/vscode" import VSCodeButtonLink from "../common/VSCodeButtonLink" import { OpenRouterModelPicker } from "./OpenRouterModelPicker" @@ -43,7 +45,7 @@ import { UnboundModelPicker } from "./UnboundModelPicker" import { ModelInfoView } from "./ModelInfoView" import { DROPDOWN_Z_INDEX } from "./styles" import { RequestyModelPicker } from "./RequestyModelPicker" -import { Slider } from "../ui" +import { TemperatureControl } from "./TemperatureControl" interface ApiOptionsProps { uriScheme: string | undefined @@ -66,8 +68,7 @@ const ApiOptions = ({ const [lmStudioModels, setLmStudioModels] = useState([]) const [vsCodeLmModels, setVsCodeLmModels] = useState([]) const [anthropicBaseUrlSelected, setAnthropicBaseUrlSelected] = useState(!!apiConfiguration?.anthropicBaseUrl) - const [anthropicThinkingEnabled, setAnthropicThinkingEnabled] = useState(!!apiConfiguration?.anthropicThinking) - const [anthropicThinkingBudget, setAnthropicThinkingBudget] = useState(apiConfiguration?.anthropicThinking ?? 1024) + const [anthropicThinkingBudget, setAnthropicThinkingBudget] = useState(apiConfiguration?.anthropicThinking) const [azureApiVersionSelected, setAzureApiVersionSelected] = useState(!!apiConfiguration?.azureApiVersion) const [openRouterBaseUrlSelected, setOpenRouterBaseUrlSelected] = useState(!!apiConfiguration?.openRouterBaseUrl) const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false) @@ -188,6 +189,7 @@ const ApiOptions = ({ checked={anthropicBaseUrlSelected} onChange={(checked: boolean) => { setAnthropicBaseUrlSelected(checked) + if (!checked) { setApiConfigurationField("anthropicBaseUrl", "") } @@ -387,6 +389,7 @@ const ApiOptions = ({ checked={openRouterBaseUrlSelected} onChange={(checked: boolean) => { setOpenRouterBaseUrlSelected(checked) + if (!checked) { setApiConfigurationField("openRouterBaseUrl", "") } @@ -510,7 +513,7 @@ const ApiOptions = ({ )} - {apiConfiguration?.apiProvider === "vertex" && ( + {selectedProvider === "vertex" && (
{ setAzureApiVersionSelected(checked) + if (!checked) { setApiConfigurationField("azureApiVersion", "") } @@ -1260,23 +1264,33 @@ const ApiOptions = ({ )} - {selectedProvider === "anthropic" && ( + {selectedProvider === "anthropic" && selectedModelId === "claude-3-7-sonnet-20250219" && (
- + { + const budget = checked ? 16_384 : undefined + setAnthropicThinkingBudget(budget) + setApiConfigurationField("anthropicThinking", budget) + }}> Thinking? - {anthropicThinkingEnabled && ( + {anthropicThinkingBudget && ( <>
- Number of tokens Claude is allowed use for its internal reasoning process + Number of tokens Claude is allowed use for its internal reasoning process.
setAnthropicThinkingBudget(value[0])} + onValueChange={(value) => { + const budget = value[0] + setAnthropicThinkingBudget(budget) + setApiConfigurationField("anthropicThinking", budget) + }} />
{anthropicThinkingBudget}
diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index 0d80580b49..29384826ac 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -1,15 +1,7 @@ -import { VSCodeButton, VSCodeCheckbox, VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react" -import { ExtensionStateContextType, useExtensionState } from "../../context/ExtensionStateContext" -import { validateApiConfiguration, validateModelId } from "../../utils/validate" -import { vscode } from "../../utils/vscode" -import ApiOptions from "./ApiOptions" -import ExperimentalFeature from "./ExperimentalFeature" -import { EXPERIMENT_IDS, experimentConfigsMap, ExperimentId } from "../../../../src/shared/experiments" -import ApiConfigManager from "./ApiConfigManager" -import { Dropdown } from "vscrui" -import type { DropdownOption } from "vscrui" -import { ApiConfiguration } from "../../../../src/shared/api" +import { VSCodeButton, VSCodeCheckbox, VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" +import { Dropdown, type DropdownOption } from "vscrui" + import { AlertDialog, AlertDialogContent, @@ -19,7 +11,17 @@ import { AlertDialogAction, AlertDialogHeader, AlertDialogFooter, -} from "../ui/alert-dialog" +} from "@/components/ui" + +import { vscode } from "../../utils/vscode" +import { validateApiConfiguration, validateModelId } from "../../utils/validate" +import { ExtensionStateContextType, useExtensionState } from "../../context/ExtensionStateContext" +import { EXPERIMENT_IDS, experimentConfigsMap, ExperimentId } from "../../../../src/shared/experiments" +import { ApiConfiguration } from "../../../../src/shared/api" + +import ExperimentalFeature from "./ExperimentalFeature" +import ApiConfigManager from "./ApiConfigManager" +import ApiOptions from "./ApiOptions" type SettingsViewProps = { onDone: () => void @@ -104,7 +106,9 @@ const SettingsView = forwardRef(({ onDone }, if (prevState.apiConfiguration?.[field] === value) { return prevState } + setChangeDetected(true) + return { ...prevState, apiConfiguration: { @@ -131,7 +135,9 @@ const SettingsView = forwardRef(({ onDone }, }, []) const handleSubmit = () => { + console.log("handleSubmit", apiConfiguration) const apiValidationResult = validateApiConfiguration(apiConfiguration) + const modelIdValidationResult = validateModelId( apiConfiguration, extensionState.glamaModels, @@ -140,6 +146,7 @@ const SettingsView = forwardRef(({ onDone }, setApiErrorMessage(apiValidationResult) setModelIdErrorMessage(modelIdValidationResult) + if (!apiValidationResult && !modelIdValidationResult) { vscode.postMessage({ type: "alwaysAllowReadOnly", bool: alwaysAllowReadOnly }) vscode.postMessage({ type: "alwaysAllowWrite", bool: alwaysAllowWrite }) @@ -162,18 +169,9 @@ const SettingsView = forwardRef(({ onDone }, vscode.postMessage({ type: "rateLimitSeconds", value: rateLimitSeconds }) vscode.postMessage({ type: "maxOpenTabsContext", value: maxOpenTabsContext }) vscode.postMessage({ type: "currentApiConfigName", text: currentApiConfigName }) - vscode.postMessage({ - type: "updateExperimental", - values: experiments, - }) + vscode.postMessage({ type: "updateExperimental", values: experiments }) vscode.postMessage({ type: "alwaysAllowModeSwitch", bool: alwaysAllowModeSwitch }) - - vscode.postMessage({ - type: "upsertApiConfiguration", - text: currentApiConfigName, - apiConfiguration, - }) - // onDone() + vscode.postMessage({ type: "upsertApiConfiguration", text: currentApiConfigName, apiConfiguration }) setChangeDetected(false) } } diff --git a/webview-ui/src/components/ui/index.ts b/webview-ui/src/components/ui/index.ts index bf00aa6442..6eb8dd25ba 100644 --- a/webview-ui/src/components/ui/index.ts +++ b/webview-ui/src/components/ui/index.ts @@ -1,3 +1,4 @@ +export * from "./alert-dialog" export * from "./autosize-textarea" export * from "./badge" export * from "./button"