Skip to content

Commit 56e48e7

Browse files
authored
Merge pull request #259 from LeXwDeX/dev
fix(provider): promote DeepSeek schema compatibility
2 parents 86b1183 + 1b886d1 commit 56e48e7

2 files changed

Lines changed: 27 additions & 0 deletions

File tree

packages/opencode/src/provider/transform.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,19 @@ export function schema(model: Provider.Model, schema: JSONSchema7): JSONSchema7
15371537
schema = sanitizeGemini(schema)
15381538
}
15391539

1540+
// DeepSeek rejects function schemas whose root type is implicit. Effect
1541+
// emits object-only discriminated unions as a root `anyOf`; retaining the
1542+
// union while declaring its shared object type preserves every branch.
1543+
if (
1544+
model.api.id.toLowerCase().includes("deepseek") &&
1545+
schema.type === undefined &&
1546+
Array.isArray(schema.anyOf) &&
1547+
schema.anyOf.length > 0 &&
1548+
schema.anyOf.every((branch) => isPlainObject(branch) && branch.type === "object")
1549+
) {
1550+
schema = { ...schema, type: "object" }
1551+
}
1552+
15401553
return schema
15411554
}
15421555

packages/opencode/test/tool/workflow-provider-schema.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ import { ProviderTransform } from "../../src/provider/transform"
1111
const openaiModel = { providerID: "openai", api: { id: "gpt-4.1", npm: "@ai-sdk/openai" } } as never
1212
const azureModel = { providerID: "azure", api: { id: "gpt-4.1", npm: "@ai-sdk/azure" } } as never
1313
const geminiModel = { providerID: "google", api: { id: "gemini-3-pro", npm: "@ai-sdk/google" } } as never
14+
const deepseekModel = {
15+
providerID: "deepseek",
16+
api: { id: "deepseek-v4-pro", npm: "@ai-sdk/openai-compatible" },
17+
} as never
1418

1519
type JsonSchemaNode = {
1620
anyOf?: JsonSchemaNode[]
@@ -117,6 +121,16 @@ describe("workflow provider-facing schema", () => {
117121
expect(Object.keys(record(resultBranch))).toEqual(expect.arrayContaining(["cursor", "limit"]))
118122
})
119123

124+
test("DeepSeek transformation presents the workflow union as an object-root function schema", () => {
125+
const transformed = ProviderTransform.schema(
126+
deepseekModel,
127+
ToolJsonSchema.fromSchema(Parameters as never),
128+
) as JsonSchemaNode
129+
expect(transformed.type).toBe("object")
130+
expect(branches(transformed)).toHaveLength(10)
131+
expect(branchByAction(transformed, "start", "spec_path")).toHaveLength(1)
132+
})
133+
120134
test("post-change byte sizes stay at the recorded evidence", async () => {
121135
const evidence = (await Bun.file(
122136
new URL("./fixtures/workflow-parameters-post-change.json", import.meta.url),

0 commit comments

Comments
 (0)