@@ -203,7 +203,7 @@ async def test_stream_request_with_reasoning(gemini_client, model, model_id):
203203 {
204204 "reasoningContent" : {
205205 "reasoningText" : {
206- "signature" : "abc" ,
206+ "signature" : "YWJj" , # base64 of "abc"
207207 "text" : "reasoning_text" ,
208208 },
209209 },
@@ -260,6 +260,51 @@ async def test_stream_request_with_tool_spec(gemini_client, model, model_id, too
260260
261261@pytest .mark .asyncio
262262async def test_stream_request_with_tool_use (gemini_client , model , model_id ):
263+ """Test toolUse with reasoningSignature is sent as function_call with thought_signature."""
264+ messages = [
265+ {
266+ "role" : "assistant" ,
267+ "content" : [
268+ {
269+ "toolUse" : {
270+ "toolUseId" : "c1" ,
271+ "name" : "calculator" ,
272+ "input" : {"expression" : "2+2" },
273+ "reasoningSignature" : "YWJj" , # base64 of "abc"
274+ },
275+ },
276+ ],
277+ },
278+ ]
279+ await anext (model .stream (messages ))
280+
281+ exp_request = {
282+ "config" : {
283+ "tools" : [{"function_declarations" : []}],
284+ },
285+ "contents" : [
286+ {
287+ "parts" : [
288+ {
289+ "function_call" : {
290+ "args" : {"expression" : "2+2" },
291+ "id" : "c1" ,
292+ "name" : "calculator" ,
293+ },
294+ "thought_signature" : "YWJj" ,
295+ },
296+ ],
297+ "role" : "model" ,
298+ },
299+ ],
300+ "model" : model_id ,
301+ }
302+ gemini_client .aio .models .generate_content_stream .assert_called_with (** exp_request )
303+
304+
305+ @pytest .mark .asyncio
306+ async def test_stream_request_with_tool_use_no_reasoning_signature (gemini_client , model , model_id ):
307+ """Test toolUse without reasoningSignature is sent as function_call without thought_signature."""
263308 messages = [
264309 {
265310 "role" : "assistant" ,
@@ -532,6 +577,55 @@ async def test_stream_response_tool_use(gemini_client, model, messages, agenerat
532577 assert tru_chunks == exp_chunks
533578
534579
580+ @pytest .mark .asyncio
581+ async def test_stream_response_tool_use_with_thought_signature (gemini_client , model , messages , agenerator , alist ):
582+ """Test that tool use responses with thought_signature include reasoningSignature."""
583+ gemini_client .aio .models .generate_content_stream .return_value = agenerator (
584+ [
585+ genai .types .GenerateContentResponse (
586+ candidates = [
587+ genai .types .Candidate (
588+ content = genai .types .Content (
589+ parts = [
590+ genai .types .Part (
591+ function_call = genai .types .FunctionCall (
592+ args = {"expression" : "2+2" },
593+ id = "c1" ,
594+ name = "calculator" ,
595+ ),
596+ thought_signature = b"abc" ,
597+ ),
598+ ],
599+ ),
600+ finish_reason = "STOP" ,
601+ ),
602+ ],
603+ usage_metadata = genai .types .GenerateContentResponseUsageMetadata (
604+ prompt_token_count = 1 ,
605+ total_token_count = 3 ,
606+ ),
607+ ),
608+ ]
609+ )
610+
611+ tru_chunks = await alist (model .stream (messages ))
612+ exp_chunks = [
613+ {"messageStart" : {"role" : "assistant" }},
614+ {
615+ "contentBlockStart" : {
616+ "start" : {
617+ "toolUse" : {"name" : "calculator" , "toolUseId" : "c1" , "reasoningSignature" : "YWJj" },
618+ },
619+ },
620+ },
621+ {"contentBlockDelta" : {"delta" : {"toolUse" : {"input" : '{"expression": "2+2"}' }}}},
622+ {"contentBlockStop" : {}},
623+ {"messageStop" : {"stopReason" : "tool_use" }},
624+ {"metadata" : {"usage" : {"inputTokens" : 1 , "outputTokens" : 2 , "totalTokens" : 3 }, "metrics" : {"latencyMs" : 0 }}},
625+ ]
626+ assert tru_chunks == exp_chunks
627+
628+
535629@pytest .mark .asyncio
536630async def test_stream_response_reasoning (gemini_client , model , messages , agenerator , alist ):
537631 gemini_client .aio .models .generate_content_stream .return_value = agenerator (
@@ -563,7 +657,7 @@ async def test_stream_response_reasoning(gemini_client, model, messages, agenera
563657 exp_chunks = [
564658 {"messageStart" : {"role" : "assistant" }},
565659 {"contentBlockStart" : {"start" : {}}},
566- {"contentBlockDelta" : {"delta" : {"reasoningContent" : {"signature" : "abc " , "text" : "test reason" }}}},
660+ {"contentBlockDelta" : {"delta" : {"reasoningContent" : {"signature" : "YWJj " , "text" : "test reason" }}}},
567661 {"contentBlockStop" : {}},
568662 {"messageStop" : {"stopReason" : "end_turn" }},
569663 {"metadata" : {"usage" : {"inputTokens" : 1 , "outputTokens" : 2 , "totalTokens" : 3 }, "metrics" : {"latencyMs" : 0 }}},
@@ -622,7 +716,11 @@ async def test_stream_response_reasoning_and_text(gemini_client, model, messages
622716 exp_chunks = [
623717 {"messageStart" : {"role" : "assistant" }},
624718 {"contentBlockStart" : {"start" : {}}},
625- {"contentBlockDelta" : {"delta" : {"reasoningContent" : {"signature" : "sig1" , "text" : "thinking about math" }}}},
719+ {
720+ "contentBlockDelta" : {
721+ "delta" : {"reasoningContent" : {"signature" : "c2lnMQ==" , "text" : "thinking about math" }}
722+ }
723+ },
626724 {"contentBlockStop" : {}},
627725 {"contentBlockStart" : {"start" : {}}},
628726 {"contentBlockDelta" : {"delta" : {"text" : "2 + 2 = 4" }}},
0 commit comments