fix(gemini): parse tool call arguments with the shared helper

_gemini_tool_call_invoke_helper called json.loads() on the assistant
tool call arguments directly. A null value raised TypeError and a
truncated JSON string raised JSONDecodeError, so the whole request
failed with "Unable to convert openai tool calls ... to gemini tool
calls" before it reached Gemini.

Use parse_tool_call_arguments(), which the Anthropic path already
uses: null becomes {} and truncated JSON is repaired with a warning.
The empty-string branch is unchanged.
This commit is contained in:
Yuxiang Zhou 2026-11-03 23:16:54 -05:00
parent cbe361d970
commit 6b51246630
2 changed files with 37 additions and 1 deletions

View file

@ -1221,7 +1221,7 @@ def _gemini_tool_call_invoke_helper(
"type": "object",
}
else:
arguments_dict = json.loads(arguments)
arguments_dict = parse_tool_call_arguments(arguments, tool_name=name, context="Gemini tool invoke")
function_call: Final = VertexFunctionCall(
name=name,
args=arguments_dict,

View file

@ -1857,6 +1857,42 @@ def test_vertex_ai_transform_empty_function_call_arguments():
}
@pytest.mark.parametrize(
"arguments, expected_args",
[
(None, {}),
('{"location": "Boston"', {"location": "Boston"}),
],
ids=["null_arguments", "truncated_arguments"],
)
def test_convert_to_gemini_tool_call_invoke_tolerates_null_and_truncated_arguments(arguments, expected_args):
"""
Gemini conversion must accept the same tool call arguments as the Anthropic
path: null is treated as no arguments and truncated JSON is repaired,
instead of raising "Unable to convert openai tool calls".
"""
from litellm.litellm_core_utils.prompt_templates.factory import (
convert_to_gemini_tool_call_invoke,
)
message = {
"role": "assistant",
"content": None,
"tool_calls": [
{
"id": "call_1",
"type": "function",
"function": {"name": "get_weather", "arguments": arguments},
}
],
}
parts = convert_to_gemini_tool_call_invoke(message)
assert len(parts) == 1
assert parts[0]["function_call"]["name"] == "get_weather"
assert parts[0]["function_call"]["args"] == expected_args
@pytest.mark.asyncio
async def test_bedrock_process_image_async_factory():
"""