Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/google/adk/models/lite_llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1716,7 +1716,13 @@ def _message_to_generate_content_response(
name=tool_call.function.name,
args=json.loads(tool_call.function.arguments or "{}"),
)
part.function_call.id = tool_call.id
# The signature is carried on the part, so strip it back out of the id.
# Leaving it there leaks base64 into anything keyed by function_call_id —
# artifact filenames, logs, UI — and `_content_to_message_param` re-attaches
# it to the outgoing tool call from `thought_signature` anyway.
part.function_call.id = tool_call.id.split(
_THOUGHT_SIGNATURE_SEPARATOR, 1
)[0]
if thought_signature:
part.thought_signature = thought_signature
parts.append(part)
Expand Down
24 changes: 24 additions & 0 deletions tests/unittests/models/test_litellm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2560,6 +2560,30 @@ def test_message_to_generate_content_response_preserves_thought_signature():
assert fc_part.thought_signature == b"round_trip_sig"


def test_message_to_generate_content_response_strips_signature_from_id():
"""An id carrying an embedded signature is split before it reaches the part."""
sig_b64 = base64.b64encode(b"embedded_sig").decode("utf-8")
message = ChatCompletionAssistantMessage(
role="assistant",
content=None,
tool_calls=[
ChatCompletionMessageToolCall(
type="function",
id=f"call_ts_2{_THOUGHT_SIGNATURE_SEPARATOR}{sig_b64}",
function=Function(
name="load_skill",
arguments='{"skill": "my_skill"}',
),
)
],
)

response = _message_to_generate_content_response(message)
fc_part = response.content.parts[0]
assert fc_part.function_call.id == "call_ts_2"
assert fc_part.thought_signature == b"embedded_sig"


def test_message_to_generate_content_response_no_thought_signature():
"""Parts without thought_signature have thought_signature=None."""
message = ChatCompletionAssistantMessage(
Expand Down
Loading