on main help sign in
feat(chat): expandable thinking for assistant
commit4316ef3c2f6b14d242e04d569d99d4fcea829ce8 authorKujtim Hoxha <kujtimii.h@gmail.com> dateThu 18 Dec 2025, 08:44 (1 year ago) parentd5f0987
5 files changed+39−1
internal/ui/chat/assistant.go+19 internal/ui/chat/messages.go+6 internal/ui/model/chat.go+7 internal/ui/model/keys.go+5−1 internal/ui/model/ui.go+2
internal/ui/chat/assistant.go+19
@@ -230,3 +230,22 @@ func (a *AssistantMessageItem) SetMessage(message *message.Message) tea.Cmd {
230230 }
231231 return nil
232232}
233+
234+// ToggleExpanded toggles the expanded state of the thinking box.
235+func (a *AssistantMessageItem) ToggleExpanded() {
236+ a.thinkingExpanded = !a.thinkingExpanded
237+ a.clearCache()
238+}
239+
240+// HandleMouseClick implements MouseClickable.
241+func (a *AssistantMessageItem) HandleMouseClick(btn ansi.MouseButton, x, y int) bool {
242+ if btn != ansi.MouseLeft {
243+ return false
244+ }
245+ // check if the click is within the thinking box
246+ if a.thinkingBoxHeight > 0 && y < a.thinkingBoxHeight {
247+ a.ToggleExpanded()
248+ return true
249+ }
250+ return false
251+}
internal/ui/chat/messages.go+6
@@ -26,11 +26,17 @@ type Identifiable interface {
2626 ID() string
2727}
2828
29+// Animatable is an interface for items that support animation.
2930type Animatable interface {
3031 StartAnimation() tea.Cmd
3132 Animate(msg anim.StepMsg) tea.Cmd
3233}
3334
35+// Expandable is an interface for items that can be expanded or collapsed.
36+type Expandable interface {
37+ ToggleExpanded()
38+}
39+
3440// MessageItem represents a [message.Message] item that can be displayed in the
3541// UI and be part of a [list.List] identifiable by a unique ID.
3642type MessageItem interface {
internal/ui/model/chat.go+7
@@ -250,6 +250,13 @@ func (m *Chat) GetMessageItem(id string) chat.MessageItem {
250250 return item
251251}
252252
253+// ToggleExpandedSelectedItem expands the selected message item if it is expandable.
254+func (m *Chat) ToggleExpandedSelectedItem() {
255+ if expandable, ok := m.list.SelectedItem().(chat.Expandable); ok {
256+ expandable.ToggleExpanded()
257+ }
258+}
259+
253260// HandleMouseDown handles mouse down events for the chat component.
254261func (m *Chat) HandleMouseDown(x, y int) bool {
255262 if m.list.Len() == 0 {
internal/ui/model/keys.go+5−1
@@ -37,6 +37,7 @@ type KeyMap struct {
3737 End key.Binding
3838 Copy key.Binding
3939 ClearHighlight key.Binding
40+ Expand key.Binding
4041 }
4142
4243 Initialize struct {
@@ -205,7 +206,10 @@ func DefaultKeyMap() KeyMap {
205206 key.WithKeys("esc", "alt+esc"),
206207 key.WithHelp("esc", "clear selection"),
207208 )
208−
209+ km.Chat.Expand = key.NewBinding(
210+ key.WithKeys("space"),
211+ key.WithHelp("space", "expand/collapse"),
212+ )
209213 km.Initialize.Yes = key.NewBinding(
210214 key.WithKeys("y", "Y"),
211215 key.WithHelp("y", "yes"),
internal/ui/model/ui.go+2
@@ -577,6 +577,8 @@ func (m *UI) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd {
577577 m.focus = uiFocusEditor
578578 cmds = append(cmds, m.textarea.Focus())
579579 m.chat.Blur()
580+ case key.Matches(msg, m.keyMap.Chat.Expand):
581+ m.chat.ToggleExpandedSelectedItem()
580582 case key.Matches(msg, m.keyMap.Chat.Up):
581583 if cmd := m.chat.ScrollBy(-1); cmd != nil {
582584 cmds = append(cmds, cmd)