From e76f5f3d451d2c883aa20d5718c1f65b53e28cca Mon Sep 17 00:00:00 2001 From: Ed Zynda Date: Tue, 31 Mar 2026 17:43:50 +0300 Subject: [PATCH] fix: prevent duplicate text when flushing streaming content before tool calls flushStreamContent() was creating a new StyledMessageItem when tool calls started, but we already had a StreamingMessageItem with the same content. Now we: - Mark the existing StreamingMessageItem as complete - Only create a new message as fallback if no streaming item exists This fixes text duplication when assistant messages precede tool calls. --- internal/ui/model.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/internal/ui/model.go b/internal/ui/model.go index aa01f61e..f7b222f8 100644 --- a/internal/ui/model.go +++ b/internal/ui/model.go @@ -2958,14 +2958,21 @@ func (m *AppModel) flushStreamContent() { } m.stream.Reset() - // Render styled content using MessageRenderer - styledMsg := m.renderer.RenderAssistantMessage(content, time.Now(), m.modelName) + // Mark the existing StreamingMessageItem as complete instead of creating a new one. + // The StreamingMessageItem already has the content from appendStreamingChunk(). + if len(m.messages) > 0 { + if streamMsg, ok := m.messages[len(m.messages)-1].(*StreamingMessageItem); ok { + streamMsg.MarkComplete() + m.refreshContent() + return + } + } - // Add to in-memory scrollList as a completed assistant message with styled content + // Fallback: If no StreamingMessageItem exists (shouldn't happen), create a new styled message. + // This handles edge cases where flushStreamContent is called without streaming. + styledMsg := m.renderer.RenderAssistantMessage(content, time.Now(), m.modelName) msg := NewStyledMessageItem(generateMessageID(), "assistant", content, styledMsg.Content) m.messages = append(m.messages, msg) - - // Refresh ScrollList content m.refreshContent() // Also append to legacy buffer for compatibility