From 30ad0e9f2cc77c9d01cba98d7d0cff9afb2c30c5 Mon Sep 17 00:00:00 2001 From: wangbo Date: Tue, 14 Jul 2026 12:55:44 +0800 Subject: [PATCH] =?UTF-8?q?fix(gemini):=20=E4=BD=BF=E7=94=A8=20JSON=20Sche?= =?UTF-8?q?ma=20=E4=BC=A0=E9=80=92=E5=B7=A5=E5=85=B7=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/internal/clients/clients_test.go | 31 ++++++++++++++++++++++- apps/api/internal/clients/gemini.go | 2 +- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/apps/api/internal/clients/clients_test.go b/apps/api/internal/clients/clients_test.go index 7297369..dbd0d9f 100644 --- a/apps/api/internal/clients/clients_test.go +++ b/apps/api/internal/clients/clients_test.go @@ -1406,7 +1406,24 @@ func TestGeminiClientChatRestoresToolContext(t *testing.T) { "function": map[string]any{ "name": "get_weather", "description": "lookup weather", - "parameters": map[string]any{"type": "object"}, + "parameters": map[string]any{ + "type": "object", + "properties": map[string]any{ + "location": map[string]any{ + "anyOf": []any{ + map[string]any{"type": "string"}, + map[string]any{ + "type": "object", + "properties": map[string]any{ + "city": map[string]any{"type": "string"}, + }, + "required": []any{"city"}, + }, + }, + }, + }, + "required": []any{"location"}, + }, }, }}, }, @@ -1450,6 +1467,18 @@ func TestGeminiClientChatRestoresToolContext(t *testing.T) { if declaration["name"] != "get_weather" || declaration["description"] != "lookup weather" { t.Fatalf("tool declaration was not converted for Gemini: %+v", captured["tools"]) } + if _, exists := declaration["parameters"]; exists { + t.Fatalf("Gemini tool declaration must not use OpenAPI parameters: %+v", declaration) + } + parameters, _ := declaration["parametersJsonSchema"].(map[string]any) + properties, _ := parameters["properties"].(map[string]any) + location, _ := properties["location"].(map[string]any) + anyOf, _ := location["anyOf"].([]any) + nestedObject, _ := anyOf[1].(map[string]any) + required, _ := nestedObject["required"].([]any) + if len(anyOf) != 2 || len(required) != 1 || required[0] != "city" { + t.Fatalf("Gemini JSON Schema was not preserved: %+v", declaration) + } } func TestGeminiClientChatConvertsFunctionCallResponse(t *testing.T) { diff --git a/apps/api/internal/clients/gemini.go b/apps/api/internal/clients/gemini.go index 88f5990..8cfe74f 100644 --- a/apps/api/internal/clients/gemini.go +++ b/apps/api/internal/clients/gemini.go @@ -523,7 +523,7 @@ func geminiToolsFromOpenAITools(value any) []any { declaration["description"] = description } if parameters, ok := function["parameters"]; ok { - declaration["parameters"] = parameters + declaration["parametersJsonSchema"] = parameters } declarations = append(declarations, declaration) }