@@ -353,7 +353,7 @@ func TestReductionMiddlewareClear(t *testing.T) {
353353 Function : schema.FunctionCall {Name : "get_weather" , Arguments : `{"location": "London, UK", "unit": "c"}` },
354354 },
355355 }),
356- schema .ToolMessage ("Sunny" , "call_123456789 " ),
356+ schema .ToolMessage ("Sunny" , "call_987654321 " ),
357357 schema .AssistantMessage ("" , []schema.ToolCall {
358358 {
359359 ID : "call_123456789" ,
@@ -460,7 +460,7 @@ func TestReductionMiddlewareClear(t *testing.T) {
460460 Function : schema.FunctionCall {Name : "get_weather" , Arguments : `{"location": "London, UK", "unit": "c"}` },
461461 },
462462 }),
463- schema .ToolMessage ("Sunny" , "call_123456789 " ),
463+ schema .ToolMessage ("Sunny" , "call_987654321 " ),
464464 schema .AssistantMessage ("" , []schema.ToolCall {
465465 {
466466 ID : "call_123456789" ,
@@ -491,6 +491,74 @@ func TestReductionMiddlewareClear(t *testing.T) {
491491 assert .Equal (t , "[Old tool result content cleared]" , s .Messages [3 ].Content )
492492 })
493493
494+ t .Run ("test clear with reordered tool results" , func (t * testing.T ) {
495+ backend := filesystem .NewInMemoryBackend ()
496+ config := & Config {
497+ SkipTruncation : true ,
498+ TokenCounter : defaultTokenCounter ,
499+ MaxTokensForClear : 20 ,
500+ ClearRetentionSuffixLimit : 0 ,
501+ ToolConfig : map [string ]* ToolReductionConfig {
502+ "get_weather" : {
503+ Backend : backend ,
504+ SkipClear : false ,
505+ ClearHandler : defaultClearHandler (testClearOffloadPath ("/tmp" ), true , "read_file" ),
506+ },
507+ },
508+ }
509+
510+ mw , err := New (ctx , config )
511+ assert .NoError (t , err )
512+ _ , s , err := mw .BeforeModelRewriteState (ctx , & adk.ChatModelAgentState {
513+ Messages : []adk.Message {
514+ schema .SystemMessage ("you are a helpful assistant" ),
515+ schema .UserMessage ("get weather for two cities" ),
516+ // Assistant message with two tool calls
517+ schema .AssistantMessage ("" , []schema.ToolCall {
518+ {
519+ ID : "two_call_one" ,
520+ Type : "function" ,
521+ Function : schema.FunctionCall {Name : "get_weather" , Arguments : `{"location": "London"}` },
522+ },
523+ {
524+ ID : "two_call_two" ,
525+ Type : "function" ,
526+ Function : schema.FunctionCall {Name : "get_weather" , Arguments : `{"location": "Paris"}` },
527+ },
528+ }),
529+ // Intentionally put tool result two BEFORE tool result one
530+ schema .ToolMessage ("Cloudy in Paris" , "two_call_two" ),
531+ schema .ToolMessage ("Sunny in London" , "two_call_one" ),
532+ schema .AssistantMessage ("" , []schema.ToolCall {{ID : "dummy" , Type : "function" , Function : schema.FunctionCall {Name : "dummy_tool" }}}),
533+ },
534+ }, & adk.ModelContext {
535+ Tools : toolsInfo ,
536+ })
537+ assert .NoError (t , err )
538+
539+ // Verify tool call arguments are preserved (not offloaded since offload is true)
540+ assert .Equal (t , `{"location": "London"}` , s .Messages [2 ].ToolCalls [0 ].Function .Arguments )
541+ assert .Equal (t , `{"location": "Paris"}` , s .Messages [2 ].ToolCalls [1 ].Function .Arguments )
542+
543+ // Verify tool result two is correctly matched and offloaded (it's at index 3)
544+ assert .Equal (t , "<persisted-output>Tool result saved to: /tmp/clear/two_call_two\n Use read_file to view</persisted-output>" , s .Messages [3 ].Content )
545+ fileContent2 , err := backend .Read (ctx , & filesystem.ReadRequest {
546+ FilePath : "/tmp/clear/two_call_two" ,
547+ })
548+ assert .NoError (t , err )
549+ fileContentStr2 := strings .TrimPrefix (strings .TrimSpace (fileContent2 .Content ), "1\t " )
550+ assert .Equal (t , "Cloudy in Paris" , fileContentStr2 )
551+
552+ // Verify tool result one is correctly matched and offloaded (it's at index 4)
553+ assert .Equal (t , "<persisted-output>Tool result saved to: /tmp/clear/two_call_one\n Use read_file to view</persisted-output>" , s .Messages [4 ].Content )
554+ fileContent1 , err := backend .Read (ctx , & filesystem.ReadRequest {
555+ FilePath : "/tmp/clear/two_call_one" ,
556+ })
557+ assert .NoError (t , err )
558+ fileContentStr1 := strings .TrimPrefix (strings .TrimSpace (fileContent1 .Content ), "1\t " )
559+ assert .Equal (t , "Sunny in London" , fileContentStr1 )
560+ })
561+
494562 t .Run ("test clear" , func (t * testing.T ) {
495563 backend := filesystem .NewInMemoryBackend ()
496564 handler := func (ctx context.Context , detail * ToolDetail ) (* ClearResult , error ) {
@@ -547,7 +615,7 @@ func TestReductionMiddlewareClear(t *testing.T) {
547615 Function : schema.FunctionCall {Name : "get_weather" , Arguments : `{"location": "London, UK", "unit": "c"}` },
548616 },
549617 }),
550- schema .ToolMessage ("Sunny" , "call_123456789 " ),
618+ schema .ToolMessage ("Sunny" , "call_987654321 " ),
551619 schema .AssistantMessage ("" , []schema.ToolCall {
552620 {
553621 ID : "call_123456789" ,
@@ -621,7 +689,7 @@ func TestReductionMiddlewareClear(t *testing.T) {
621689 Function : schema.FunctionCall {Name : "get_weather" , Arguments : `{"location": "London, UK", "unit": "c"}` },
622690 },
623691 }),
624- schema .ToolMessage ("Sunny" , "call_123456789 " ),
692+ schema .ToolMessage ("Sunny" , "call_987654321 " ),
625693 schema .AssistantMessage ("" , []schema.ToolCall {
626694 {
627695 ID : "call_123456789" ,
@@ -872,7 +940,7 @@ func TestReductionMiddlewareClear(t *testing.T) {
872940 Function : schema.FunctionCall {Name : "get_weather" , Arguments : `{"location": "London, UK", "unit": "c"}` },
873941 },
874942 }),
875- schema .ToolMessage ("Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny" , "call_123456789 " ),
943+ schema .ToolMessage ("Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny Sunny" , "call_987654321 " ),
876944 schema .AssistantMessage ("" , []schema.ToolCall {
877945 {
878946 ID : "call_123456789" ,
0 commit comments