From 069b94983bf0c33202527998719def13d044f594 Mon Sep 17 00:00:00 2001 From: ChickenBreast-ky Date: Wed, 11 Feb 2026 22:38:01 +0900 Subject: [PATCH 1/2] fix(provider): infer type 'object' for schemas with properties but missing type in Gemini sanitization Follow-up to #11888. sanitizeGemini strips properties/required from non-object types, but misses the case where type is entirely undefined. MCP tools like Notion define schemas with properties/required but no type field, causing Gemini API 400 errors. This fix infers type 'object' when properties or required exist but type is missing, per JSON Schema's implicit object semantics. Fixes #13148 --- packages/opencode/src/provider/transform.ts | 6 +++ .../opencode/test/provider/transform.test.ts | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 7ed89cb2599c..01de2dfc7ed0 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -792,6 +792,12 @@ export namespace ProviderTransform { } } + // Infer type "object" when properties/required exist but type is missing + // (common in MCP tool schemas like Notion MCP) + if (!result.type && (result.properties || result.required)) { + result.type = "object" + } + // Remove properties/required from non-object types (Gemini rejects these) if (result.type && result.type !== "object") { delete result.properties diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 02bb5278fc7d..8de192ce6b91 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -398,6 +398,49 @@ describe("ProviderTransform.schema - gemini non-object properties removal", () = expect(result.properties.data.required).toEqual(["name"]) }) + test("infers type 'object' when properties exist but type is missing", () => { + const schema = { + type: "object", + properties: { + data: { + description: "The data", + properties: { page_id: { type: "string" } }, + required: ["page_id"], + }, + }, + } as any + + const result = ProviderTransform.schema(geminiModel, schema) as any + + expect(result.properties.data.type).toBe("object") + expect(result.properties.data.properties).toBeDefined() + expect(result.properties.data.required).toEqual(["page_id"]) + }) + + test("infers type 'object' for array items with properties but no type", () => { + const schema = { + type: "object", + properties: { + title: { + type: "array", + items: { + properties: { + annotations: { + type: "object", + properties: { bold: { type: "boolean" } }, + }, + }, + }, + }, + }, + } as any + + const result = ProviderTransform.schema(geminiModel, schema) as any + + expect(result.properties.title.items.type).toBe("object") + expect(result.properties.title.items.properties).toBeDefined() + }) + test("does not affect non-gemini providers", () => { const openaiModel = { providerID: "openai", From 2ec40194b3e437690c8194cb01f7a930c6b241e0 Mon Sep 17 00:00:00 2001 From: Kiyoung Chang <81131079+ChickenBreast-ky@users.noreply.github.com> Date: Thu, 19 Feb 2026 09:57:47 +0900 Subject: [PATCH 2/2] chore(ci): retrigger checks for PR #13150