diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index f42e14139f1e..ff81c8805691 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -861,13 +861,28 @@ export function variants(model: Provider.Model): Record [effort, { reasoningEffort: effort }])) } - const efforts = [...WIDELY_SUPPORTED_EFFORTS] + + // Add none and max variants to deepseek-v4 models. None is only added to the official + // Deepseek provider because others may not support it. if (model.api.id.toLowerCase().includes("deepseek-v4")) { - efforts.push("max") + const efforts = [...WIDELY_SUPPORTED_EFFORTS, "max"] + if (model.providerID === "deepseek") efforts.unshift("none") + return Object.fromEntries( + efforts.map((effort) => [ + effort, + effort === "none" + ? { thinking: { type: "disabled" } } + : { reasoningEffort: effort }, + ]) + ) } + + // Use the widely supported levels for all other models using this API. + const efforts = [...WIDELY_SUPPORTED_EFFORTS] return Object.fromEntries(efforts.map((effort) => [effort, { reasoningEffort: effort }])) case "@ai-sdk/azure": diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 7307e3f60b7e..5f3e65e225a2 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -1,4 +1,6 @@ import { describe, expect, test } from "bun:test" +import { generateText } from "ai" +import { createOpenAICompatible } from "@ai-sdk/openai-compatible" import { Effect } from "effect" import { ProviderTransform } from "@/provider/transform" import { LLMRequestPrep } from "@/session/llm/request" @@ -3798,6 +3800,49 @@ describe("ProviderTransform.variants", () => { high: { reasoningEffort: "high" }, }) }) + + test("deepseek-v4 none disables thinking on the wire", async () => { + const model = createMockModel({ + id: "deepseek/deepseek-v4-pro", + providerID: "deepseek", + api: { + id: "deepseek-v4-pro", + url: "https://api.deepseek.com", + npm: "@ai-sdk/openai-compatible", + }, + }) + let body: Record | undefined + const deepseek = createOpenAICompatible({ + name: "deepseek", + baseURL: model.api.url, + apiKey: "test", + fetch: Object.assign( + async (_input: Parameters[0], init?: Parameters[1]) => { + body = JSON.parse(String(init?.body)) + return new Response( + JSON.stringify({ + id: "chatcmpl-test", + object: "chat.completion", + created: 0, + model: model.api.id, + choices: [{ index: 0, message: { role: "assistant", content: "ok" }, finish_reason: "stop" }], + usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }, + }), + { headers: { "Content-Type": "application/json" } }, + ) + }, + { preconnect: fetch.preconnect.bind(fetch) }, + ), + }) + + await generateText({ + model: deepseek(model.api.id), + prompt: "hi", + providerOptions: ProviderTransform.providerOptions(model, ProviderTransform.variants(model).none), + }) + + expect(body?.thinking).toEqual({ type: "disabled" }) + }) }) describe("@ai-sdk/azure", () => {