diff --git a/src/api/providers/__tests__/openai.spec.ts b/src/api/providers/__tests__/openai.spec.ts index 9c79e56159..72d219e02a 100644 --- a/src/api/providers/__tests__/openai.spec.ts +++ b/src/api/providers/__tests__/openai.spec.ts @@ -453,6 +453,27 @@ describe("OpenAiHandler", () => { expect(callArgs.reasoning_effort).toBe("high") }) + it("should pass through max reasoning_effort when configured by an OpenAI-compatible model", async () => { + const reasoningOptions: ApiHandlerOptions = { + ...mockOptions, + enableReasoningEffort: true, + openAiCustomModelInfo: { + contextWindow: 128_000, + supportsPromptCache: false, + supportsReasoningEffort: ["low", "medium", "high", "xhigh", "max"], + reasoningEffort: "max", + }, + } + const reasoningHandler = new OpenAiHandler(reasoningOptions) + const stream = reasoningHandler.createMessage(systemPrompt, messages) + for await (const _chunk of stream) { + } + + expect(mockCreate).toHaveBeenCalled() + const callArgs = mockCreate.mock.calls[0][0] + expect(callArgs.reasoning_effort).toBe("max") + }) + it("should not include reasoning_effort when reasoning effort is disabled", async () => { const noReasoningOptions: ApiHandlerOptions = { ...mockOptions, diff --git a/webview-ui/src/components/settings/providers/OpenAICompatible.tsx b/webview-ui/src/components/settings/providers/OpenAICompatible.tsx index 0524932c5f..8b11c128c7 100644 --- a/webview-ui/src/components/settings/providers/OpenAICompatible.tsx +++ b/webview-ui/src/components/settings/providers/OpenAICompatible.tsx @@ -6,7 +6,7 @@ import { VSCodeButton, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" import { type ProviderSettings, type ModelInfo, - type ReasoningEffort, + type ReasoningEffortExtended, type OrganizationAllowList, type ExtensionMessage, azureOpenAiDefaultApiVersion, @@ -266,13 +266,13 @@ export const OpenAICompatible = ({ setApiConfigurationField("openAiCustomModelInfo", { ...openAiCustomModelInfo, - reasoningEffort: value as ReasoningEffort, + reasoningEffort: value as ReasoningEffortExtended, }) } }} modelInfo={{ ...(apiConfiguration.openAiCustomModelInfo || openAiModelInfoSaneDefaults), - supportsReasoningEffort: ["low", "medium", "high", "xhigh"], + supportsReasoningEffort: ["low", "medium", "high", "xhigh", "max"], }} /> )} 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 aba81ec219..3da109efc2 100644 --- a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.spec.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.spec.tsx @@ -76,8 +76,13 @@ vi.mock("../../R1FormatSetting", () => ({ R1FormatSetting: () =>
R1 Format Setting
, })) +const { mockThinkingBudget } = vi.hoisted(() => ({ mockThinkingBudget: vi.fn() })) + vi.mock("../../ThinkingBudget", () => ({ - ThinkingBudget: () =>
Thinking Budget
, + ThinkingBudget: (props: any) => { + mockThinkingBudget(props) + return
Thinking Budget
+ }, })) // Mock react-use @@ -312,4 +317,39 @@ describe("OpenAICompatible Component - includeMaxTokens checkbox", () => { expect(description).toHaveClass("text-sm", "text-vscode-descriptionForeground", "ml-6") }) }) + describe("reasoning effort", () => { + it("should expose and persist the max reasoning-effort value", () => { + const apiConfiguration: Partial = { + enableReasoningEffort: true, + openAiCustomModelInfo: { + contextWindow: 128_000, + supportsPromptCache: false, + }, + } + + render( + , + ) + + const thinkingBudgetProps = mockThinkingBudget.mock.calls[0][0] + expect(thinkingBudgetProps.modelInfo.supportsReasoningEffort).toEqual([ + "low", + "medium", + "high", + "xhigh", + "max", + ]) + + thinkingBudgetProps.setApiConfigurationField("reasoningEffort", "max") + + expect(mockSetApiConfigurationField).toHaveBeenCalledWith("openAiCustomModelInfo", { + ...apiConfiguration.openAiCustomModelInfo, + reasoningEffort: "max", + }) + }) + }) })