From 43dd33842ee70de0675ea3d1362b67b7dbff0051 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Mon, 17 Aug 2026 13:43:52 -0500 Subject: [PATCH] fix(ai): default Gemini function args (#43111) --- packages/ai/src/protocols/gemini.ts | 4 ++-- packages/ai/test/provider/gemini.test.ts | 25 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/packages/ai/src/protocols/gemini.ts b/packages/ai/src/protocols/gemini.ts index 6038f469a5..7dd3ff4be8 100644 --- a/packages/ai/src/protocols/gemini.ts +++ b/packages/ai/src/protocols/gemini.ts @@ -92,7 +92,7 @@ const GeminiFunctionCallPart = Schema.Struct({ functionCall: Schema.Struct({ id: Schema.optional(Schema.String), name: Schema.String, - args: Schema.Unknown, + args: Schema.optional(Schema.Unknown), }), thoughtSignature: Schema.optional(Schema.String), }) @@ -586,7 +586,7 @@ const step = (state: ParserState, event: GeminiEvent) => { } if ("functionCall" in part) { - const input = part.functionCall.args + const input = part.functionCall.args === undefined ? {} : part.functionCall.args const id = `tool_${nextToolCallId++}` const metadata = { ...(part.functionCall.id === undefined ? {} : { functionCallId: part.functionCall.id }), diff --git a/packages/ai/test/provider/gemini.test.ts b/packages/ai/test/provider/gemini.test.ts index ec0da96e9d..b228e73592 100644 --- a/packages/ai/test/provider/gemini.test.ts +++ b/packages/ai/test/provider/gemini.test.ts @@ -767,6 +767,31 @@ describe("Gemini route", () => { }), ) + it.effect("defaults omitted function call args to an empty object", () => + Effect.gen(function* () { + const response = yield* LLMClient.generate( + LLMRequest.update(request, { + tools: [ToolDefinition.make({ name: "ping", description: "Ping", inputSchema: { type: "object" } })], + }), + ).pipe( + Effect.provide( + fixedResponse( + sseEvents({ + candidates: [ + { + content: { role: "model", parts: [{ functionCall: { name: "ping" } }] }, + finishReason: "STOP", + }, + ], + }), + ), + ), + ) + + expect(response.toolCalls).toEqual([{ type: "tool-call", id: "tool_0", name: "ping", input: {} }]) + }), + ) + it.effect("maps tool calls without a finish reason", () => Effect.gen(function* () { const response = yield* LLMClient.generate(