From 2656a188bca1a241911b9145a75290d735b82b48 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Wed, 18 Feb 2026 23:22:27 +0300 Subject: [PATCH] fix(ui): cache blurred and focused renderings separately for assistant messages (#2252) Assistant messages can have long content, and rendering them can be expensive. To improve performance, we cache the rendered content for both blurred and focused states separately. --- internal/ui/chat/assistant.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/internal/ui/chat/assistant.go b/internal/ui/chat/assistant.go index 4ce71dda2515e5489900c33eb716e1d6d884409a..603beb28e9c35ffe499dc48bd2c31e2ed2c8b128 100644 --- a/internal/ui/chat/assistant.go +++ b/internal/ui/chat/assistant.go @@ -27,6 +27,8 @@ type AssistantMessageItem struct { *highlightableMessageItem *cachedMessageItem *focusableMessageItem + blurredCache *cachedMessageItem + focusedCache *cachedMessageItem message *message.Message sty *styles.Styles @@ -40,6 +42,8 @@ func NewAssistantMessageItem(sty *styles.Styles, message *message.Message) Messa a := &AssistantMessageItem{ highlightableMessageItem: defaultHighlighter(sty), cachedMessageItem: &cachedMessageItem{}, + blurredCache: &cachedMessageItem{}, + focusedCache: &cachedMessageItem{}, focusableMessageItem: &focusableMessageItem{}, message: message, sty: sty, @@ -107,11 +111,22 @@ func (a *AssistantMessageItem) RawRender(width int) string { // Render implements MessageItem. func (a *AssistantMessageItem) Render(width int) string { - style := a.sty.Chat.Message.AssistantBlurred + cache := a.blurredCache if a.focused { - style = a.sty.Chat.Message.AssistantFocused + cache = a.focusedCache } - return style.Render(a.RawRender(width)) + + content, _, ok := cache.getCachedRender(width) + if !ok { + style := a.sty.Chat.Message.AssistantBlurred + if a.focused { + style = a.sty.Chat.Message.AssistantFocused + } + content = style.Render(a.RawRender(width)) + cache.setCachedRender(content, width, lipgloss.Height(content)) + } + + return content } // renderMessageContent renders the message content including thinking, main content, and finish reason.