@@ -92,6 +116,23 @@ export const InteractiveDemo: Story = {
},
};
+export const Opus45ThreeLevels: Story = {
+ args: { modelString: "anthropic:claude-opus-4-5" },
+ render: (args) => (
+
+
+ Claude Opus 4.5 uses the effort parameter (low/medium/high only, no “off”):
+
+
+
+ • Low: Conservative token usage
+
• Medium: Balanced usage (default)
+
• High: Best results, more tokens
+
+
+ ),
+};
+
export const LockedThinking: Story = {
args: { modelString: "openai:gpt-5-pro" },
render: (args) => (
diff --git a/src/browser/utils/thinking/policy.test.ts b/src/browser/utils/thinking/policy.test.ts
index ac99b3b7d6..974fca0c63 100644
--- a/src/browser/utils/thinking/policy.test.ts
+++ b/src/browser/utils/thinking/policy.test.ts
@@ -33,6 +33,23 @@ describe("getThinkingPolicyForModel", () => {
]);
});
+ test("returns low/medium/high for Opus 4.5", () => {
+ expect(getThinkingPolicyForModel("anthropic:claude-opus-4-5")).toEqual([
+ "low",
+ "medium",
+ "high",
+ ]);
+ expect(getThinkingPolicyForModel("anthropic:claude-opus-4-5-20251101")).toEqual([
+ "low",
+ "medium",
+ "high",
+ ]);
+ });
+
+ test("returns low/high for Gemini 3", () => {
+ expect(getThinkingPolicyForModel("google:gemini-3-pro-preview")).toEqual(["low", "high"]);
+ });
+
test("returns all levels for other providers", () => {
expect(getThinkingPolicyForModel("anthropic:claude-opus-4")).toEqual([
"off",
@@ -46,7 +63,6 @@ describe("getThinkingPolicyForModel", () => {
"medium",
"high",
]);
- expect(getThinkingPolicyForModel("google:gemini-3-pro-preview")).toEqual(["low", "high"]);
});
});
@@ -78,6 +94,22 @@ describe("enforceThinkingPolicy", () => {
expect(enforceThinkingPolicy("openai:gpt-5-pro", "low")).toBe("high");
});
});
+
+ describe("Opus 4.5 (no off option)", () => {
+ test("allows low/medium/high levels", () => {
+ expect(enforceThinkingPolicy("anthropic:claude-opus-4-5", "low")).toBe("low");
+ expect(enforceThinkingPolicy("anthropic:claude-opus-4-5", "medium")).toBe("medium");
+ expect(enforceThinkingPolicy("anthropic:claude-opus-4-5", "high")).toBe("high");
+ });
+
+ test("falls back to high when off is requested", () => {
+ expect(enforceThinkingPolicy("anthropic:claude-opus-4-5", "off")).toBe("high");
+ });
+
+ test("falls back to high when off is requested (versioned model)", () => {
+ expect(enforceThinkingPolicy("anthropic:claude-opus-4-5-20251101", "off")).toBe("high");
+ });
+ });
});
// Note: Tests for invalid levels removed - TypeScript type system prevents invalid
diff --git a/src/browser/utils/thinking/policy.ts b/src/browser/utils/thinking/policy.ts
index e8157b3725..41c2fad4fd 100644
--- a/src/browser/utils/thinking/policy.ts
+++ b/src/browser/utils/thinking/policy.ts
@@ -25,6 +25,8 @@ export type ThinkingPolicy = readonly ThinkingLevel[];
*
* Rules:
* - openai:gpt-5-pro → ["high"] (only supported level)
+ * - anthropic:claude-opus-4-5 → ["low", "medium", "high"] (effort parameter only)
+ * - gemini-3 → ["low", "high"] (thinking level only)
* - default → ["off", "low", "medium", "high"] (all levels selectable)
*
* Tolerates version suffixes (e.g., gpt-5-pro-2025-10-06).
@@ -37,6 +39,12 @@ export function getThinkingPolicyForModel(modelString: string): ThinkingPolicy {
return ["high"];
}
+ // Claude Opus 4.5 only supports effort parameter: low, medium, high (no "off")
+ // Match "anthropic:" followed by "claude-opus-4-5" with optional version suffix
+ if (modelString.includes("opus-4-5")) {
+ return ["low", "medium", "high"];
+ }
+
// Gemini 3 Pro only supports "low" and "high" reasoning levels
if (modelString.includes("gemini-3")) {
return ["low", "high"];
@@ -51,8 +59,8 @@ export function getThinkingPolicyForModel(modelString: string): ThinkingPolicy {
*
* Fallback strategy:
* 1. If requested level is allowed, use it
- * 2. If "medium" is allowed, use it (reasonable default)
- * 3. Otherwise use first allowed level
+ * 2. For Opus 4.5: prefer "high" (best experience for reasoning model)
+ * 3. Otherwise: prefer "medium" if allowed, else use first allowed level
*/
export function enforceThinkingPolicy(
modelString: string,
@@ -64,6 +72,11 @@ export function enforceThinkingPolicy(
return requested;
}
+ // Special case: Opus 4.5 defaults to "high" for best experience
+ if (modelString.includes("opus-4-5") && allowed.includes("high")) {
+ return "high";
+ }
+
// Fallback: prefer "medium" if allowed, else use first allowed level
return allowed.includes("medium") ? "medium" : allowed[0];
}