diff --git a/CHANGELOG.md b/CHANGELOG.md index c67735cfb..c3b909a81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Docs: document DM history limits for channel DMs. (#883) — thanks @pkrmf. ### Fixes +- Agents: scrub tuple `items` schemas for Gemini tool calls. (#926, fixes #746) — thanks @grp06. - Embedded runner: suppress raw API error payloads from replies. (#924) — thanks @grp06. - Auth: normalize Claude Code CLI profile mode to oauth and auto-migrate config. (#855) — thanks @sebslight. - Sandbox: restore `docker.binds` config validation for custom bind mounts. (#873) — thanks @akonyer. diff --git a/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping-a.test.ts b/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping-a.test.ts index a3575180b..ee44b2590 100644 --- a/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping-a.test.ts +++ b/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping-a.test.ts @@ -156,6 +156,30 @@ describe("createClawdbotCodingTools", () => { enum: ["a", "b"], }); }); + it("cleans tuple items schemas", () => { + const cleaned = __testing.cleanToolSchemaForGemini({ + type: "object", + properties: { + tuples: { + type: "array", + items: [ + { type: "string", format: "uuid" }, + { type: "number", minimum: 1 }, + ], + }, + }, + }) as { + properties?: Record; + }; + + const tuples = cleaned.properties?.tuples as { items?: unknown } | undefined; + const items = Array.isArray(tuples?.items) ? tuples?.items : []; + const first = items[0] as { format?: unknown } | undefined; + const second = items[1] as { minimum?: unknown } | undefined; + + expect(first?.format).toBeUndefined(); + expect(second?.minimum).toBeUndefined(); + }); it("drops null-only union variants without flattening other unions", () => { const cleaned = __testing.cleanToolSchemaForGemini({ type: "object", diff --git a/src/agents/schema/clean-for-gemini.ts b/src/agents/schema/clean-for-gemini.ts index ecfc66609..f838ed7a0 100644 --- a/src/agents/schema/clean-for-gemini.ts +++ b/src/agents/schema/clean-for-gemini.ts @@ -280,8 +280,16 @@ function cleanSchemaForGeminiWithDefs( cleanSchemaForGeminiWithDefs(v, nextDefs, refStack), ]), ); - } else if (key === "items" && value && typeof value === "object") { - cleaned[key] = cleanSchemaForGeminiWithDefs(value, nextDefs, refStack); + } else if (key === "items" && value) { + if (Array.isArray(value)) { + cleaned[key] = value.map((entry) => + cleanSchemaForGeminiWithDefs(entry, nextDefs, refStack), + ); + } else if (typeof value === "object") { + cleaned[key] = cleanSchemaForGeminiWithDefs(value, nextDefs, refStack); + } else { + cleaned[key] = value; + } } else if (key === "anyOf" && Array.isArray(value)) { cleaned[key] = cleanedAnyOf ??