diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 320af4d3953..0aacf0935c2 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -424,6 +424,10 @@ export namespace ProviderTransform { result.required = result.required.filter((field: any) => field in result.properties) } + if (result.type === "array" && result.items == null) { + result.items = {} + } + return result } diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 17ae7f55808..78bd296c99c 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -167,6 +167,30 @@ describe("ProviderTransform.maxOutputTokens", () => { }) }) +describe("ProviderTransform.schema - gemini array items", () => { + test("adds missing items for array properties", () => { + const geminiModel = { + providerID: "google", + api: { + id: "gemini-3-pro", + }, + } as any + + const schema = { + type: "object", + properties: { + nodes: { type: "array" }, + edges: { type: "array", items: { type: "string" } }, + }, + } as any + + const result = ProviderTransform.schema(geminiModel, schema) as any + + expect(result.properties.nodes.items).toBeDefined() + expect(result.properties.edges.items.type).toBe("string") + }) +}) + describe("ProviderTransform.message - DeepSeek reasoning content", () => { test("DeepSeek with tool calls includes reasoning_content in providerOptions", () => { const msgs = [