From 3b45b170fe486489e46db2960eb9331d8925b763 Mon Sep 17 00:00:00 2001 From: Julian von der Goltz Date: Wed, 20 May 2026 15:00:38 +0200 Subject: [PATCH] Address Gemini thought signature review feedback --- .../llms/vertex_ai/gemini/transformation.py | 4 -- litellm/types/llms/vertex_ai.py | 1 + .../test_vertex_ai_gemini_transformation.py | 49 +++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/litellm/llms/vertex_ai/gemini/transformation.py b/litellm/llms/vertex_ai/gemini/transformation.py index 3a4e52997de..65cdddd6c01 100644 --- a/litellm/llms/vertex_ai/gemini/transformation.py +++ b/litellm/llms/vertex_ai/gemini/transformation.py @@ -994,10 +994,6 @@ def _gemini_convert_messages_with_history( # noqa: PLR0915 if ( isinstance(existing_part, dict) and existing_part.get("thoughtSignature") - and ( - existing_part.get("functionCall") is not None - or existing_part.get("function_call") is not None - ) ): turn_thought_signature = existing_part.get( "thoughtSignature" diff --git a/litellm/types/llms/vertex_ai.py b/litellm/types/llms/vertex_ai.py index 87bf11a9026..452d9f0cbf5 100644 --- a/litellm/types/llms/vertex_ai.py +++ b/litellm/types/llms/vertex_ai.py @@ -39,6 +39,7 @@ class PartType(TypedDict, total=False): inline_data: BlobType file_data: FileDataType function_call: FunctionCall + functionCall: FunctionCall function_response: FunctionResponse thought: bool thoughtSignature: str diff --git a/tests/test_litellm/llms/vertex_ai/gemini/test_vertex_ai_gemini_transformation.py b/tests/test_litellm/llms/vertex_ai/gemini/test_vertex_ai_gemini_transformation.py index 2c53d9970c8..68de50d3b0c 100644 --- a/tests/test_litellm/llms/vertex_ai/gemini/test_vertex_ai_gemini_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/gemini/test_vertex_ai_gemini_transformation.py @@ -569,6 +569,55 @@ def test_parallel_tool_calls_copy_thought_signature_from_thinking_block(): assert all(p.get("thoughtSignature") == "sig-turn-123" for p in function_parts) +def test_parallel_tool_calls_copy_thought_signature_from_text_thinking_block(): + """Text-fallback thinking blocks still carry the turn signature.""" + messages = [ + { + "role": "assistant", + "content": None, + "thinking_blocks": [ + { + "type": "thinking", + "thinking": "I need to call both tools.", + "signature": "sig-text-thinking", + } + ], + "tool_calls": [ + { + "id": "call_1", + "type": "function", + "function": { + "name": "get_current_temperature", + "arguments": '{"location": "Paris"}', + }, + "index": 0, + }, + { + "id": "call_2", + "type": "function", + "function": { + "name": "get_current_temperature", + "arguments": '{"location": "London"}', + }, + "index": 1, + }, + ], + } + ] + + contents = _gemini_convert_messages_with_history(messages, model="gemini-2.5-flash") + + function_parts = [ + p + for p in contents[0]["parts"] + if p.get("functionCall") is not None or p.get("function_call") is not None + ] + assert len(function_parts) == 2 + assert all( + p.get("thoughtSignature") == "sig-text-thinking" for p in function_parts + ) + + def test_thought_signature_with_function_call_mode(): """Test thought signature extraction in function_call mode (is_function_call=True)""" from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import (