Просмотр исходного кода

fix(provider): honor reasoning option semantics (#37519)

Aiden Cline 1 месяц назад
Родитель
Сommit
49d2dd8a38

+ 2 - 2
packages/opencode/src/provider/transform.ts

@@ -1586,7 +1586,7 @@ export function reasoningVariants(model: ModelsDev.Model, target: Provider.Model
   if (options.length === 0) return {}
 
   const effort = options.find((option) => option.type === "effort")
-  if (effort) return nonEmptyVariants(effortVariants(target, effort.values))
+  if (effort) return effortVariants(target, effort.values)
 
   const toggle = options.some((option) => option.type === "toggle")
   const budget = options.find((option) => option.type === "budget_tokens")
@@ -1651,7 +1651,7 @@ function reasoningEffort(model: Provider.Model, effort: string) {
       return { reasoning: { effort } }
     case "@ai-sdk/anthropic":
     case "@ai-sdk/google-vertex/anthropic":
-      return anthropicEffort(model, effort)
+      return anthropicEffort(model, effort) ?? { effort }
     case "@ai-sdk/google":
     case "@ai-sdk/google-vertex":
       return { thinkingConfig: { includeThoughts: true, thinkingLevel: effort } }

+ 10 - 1
packages/opencode/test/provider/provider.test.ts

@@ -1477,7 +1477,7 @@ test("models.dev normalization fills required response fields", () => {
   expect(model.release_date).toBe("")
 })
 
-test("models.dev reasoning options replace generated variants and unsupported options fall back", () => {
+test("models.dev reasoning options replace generated variants and unsupported toggles fall back", () => {
   const provider = {
     id: "reasoning",
     name: "Reasoning",
@@ -1514,6 +1514,14 @@ test("models.dev reasoning options replace generated variants and unsupported op
         limit: { context: 128_000, output: 64_000 },
         experimental: { modes: { fast: {} } },
       },
+      anthropicCompatible: {
+        id: "k3",
+        name: "Anthropic Compatible",
+        reasoning: true,
+        reasoning_options: [{ type: "effort", values: ["max"] }],
+        provider: { npm: "@ai-sdk/anthropic" },
+        limit: { context: 1_048_576, output: 131_072 },
+      },
     },
   } as unknown as ModelsDev.Provider
 
@@ -1530,6 +1538,7 @@ test("models.dev reasoning options replace generated variants and unsupported op
   expect(models.override.variants).toEqual({
     high: { thinkingConfig: { includeThoughts: true, thinkingLevel: "high" } },
   })
+  expect(models.anthropicCompatible.variants).toEqual({ max: { effort: "max" } })
   expect(models["gemini-3-pro-fast"].variants).toEqual(models.override.variants)
 })
 

+ 18 - 8
packages/opencode/test/provider/transform.test.ts

@@ -3103,13 +3103,20 @@ describe("ProviderTransform.reasoningVariants", () => {
     ).toEqual({ high: { effort: "high" } })
   })
 
-  test("leaves legacy Anthropic effort options to budget fallback", () => {
+  test("uses explicit effort metadata for Anthropic-compatible models", () => {
     expect(
       ProviderTransform.reasoningVariants(
         model([{ type: "effort", values: ["high"] }]),
         target("@ai-sdk/anthropic", "claude-sonnet-4"),
       ),
-    ).toBeUndefined()
+    ).toEqual({ high: { effort: "high" } })
+
+    expect(
+      ProviderTransform.reasoningVariants(
+        model([{ type: "effort", values: ["max"] }]),
+        target("@ai-sdk/anthropic", "k3"),
+      ),
+    ).toEqual({ max: { effort: "max" } })
   })
 
   test("uses adaptive reasoning config for Anthropic models on Bedrock", () => {
@@ -3129,13 +3136,13 @@ describe("ProviderTransform.reasoningVariants", () => {
     })
   })
 
-  test("leaves legacy Anthropic Bedrock effort options to budget fallback", () => {
+  test("does not replace unsupported Anthropic Bedrock effort options with token budgets", () => {
     expect(
       ProviderTransform.reasoningVariants(
         model([{ type: "effort", values: ["high"] }]),
         target("@ai-sdk/amazon-bedrock", "anthropic.claude-sonnet-4-v1:0"),
       ),
-    ).toBeUndefined()
+    ).toEqual({})
   })
 
   test.each([
@@ -3256,10 +3263,13 @@ describe("ProviderTransform.reasoningVariants", () => {
     })
   })
 
-  test("leaves unsupported options for heuristic fallback", () => {
+  test("does not replace unsupported effort options with heuristic variants", () => {
     expect(
       ProviderTransform.reasoningVariants(model([{ type: "effort", values: ["high"] }]), target("@ai-sdk/perplexity")),
-    ).toBeUndefined()
+    ).toEqual({})
+  })
+
+  test("leaves unsupported toggle options for heuristic fallback", () => {
     expect(ProviderTransform.reasoningVariants(model([{ type: "toggle" }]), target("@ai-sdk/openai"))).toBeUndefined()
   })
 
@@ -3275,7 +3285,7 @@ describe("ProviderTransform.reasoningVariants", () => {
     })
     expect(
       ProviderTransform.reasoningVariants(effort, target("@ai-sdk/github-copilot", "gemini-3-pro")),
-    ).toBeUndefined()
+    ).toEqual({})
   })
 
   test.each(["@ai-sdk/cohere", "@ai-sdk/perplexity", "@ai-sdk/vercel", "@ai-sdk/alibaba", "gitlab-ai-provider"])(
@@ -3283,7 +3293,7 @@ describe("ProviderTransform.reasoningVariants", () => {
     (npm) => {
       expect(
         ProviderTransform.reasoningVariants(model([{ type: "effort", values: ["high"] }]), target(npm)),
-      ).toBeUndefined()
+      ).toEqual({})
     },
   )
 })