From e7649e0151f4296b53596cb1f99cc9cf7305a928 Mon Sep 17 00:00:00 2001 From: Frank <97429702+tsubasakong@users.noreply.github.com> Date: Thu, 12 Mar 2026 10:55:06 -0700 Subject: [PATCH] fix: add fallback Gemini array item schema --- astrbot/core/agent/tool.py | 12 ++++++- tests/unit/test_tool_google_schema.py | 47 +++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/unit/test_tool_google_schema.py diff --git a/astrbot/core/agent/tool.py b/astrbot/core/agent/tool.py index c2536708e6..a7707c9a6f 100644 --- a/astrbot/core/agent/tool.py +++ b/astrbot/core/agent/tool.py @@ -293,7 +293,17 @@ def convert_schema(schema: dict) -> dict: if properties: result["properties"] = properties - if "items" in schema: + if target_type == "array": + # Gemini rejects array schemas that omit `items`, while JSON Schema + # producers in the wild (especially external MCP tools) sometimes + # leave element types unspecified. Fall back to a permissive string + # item schema so tool calling stays functional instead of failing the + # whole request with `items: missing field`. + if isinstance(schema.get("items"), dict) and schema["items"]: + result["items"] = convert_schema(schema["items"]) + else: + result["items"] = {"type": "string"} + elif "items" in schema: result["items"] = convert_schema(schema["items"]) return result diff --git a/tests/unit/test_tool_google_schema.py b/tests/unit/test_tool_google_schema.py new file mode 100644 index 0000000000..eed2311163 --- /dev/null +++ b/tests/unit/test_tool_google_schema.py @@ -0,0 +1,47 @@ +from astrbot.core.agent.tool import FunctionTool, ToolSet + + +def test_google_schema_adds_default_items_for_array_parameters_without_items(): + tool = FunctionTool( + name="lookup_sources", + description="Look up sources by UUID.", + parameters={ + "type": "object", + "properties": { + "source_uuids": { + "type": "array", + "description": "Source UUIDs to fetch.", + } + }, + }, + ) + + schema = ToolSet(tools=[tool]).google_schema() + source_uuids = schema["function_declarations"][0]["parameters"]["properties"][ + "source_uuids" + ] + + assert source_uuids["type"] == "array" + assert source_uuids["items"] == {"type": "string"} + + +def test_google_schema_preserves_explicit_array_item_schema(): + tool = FunctionTool( + name="lookup_numbers", + description="Look up integer values.", + parameters={ + "type": "object", + "properties": { + "numbers": { + "type": "array", + "items": {"type": "integer", "format": "int32"}, + } + }, + }, + ) + + schema = ToolSet(tools=[tool]).google_schema() + numbers = schema["function_declarations"][0]["parameters"]["properties"]["numbers"] + + assert numbers["type"] == "array" + assert numbers["items"] == {"type": "integer", "format": "int32"}