From a1fa5899834d9661f8430d0f28cde6e049039418 Mon Sep 17 00:00:00 2001 From: gabisonia Date: Wed, 16 Sep 2026 16:04:11 +0200 Subject: [PATCH] Preserve raw JSON in tool result compaction --- agent/compaction/compaction_test.go | 38 +++++++++++++++++++++++++++++ agent/compaction/toolresult.go | 7 +++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/agent/compaction/compaction_test.go b/agent/compaction/compaction_test.go index 96e030c7..04dbf6f4 100644 --- a/agent/compaction/compaction_test.go +++ b/agent/compaction/compaction_test.go @@ -350,6 +350,44 @@ func TestToolResultStrategy_CollapsesOldToolGroups(t *testing.T) { } } +func TestDefaultToolCallFormatter_ResultTypes(t *testing.T) { + for _, tc := range []struct { + name string + result any + want string + }{ + {name: "raw JSON object", result: json.RawMessage(`{"status":"shipped"}`), want: "[Tool Calls]\nlookup:\n - {\"status\":\"shipped\"}"}, + {name: "raw JSON array", result: json.RawMessage(`["first","second"]`), want: "[Tool Calls]\nlookup:\n - [\"first\",\"second\"]"}, + {name: "raw JSON null", result: json.RawMessage(`null`), want: "[Tool Calls]\nlookup:\n - null"}, + {name: "empty raw JSON", result: json.RawMessage{}, want: "[Tool Calls]\nlookup:"}, + {name: "nil raw JSON", result: json.RawMessage(nil), want: "[Tool Calls]\nlookup:"}, + {name: "string", result: "shipped", want: "[Tool Calls]\nlookup:\n - shipped"}, + {name: "number", result: 42, want: "[Tool Calls]\nlookup:\n - 42"}, + } { + t.Run(tc.name, func(t *testing.T) { + group := &compaction.MessageGroup{ + Messages: []*message.Message{ + { + Role: message.RoleAssistant, + Contents: []message.Content{ + &message.FunctionCallContent{CallID: "call-1", Name: "lookup"}, + }, + }, + { + Role: message.RoleTool, + Contents: []message.Content{ + &message.FunctionResultContent{CallID: "call-1", Result: tc.result}, + }, + }, + }, + } + if got := compaction.DefaultToolCallFormatter(group); got != tc.want { + t.Fatalf("formatter output = %q, want %q", got, tc.want) + } + }) + } +} + // TestDefaultToolCallFormatter_DedupsRepeatedNamesWithEmptyResults guards the // tool-name deduplication when repeated calls to the same tool produce empty // results. The name must still be listed exactly once, matching the behavior diff --git a/agent/compaction/toolresult.go b/agent/compaction/toolresult.go index a219ef6b..be2776bb 100644 --- a/agent/compaction/toolresult.go +++ b/agent/compaction/toolresult.go @@ -4,6 +4,7 @@ package compaction import ( "context" + "encoding/json" "fmt" "slices" "strings" @@ -120,7 +121,11 @@ func DefaultToolCallFormatter(group *MessageGroup) string { case *message.FunctionCallContent: functionCalls = append(functionCalls, call{id: typed.CallID, name: typed.Name}) case *message.FunctionResultContent: - resultsByCallID[typed.CallID] = fmt.Sprint(typed.Result) + if raw, ok := typed.Result.(json.RawMessage); ok { + resultsByCallID[typed.CallID] = string(raw) + } else { + resultsByCallID[typed.CallID] = fmt.Sprint(typed.Result) + } hasFunctionResult = true } }