tweak: make interleaved reasoning_content default to true for openai compat deepseek setups (#24630)
This commit is contained in:
@@ -1135,6 +1135,13 @@ const layer: Layer.Layer<
|
|||||||
|
|
||||||
for (const [modelID, model] of Object.entries(provider.models ?? {})) {
|
for (const [modelID, model] of Object.entries(provider.models ?? {})) {
|
||||||
const existingModel = parsed.models[model.id ?? modelID]
|
const existingModel = parsed.models[model.id ?? modelID]
|
||||||
|
const apiID = model.id ?? existingModel?.api.id ?? modelID
|
||||||
|
const apiNpm =
|
||||||
|
model.provider?.npm ??
|
||||||
|
provider.npm ??
|
||||||
|
existingModel?.api.npm ??
|
||||||
|
modelsDev[providerID]?.npm ??
|
||||||
|
"@ai-sdk/openai-compatible"
|
||||||
const name = iife(() => {
|
const name = iife(() => {
|
||||||
if (model.name) return model.name
|
if (model.name) return model.name
|
||||||
if (model.id && model.id !== modelID) return modelID
|
if (model.id && model.id !== modelID) return modelID
|
||||||
@@ -1143,13 +1150,8 @@ const layer: Layer.Layer<
|
|||||||
const parsedModel: Model = {
|
const parsedModel: Model = {
|
||||||
id: ModelID.make(modelID),
|
id: ModelID.make(modelID),
|
||||||
api: {
|
api: {
|
||||||
id: model.id ?? existingModel?.api.id ?? modelID,
|
id: apiID,
|
||||||
npm:
|
npm: apiNpm,
|
||||||
model.provider?.npm ??
|
|
||||||
provider.npm ??
|
|
||||||
existingModel?.api.npm ??
|
|
||||||
modelsDev[providerID]?.npm ??
|
|
||||||
"@ai-sdk/openai-compatible",
|
|
||||||
url: model.provider?.api ?? provider?.api ?? existingModel?.api.url ?? modelsDev[providerID]?.api ?? "",
|
url: model.provider?.api ?? provider?.api ?? existingModel?.api.url ?? modelsDev[providerID]?.api ?? "",
|
||||||
},
|
},
|
||||||
status: model.status ?? existingModel?.status ?? "active",
|
status: model.status ?? existingModel?.status ?? "active",
|
||||||
@@ -1177,7 +1179,12 @@ const layer: Layer.Layer<
|
|||||||
model.modalities?.output?.includes("video") ?? existingModel?.capabilities.output.video ?? false,
|
model.modalities?.output?.includes("video") ?? existingModel?.capabilities.output.video ?? false,
|
||||||
pdf: model.modalities?.output?.includes("pdf") ?? existingModel?.capabilities.output.pdf ?? false,
|
pdf: model.modalities?.output?.includes("pdf") ?? existingModel?.capabilities.output.pdf ?? false,
|
||||||
},
|
},
|
||||||
interleaved: model.interleaved ?? existingModel?.capabilities.interleaved ?? false,
|
interleaved:
|
||||||
|
model.interleaved ??
|
||||||
|
existingModel?.capabilities.interleaved ??
|
||||||
|
(!existingModel && apiNpm === "@ai-sdk/openai-compatible" && apiID.includes("deepseek")
|
||||||
|
? { field: "reasoning_content" }
|
||||||
|
: false),
|
||||||
},
|
},
|
||||||
cost: {
|
cost: {
|
||||||
input: model?.cost?.input ?? existingModel?.cost?.input ?? 0,
|
input: model?.cost?.input ?? existingModel?.cost?.input ?? 0,
|
||||||
|
|||||||
@@ -312,6 +312,67 @@ test("custom provider with npm package", async () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("custom DeepSeek openai-compatible model defaults interleaved reasoning field", async () => {
|
||||||
|
await using tmp = await tmpdir({
|
||||||
|
init: async (dir) => {
|
||||||
|
await Bun.write(
|
||||||
|
path.join(dir, "opencode.json"),
|
||||||
|
JSON.stringify({
|
||||||
|
$schema: "https://opencode.ai/config.json",
|
||||||
|
provider: {
|
||||||
|
"custom-provider": {
|
||||||
|
name: "Custom Provider",
|
||||||
|
npm: "@ai-sdk/openai-compatible",
|
||||||
|
api: "https://api.custom.com/v1",
|
||||||
|
models: {
|
||||||
|
"deepseek-r1": {
|
||||||
|
name: "DeepSeek R1",
|
||||||
|
},
|
||||||
|
"deepseek-details": {
|
||||||
|
name: "DeepSeek Details",
|
||||||
|
interleaved: { field: "reasoning_details" },
|
||||||
|
},
|
||||||
|
"custom-model": {
|
||||||
|
name: "Custom Model",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
apiKey: "custom-key",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"custom-anthropic-provider": {
|
||||||
|
name: "Custom Anthropic Provider",
|
||||||
|
npm: "@ai-sdk/anthropic",
|
||||||
|
api: "https://api.custom.com/v1",
|
||||||
|
models: {
|
||||||
|
"deepseek-r1": {
|
||||||
|
name: "DeepSeek R1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
apiKey: "custom-key",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await Instance.provide({
|
||||||
|
directory: tmp.path,
|
||||||
|
fn: async () => {
|
||||||
|
const providers = await list()
|
||||||
|
const provider = providers[ProviderID.make("custom-provider")]
|
||||||
|
expect(provider.models["deepseek-r1"].capabilities.interleaved).toEqual({ field: "reasoning_content" })
|
||||||
|
expect(provider.models["deepseek-details"].capabilities.interleaved).toEqual({ field: "reasoning_details" })
|
||||||
|
expect(provider.models["custom-model"].capabilities.interleaved).toBe(false)
|
||||||
|
expect(
|
||||||
|
providers[ProviderID.make("custom-anthropic-provider")].models["deepseek-r1"].capabilities.interleaved,
|
||||||
|
).toBe(false)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test("env variable takes precedence, config merges options", async () => {
|
test("env variable takes precedence, config merges options", async () => {
|
||||||
await using tmp = await tmpdir({
|
await using tmp = await tmpdir({
|
||||||
init: async (dir) => {
|
init: async (dir) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user