diff --git a/internal/ui/model/ui.go b/internal/ui/model/ui.go index 8ee3a36ad680ee12c2087dcc64eda6c3b6675215..a19788d7bfa5b33287a604871e1fe6b7e43f2d84 100644 --- a/internal/ui/model/ui.go +++ b/internal/ui/model/ui.go @@ -556,6 +556,11 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.WindowSizeMsg: m.width, m.height = msg.Width, msg.Height m.updateLayoutAndSize() + if m.state == uiChat && m.chat.Follow() { + if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil { + cmds = append(cmds, cmd) + } + } case tea.KeyboardEnhancementsMsg: m.keyenh = msg if msg.SupportsKeyDisambiguation() { @@ -680,7 +685,11 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { cmds = append(cmds, cmd) } if !m.chat.SelectedItemInView() { - m.chat.SelectNext() + if m.chat.AtBottom() { + m.chat.SelectLast() + } else { + m.chat.SelectNext() + } if cmd := m.chat.ScrollToSelectedAndAnimate(); cmd != nil { cmds = append(cmds, cmd) } @@ -692,6 +701,11 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if cmd := m.chat.Animate(msg); cmd != nil { cmds = append(cmds, cmd) } + if m.chat.Follow() { + if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil { + cmds = append(cmds, cmd) + } + } } case spinner.TickMsg: if m.dialog.HasDialogs() { @@ -822,7 +836,7 @@ func (m *UI) setSessionMessages(msgs []message.Message) tea.Cmd { cmds = append(cmds, cmd) } m.chat.SelectLast() - return tea.Batch(cmds...) + return tea.Sequence(cmds...) } // loadNestedToolCalls recursively loads nested tool calls for agent/agentic_fetch tools. @@ -950,7 +964,7 @@ func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd { } } } - return tea.Batch(cmds...) + return tea.Sequence(cmds...) } func (m *UI) handleClickFocus(msg tea.MouseClickMsg) (cmd tea.Cmd) { @@ -1029,16 +1043,16 @@ func (m *UI) updateSessionMessage(msg message.Message) tea.Cmd { if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil { cmds = append(cmds, cmd) } + m.chat.SelectLast() } - return tea.Batch(cmds...) + return tea.Sequence(cmds...) } // handleChildSessionMessage handles messages from child sessions (agent tools). func (m *UI) handleChildSessionMessage(event pubsub.Event[message.Message]) tea.Cmd { var cmds []tea.Cmd - atBottom := m.chat.AtBottom() // Only process messages with tool calls or results. if len(event.Payload.ToolCalls()) == 0 && len(event.Payload.ToolResults()) == 0 { return nil @@ -1118,13 +1132,14 @@ func (m *UI) handleChildSessionMessage(event pubsub.Event[message.Message]) tea. // Update the chat so it updates the index map for animations to work as expected m.chat.UpdateNestedToolIDs(toolCallID) - if atBottom { + if m.chat.Follow() { if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil { cmds = append(cmds, cmd) } + m.chat.SelectLast() } - return tea.Batch(cmds...) + return tea.Sequence(cmds...) } func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd { @@ -1804,7 +1819,7 @@ func (m *UI) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd { handleGlobalKeys(msg) } - return tea.Batch(cmds...) + return tea.Sequence(cmds...) } // drawHeader draws the header section of the UI.