From f533990e86e182b3d8cb0aa80cddb7a5ae8da5b1 Mon Sep 17 00:00:00 2001 From: PratikDhanave Date: Fri, 24 Jul 2026 09:30:02 +0530 Subject: [PATCH] Join Response.String() messages with a newline like .NET ConcatText Response.String() flattened every message's text into one builder with no separator, so a multi-message assistant turn returned "fooBar" where .NET AgentResponse.Text (backed by ChatMessage list ConcatText) returns "foo\nBar". Join each non-empty per-message text with a newline, skipping empty messages, matching .NET semantics. This also aligns the agent-as-tool result returned by agenttool's FuncTool, which surfaces resp.String(). --- agent/response.go | 14 ++++++++++---- agent/response_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/agent/response.go b/agent/response.go index 6bd8aa4b..a05f6621 100644 --- a/agent/response.go +++ b/agent/response.go @@ -69,11 +69,17 @@ func (resp *Response) String() string { } var sb strings.Builder for _, msg := range resp.Messages { - for _, c := range msg.Contents { - if textContent, ok := c.(*message.TextContent); ok { - sb.WriteString(textContent.Text) - } + // msg.String() equals message.Contents.Text(), the per-message join. + // Add a newline separator between each non-empty message, matching + // .NET's ChatMessage list ConcatText / AgentResponse.Text. + t := msg.String() + if t == "" { + continue + } + if sb.Len() > 0 { + sb.WriteByte('\n') } + sb.WriteString(t) } return sb.String() } diff --git a/agent/response_test.go b/agent/response_test.go index 6ed913fd..e0475aa0 100644 --- a/agent/response_test.go +++ b/agent/response_test.go @@ -788,3 +788,44 @@ func TestResponse_ToUpdates_WithAdditionalPropertiesOnlyProducesSingleUpdate(t * t.Errorf("expected key value, got %v", updates[0].AdditionalProperties["key"]) } } + +func TestResponse_String(t *testing.T) { + msg := func(texts ...string) *message.Message { + var contents message.Contents + for _, text := range texts { + contents = append(contents, &message.TextContent{Text: text}) + } + return &message.Message{Role: message.RoleAssistant, Contents: contents} + } + + tests := []struct { + name string + messages []*message.Message + want string + }{ + { + name: "two messages joined with newline", + messages: []*message.Message{msg("foo"), msg("Bar")}, + want: "foo\nBar", + }, + { + name: "empty middle message skipped without double newline", + messages: []*message.Message{msg("foo"), msg(""), msg("Bar")}, + want: "foo\nBar", + }, + { + name: "multiple text contents stay glued within a message", + messages: []*message.Message{msg("a", "b")}, + want: "ab", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resp := &agent.Response{Messages: tt.messages} + if got := resp.String(); got != tt.want { + t.Errorf("String() = %q, want %q", got, tt.want) + } + }) + } +}