diff --git a/pkg/tui/views/chat/update.go b/pkg/tui/views/chat/update.go index 9b58a3e..be314dc 100644 --- a/pkg/tui/views/chat/update.go +++ b/pkg/tui/views/chat/update.go @@ -93,7 +93,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { // append chunk to existing message m.setMessageContents(last, m.messages[last].Content+msg.Content) } else { - // use chunk in new message + // use chunk in a new message m.addMessage(api.Message{ Role: api.MessageRoleAssistant, Content: msg.Content, @@ -177,6 +177,8 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { case cursor.BlinkMsg: if m.state == pendingResponse { // ensure we show the updated "wait for response" cursor blink state + last := len(m.messages)-1 + m.messageCache[last] = m.renderMessage(last) m.updateContent() } case msgConversationPersisted: diff --git a/pkg/tui/views/chat/view.go b/pkg/tui/views/chat/view.go index 40a1463..30ca344 100644 --- a/pkg/tui/views/chat/view.go +++ b/pkg/tui/views/chat/view.go @@ -124,6 +124,9 @@ func (m *Model) renderMessageHeading(i int, message *api.Message) string { return messageHeadingStyle.Render(prefix + user + suffix) } +// renderMessages renders the message at the given index as it should be shown +// *at this moment* - we render differently depending on the current application +// state (window size, etc, etc). func (m *Model) renderMessage(i int) string { msg := &m.messages[i] @@ -138,8 +141,11 @@ func (m *Model) renderMessage(i int) string { } } - // Show the assistant's cursor - if m.state == pendingResponse && i == len(m.messages)-1 && msg.Role == api.MessageRoleAssistant { + isLast := i == len(m.messages)-1 + isAssistant := msg.Role == api.MessageRoleAssistant + + if m.state == pendingResponse && isLast && isAssistant { + // Show the assistant's cursor sb.WriteString(m.replyCursor.View()) } @@ -236,22 +242,14 @@ func (m *Model) conversationMessagesView() string { sb.WriteString("\n") lineCnt += lipgloss.Height(heading) - var rendered string - if m.state == pendingResponse && i == len(m.messages)-1 { - // do a direct render of final (assistant) message to handle the - // assistant cursor blink - rendered = m.renderMessage(i) - } else { - rendered = m.messageCache[i] - } - + rendered := m.messageCache[i] sb.WriteString(rendered) sb.WriteString("\n") lineCnt += lipgloss.Height(rendered) } // Render a placeholder for the incoming assistant reply - if m.state == pendingResponse && (len(m.messages) == 0 || m.messages[len(m.messages)-1].Role != api.MessageRoleAssistant) { + if m.state == pendingResponse && m.messages[len(m.messages)-1].Role != api.MessageRoleAssistant { heading := m.renderMessageHeading(-1, &api.Message{ Role: api.MessageRoleAssistant, })