Skip to content

Commit df5fdef

Browse files
fix: respect explicit supportsReasoningEffort array values (#9970)
1 parent f472a82 commit df5fdef

File tree

2 files changed

+99
-4
lines changed

2 files changed

+99
-4
lines changed

webview-ui/src/components/settings/ThinkingBudget.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,16 @@ export const ThinkingBudget = ({ apiConfiguration, setApiConfigurationField, mod
8787

8888
// "disable" turns off reasoning entirely; "none" is a valid reasoning level.
8989
// Both display as "None" in the UI but behave differently.
90-
// Add "disable" option if reasoning effort is not required.
90+
// Add "disable" option only when:
91+
// 1. requiredReasoningEffort is not true, AND
92+
// 2. supportsReasoningEffort is boolean true (not an explicit array)
93+
// When the model provides an explicit array, respect those exact values.
9194
type ReasoningEffortOption = ReasoningEffortWithMinimal | "none" | "disable"
92-
const availableOptions: ReadonlyArray<ReasoningEffortOption> = modelInfo?.requiredReasoningEffort
93-
? (baseAvailableOptions as ReadonlyArray<ReasoningEffortOption>)
94-
: (["disable", ...baseAvailableOptions] as ReasoningEffortOption[])
95+
const shouldAutoAddDisable =
96+
!modelInfo?.requiredReasoningEffort && supports === true && !baseAvailableOptions.includes("disable" as any)
97+
const availableOptions: ReadonlyArray<ReasoningEffortOption> = shouldAutoAddDisable
98+
? (["disable", ...baseAvailableOptions] as ReasoningEffortOption[])
99+
: (baseAvailableOptions as ReadonlyArray<ReasoningEffortOption>)
95100

96101
// Default reasoning effort - use model's default if available
97102
// GPT-5 models have "medium" as their default in the model configuration

webview-ui/src/components/settings/__tests__/ThinkingBudget.spec.tsx

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,19 @@ vi.mock("@/components/ui", () => ({
1818
onChange={(e) => onValueChange([parseInt(e.target.value)])}
1919
/>
2020
),
21+
Select: ({ children, value, onValueChange: _onValueChange }: any) => (
22+
<div data-testid="select" data-value={value}>
23+
{children}
24+
</div>
25+
),
26+
SelectTrigger: ({ children }: any) => <button data-testid="select-trigger">{children}</button>,
27+
SelectValue: ({ placeholder }: any) => <span data-testid="select-value">{placeholder}</span>,
28+
SelectContent: ({ children }: any) => <div data-testid="select-content">{children}</div>,
29+
SelectItem: ({ children, value }: any) => (
30+
<div data-testid={`select-item-${value}`} data-value={value}>
31+
{children}
32+
</div>
33+
),
2134
}))
2235

2336
vi.mock("@/components/ui/hooks/useSelectedModel", () => ({
@@ -215,4 +228,81 @@ describe("ThinkingBudget", () => {
215228

216229
expect(setApiConfigurationField).toHaveBeenCalledWith("modelMaxTokens", 12000)
217230
})
231+
232+
describe("reasoning effort dropdown", () => {
233+
const reasoningEffortModelInfo: ModelInfo = {
234+
supportsReasoningEffort: true,
235+
contextWindow: 200000,
236+
supportsPromptCache: true,
237+
}
238+
239+
it("should show 'disable' option when supportsReasoningEffort is boolean true", () => {
240+
render(<ThinkingBudget {...defaultProps} modelInfo={reasoningEffortModelInfo} />)
241+
242+
expect(screen.getByTestId("reasoning-effort")).toBeInTheDocument()
243+
// "disable" should be shown when supportsReasoningEffort is true (boolean)
244+
expect(screen.getByTestId("select-item-disable")).toBeInTheDocument()
245+
expect(screen.getByTestId("select-item-low")).toBeInTheDocument()
246+
expect(screen.getByTestId("select-item-medium")).toBeInTheDocument()
247+
expect(screen.getByTestId("select-item-high")).toBeInTheDocument()
248+
})
249+
250+
it("should NOT show 'disable' option when supportsReasoningEffort is an explicit array without disable", () => {
251+
render(
252+
<ThinkingBudget
253+
{...defaultProps}
254+
modelInfo={{
255+
...reasoningEffortModelInfo,
256+
supportsReasoningEffort: ["low", "high"],
257+
}}
258+
/>,
259+
)
260+
261+
expect(screen.getByTestId("reasoning-effort")).toBeInTheDocument()
262+
// "disable" should NOT be shown when model explicitly specifies only ["low", "high"]
263+
expect(screen.queryByTestId("select-item-disable")).not.toBeInTheDocument()
264+
expect(screen.getByTestId("select-item-low")).toBeInTheDocument()
265+
expect(screen.queryByTestId("select-item-medium")).not.toBeInTheDocument()
266+
expect(screen.getByTestId("select-item-high")).toBeInTheDocument()
267+
})
268+
269+
it("should show 'disable' option when supportsReasoningEffort array explicitly includes disable", () => {
270+
render(
271+
<ThinkingBudget
272+
{...defaultProps}
273+
modelInfo={{
274+
...reasoningEffortModelInfo,
275+
supportsReasoningEffort: ["disable", "low", "high"],
276+
}}
277+
/>,
278+
)
279+
280+
expect(screen.getByTestId("reasoning-effort")).toBeInTheDocument()
281+
// "disable" should be shown when model explicitly includes it in the array
282+
expect(screen.getByTestId("select-item-disable")).toBeInTheDocument()
283+
expect(screen.getByTestId("select-item-low")).toBeInTheDocument()
284+
expect(screen.queryByTestId("select-item-medium")).not.toBeInTheDocument()
285+
expect(screen.getByTestId("select-item-high")).toBeInTheDocument()
286+
})
287+
288+
it("should show 'none' option when supportsReasoningEffort array includes none", () => {
289+
render(
290+
<ThinkingBudget
291+
{...defaultProps}
292+
modelInfo={{
293+
...reasoningEffortModelInfo,
294+
supportsReasoningEffort: ["none", "low", "medium", "high"],
295+
}}
296+
/>,
297+
)
298+
299+
expect(screen.getByTestId("reasoning-effort")).toBeInTheDocument()
300+
// Only values from the explicit array should be shown
301+
expect(screen.queryByTestId("select-item-disable")).not.toBeInTheDocument()
302+
expect(screen.getByTestId("select-item-none")).toBeInTheDocument()
303+
expect(screen.getByTestId("select-item-low")).toBeInTheDocument()
304+
expect(screen.getByTestId("select-item-medium")).toBeInTheDocument()
305+
expect(screen.getByTestId("select-item-high")).toBeInTheDocument()
306+
})
307+
})
218308
})

0 commit comments

Comments
 (0)