diff --git a/src/api/providers/__tests__/vertex.test.ts b/src/api/providers/__tests__/vertex.test.ts index 076f902ca..9cf92f0a1 100644 --- a/src/api/providers/__tests__/vertex.test.ts +++ b/src/api/providers/__tests__/vertex.test.ts @@ -641,7 +641,7 @@ describe("VertexHandler", () => { vertexProjectId: "test-project", vertexRegion: "us-central1", modelMaxTokens: 16384, - vertexThinking: 4096, + modelMaxThinkingTokens: 4096, }) const modelInfo = thinkingHandler.getModel() @@ -662,7 +662,7 @@ describe("VertexHandler", () => { vertexProjectId: "test-project", vertexRegion: "us-central1", modelMaxTokens: 16384, - vertexThinking: 5000, + modelMaxThinkingTokens: 5000, }) expect((handlerWithBudget.getModel().thinking as any).budget_tokens).toBe(5000) @@ -688,25 +688,13 @@ describe("VertexHandler", () => { expect((handlerWithSmallMaxTokens.getModel().thinking as any).budget_tokens).toBe(1024) }) - it("should use anthropicThinking value if vertexThinking is not provided", () => { - const handler = new VertexHandler({ - apiModelId: "claude-3-7-sonnet@20250219:thinking", - vertexProjectId: "test-project", - vertexRegion: "us-central1", - modelMaxTokens: 16384, - anthropicThinking: 6000, // Should be used as fallback - }) - - expect((handler.getModel().thinking as any).budget_tokens).toBe(6000) - }) - it("should pass thinking configuration to API", async () => { const thinkingHandler = new VertexHandler({ apiModelId: "claude-3-7-sonnet@20250219:thinking", vertexProjectId: "test-project", vertexRegion: "us-central1", modelMaxTokens: 16384, - vertexThinking: 4096, + modelMaxThinkingTokens: 4096, }) const mockCreate = jest.fn().mockImplementation(async (options) => { diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts index eca81eab2..fc0b99c59 100644 --- a/src/api/providers/anthropic.ts +++ b/src/api/providers/anthropic.ts @@ -206,7 +206,7 @@ export class AnthropicHandler implements ApiHandler, SingleCompletionHandler { // least 1024 tokens. const maxBudgetTokens = Math.floor(maxTokens * 0.8) const budgetTokens = Math.max( - Math.min(this.options.anthropicThinking ?? maxBudgetTokens, maxBudgetTokens), + Math.min(this.options.modelMaxThinkingTokens ?? maxBudgetTokens, maxBudgetTokens), 1024, ) diff --git a/src/api/providers/openrouter.ts b/src/api/providers/openrouter.ts index 69bcb0074..82c02e20a 100644 --- a/src/api/providers/openrouter.ts +++ b/src/api/providers/openrouter.ts @@ -117,7 +117,7 @@ export class OpenRouterHandler implements ApiHandler, SingleCompletionHandler { // least 1024 tokens. const maxBudgetTokens = Math.floor((maxTokens || 8192) * 0.8) const budgetTokens = Math.max( - Math.min(this.options.anthropicThinking ?? maxBudgetTokens, maxBudgetTokens), + Math.min(this.options.modelMaxThinkingTokens ?? maxBudgetTokens, maxBudgetTokens), 1024, ) diff --git a/src/api/providers/vertex.ts b/src/api/providers/vertex.ts index 69fb7d26f..a25fad07e 100644 --- a/src/api/providers/vertex.ts +++ b/src/api/providers/vertex.ts @@ -300,10 +300,7 @@ export class VertexHandler implements ApiHandler, SingleCompletionHandler { temperature = 1.0 // Thinking requires temperature 1.0 const maxBudgetTokens = Math.floor(maxTokens * 0.8) const budgetTokens = Math.max( - Math.min( - this.options.vertexThinking ?? this.options.anthropicThinking ?? maxBudgetTokens, - maxBudgetTokens, - ), + Math.min(this.options.modelMaxThinkingTokens ?? maxBudgetTokens, maxBudgetTokens), 1024, ) thinking = { type: "enabled", budget_tokens: budgetTokens } diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 5417e54ff..7b6f2c897 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1651,8 +1651,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { lmStudioModelId, lmStudioBaseUrl, anthropicBaseUrl, - anthropicThinking, - vertexThinking, geminiApiKey, openAiNativeApiKey, deepSeekApiKey, @@ -1673,6 +1671,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { requestyModelInfo, modelTemperature, modelMaxTokens, + modelMaxThinkingTokens, } = apiConfiguration await Promise.all([ this.updateGlobalState("apiProvider", apiProvider), @@ -1701,8 +1700,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { this.updateGlobalState("lmStudioModelId", lmStudioModelId), this.updateGlobalState("lmStudioBaseUrl", lmStudioBaseUrl), this.updateGlobalState("anthropicBaseUrl", anthropicBaseUrl), - this.updateGlobalState("anthropicThinking", anthropicThinking), - this.updateGlobalState("vertexThinking", vertexThinking), this.storeSecret("geminiApiKey", geminiApiKey), this.storeSecret("openAiNativeApiKey", openAiNativeApiKey), this.storeSecret("deepSeekApiKey", deepSeekApiKey), @@ -1723,6 +1720,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { this.updateGlobalState("requestyModelInfo", requestyModelInfo), this.updateGlobalState("modelTemperature", modelTemperature), this.updateGlobalState("modelMaxTokens", modelMaxTokens), + this.updateGlobalState("anthropicThinking", modelMaxThinkingTokens), ]) if (this.cline) { this.cline.api = buildApiHandler(apiConfiguration) @@ -2159,8 +2157,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { lmStudioModelId, lmStudioBaseUrl, anthropicBaseUrl, - anthropicThinking, - vertexThinking, geminiApiKey, openAiNativeApiKey, deepSeekApiKey, @@ -2216,6 +2212,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { requestyModelInfo, modelTemperature, modelMaxTokens, + modelMaxThinkingTokens, maxOpenTabsContext, ] = await Promise.all([ this.getGlobalState("apiProvider") as Promise, @@ -2244,8 +2241,6 @@ 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.getGlobalState("vertexThinking") as Promise, this.getSecret("geminiApiKey") as Promise, this.getSecret("openAiNativeApiKey") as Promise, this.getSecret("deepSeekApiKey") as Promise, @@ -2301,6 +2296,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { this.getGlobalState("requestyModelInfo") as Promise, this.getGlobalState("modelTemperature") as Promise, this.getGlobalState("modelMaxTokens") as Promise, + this.getGlobalState("anthropicThinking") as Promise, this.getGlobalState("maxOpenTabsContext") as Promise, ]) @@ -2346,8 +2342,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { lmStudioModelId, lmStudioBaseUrl, anthropicBaseUrl, - anthropicThinking, - vertexThinking, geminiApiKey, openAiNativeApiKey, deepSeekApiKey, @@ -2368,6 +2362,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { requestyModelInfo, modelTemperature, modelMaxTokens, + modelMaxThinkingTokens, }, lastShownAnnouncementId, customInstructions, diff --git a/src/shared/__tests__/checkExistApiConfig.test.ts b/src/shared/__tests__/checkExistApiConfig.test.ts index 62517d695..c99ddddbc 100644 --- a/src/shared/__tests__/checkExistApiConfig.test.ts +++ b/src/shared/__tests__/checkExistApiConfig.test.ts @@ -32,7 +32,7 @@ describe("checkExistKey", () => { apiKey: "test-key", apiProvider: undefined, anthropicBaseUrl: undefined, - anthropicThinking: undefined, + modelMaxThinkingTokens: undefined, } expect(checkExistKey(config)).toBe(true) }) diff --git a/src/shared/api.ts b/src/shared/api.ts index b36781d63..f88bb5e8b 100644 --- a/src/shared/api.ts +++ b/src/shared/api.ts @@ -21,7 +21,6 @@ export interface ApiHandlerOptions { apiModelId?: string apiKey?: string // anthropic anthropicBaseUrl?: string - anthropicThinking?: number vsCodeLmModelSelector?: vscode.LanguageModelChatSelector glamaModelId?: string glamaModelInfo?: ModelInfo @@ -41,7 +40,6 @@ export interface ApiHandlerOptions { awsUseProfile?: boolean vertexProjectId?: string vertexRegion?: string - vertexThinking?: number openAiBaseUrl?: string openAiApiKey?: string openAiModelId?: string @@ -70,6 +68,7 @@ export interface ApiHandlerOptions { requestyModelInfo?: ModelInfo modelTemperature?: number modelMaxTokens?: number + modelMaxThinkingTokens?: number } export type ApiConfiguration = ApiHandlerOptions & { diff --git a/src/shared/globalState.ts b/src/shared/globalState.ts index 6e29e0383..aabc77cc0 100644 --- a/src/shared/globalState.ts +++ b/src/shared/globalState.ts @@ -24,7 +24,6 @@ export type GlobalStateKey = | "awsUseProfile" | "vertexProjectId" | "vertexRegion" - | "vertexThinking" | "lastShownAnnouncementId" | "customInstructions" | "alwaysAllowReadOnly" @@ -43,7 +42,6 @@ export type GlobalStateKey = | "lmStudioModelId" | "lmStudioBaseUrl" | "anthropicBaseUrl" - | "anthropicThinking" | "azureApiVersion" | "openAiStreamingEnabled" | "openRouterModelId" @@ -83,5 +81,6 @@ export type GlobalStateKey = | "unboundModelInfo" | "modelTemperature" | "modelMaxTokens" + | "anthropicThinking" // TODO: Rename to `modelMaxThinkingTokens`. | "mistralCodestralUrl" | "maxOpenTabsContext" diff --git a/webview-ui/src/components/settings/ThinkingBudget.tsx b/webview-ui/src/components/settings/ThinkingBudget.tsx index d21e1fb7e..557a69538 100644 --- a/webview-ui/src/components/settings/ThinkingBudget.tsx +++ b/webview-ui/src/components/settings/ThinkingBudget.tsx @@ -17,27 +17,24 @@ export const ThinkingBudget = ({ modelInfo, provider, }: ThinkingBudgetProps) => { - const isVertexProvider = provider === "vertex" - const budgetField = isVertexProvider ? "vertexThinking" : "anthropicThinking" - const tokens = apiConfiguration?.modelMaxTokens || modelInfo?.maxTokens || 64_000 const tokensMin = 8192 const tokensMax = modelInfo?.maxTokens || 64_000 // Get the appropriate thinking tokens based on provider const thinkingTokens = useMemo(() => { - const value = isVertexProvider ? apiConfiguration?.vertexThinking : apiConfiguration?.anthropicThinking + const value = apiConfiguration?.modelMaxThinkingTokens return value || Math.min(Math.floor(0.8 * tokens), 8192) - }, [apiConfiguration, isVertexProvider, tokens]) + }, [apiConfiguration, tokens]) const thinkingTokensMin = 1024 const thinkingTokensMax = Math.floor(0.8 * tokens) useEffect(() => { if (thinkingTokens > thinkingTokensMax) { - setApiConfigurationField(budgetField, thinkingTokensMax) + setApiConfigurationField("modelMaxThinkingTokens", thinkingTokensMax) } - }, [thinkingTokens, thinkingTokensMax, setApiConfigurationField, budgetField]) + }, [thinkingTokens, thinkingTokensMax, setApiConfigurationField]) if (!modelInfo?.thinking) { return null @@ -66,7 +63,7 @@ export const ThinkingBudget = ({ max={thinkingTokensMax} step={1024} value={[thinkingTokens]} - onValueChange={([value]) => setApiConfigurationField(budgetField, value)} + onValueChange={([value]) => setApiConfigurationField("modelMaxThinkingTokens", value)} />
{thinkingTokens}
diff --git a/webview-ui/src/components/settings/__tests__/ApiOptions.test.tsx b/webview-ui/src/components/settings/__tests__/ApiOptions.test.tsx index 65ae13700..06ed95585 100644 --- a/webview-ui/src/components/settings/__tests__/ApiOptions.test.tsx +++ b/webview-ui/src/components/settings/__tests__/ApiOptions.test.tsx @@ -51,12 +51,7 @@ jest.mock("../ThinkingBudget", () => ({ ThinkingBudget: ({ apiConfiguration, setApiConfigurationField, modelInfo, provider }: any) => modelInfo?.thinking ? (
- +
) : null, })) diff --git a/webview-ui/src/components/settings/__tests__/ThinkingBudget.test.tsx b/webview-ui/src/components/settings/__tests__/ThinkingBudget.test.tsx index 54f6b1037..212316ea9 100644 --- a/webview-ui/src/components/settings/__tests__/ThinkingBudget.test.tsx +++ b/webview-ui/src/components/settings/__tests__/ThinkingBudget.test.tsx @@ -60,13 +60,13 @@ describe("ThinkingBudget", () => { expect(screen.getAllByTestId("slider")).toHaveLength(2) }) - it("should use anthropicThinking field for Anthropic provider", () => { + it("should use modelMaxThinkingTokens field for Anthropic provider", () => { const setApiConfigurationField = jest.fn() render( , @@ -75,16 +75,16 @@ describe("ThinkingBudget", () => { const sliders = screen.getAllByTestId("slider") fireEvent.change(sliders[1], { target: { value: "5000" } }) - expect(setApiConfigurationField).toHaveBeenCalledWith("anthropicThinking", 5000) + expect(setApiConfigurationField).toHaveBeenCalledWith("modelMaxThinkingTokens", 5000) }) - it("should use vertexThinking field for Vertex provider", () => { + it("should use modelMaxThinkingTokens field for Vertex provider", () => { const setApiConfigurationField = jest.fn() render( , @@ -93,7 +93,7 @@ describe("ThinkingBudget", () => { const sliders = screen.getAllByTestId("slider") fireEvent.change(sliders[1], { target: { value: "5000" } }) - expect(setApiConfigurationField).toHaveBeenCalledWith("vertexThinking", 5000) + expect(setApiConfigurationField).toHaveBeenCalledWith("modelMaxThinkingTokens", 5000) }) it("should cap thinking tokens at 80% of max tokens", () => { @@ -102,13 +102,13 @@ describe("ThinkingBudget", () => { render( , ) // Effect should trigger and cap the value - expect(setApiConfigurationField).toHaveBeenCalledWith("anthropicThinking", 8000) // 80% of 10000 + expect(setApiConfigurationField).toHaveBeenCalledWith("modelMaxThinkingTokens", 8000) // 80% of 10000 }) it("should use default thinking tokens if not provided", () => {