Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 31 additions & 42 deletions pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log/slog"
"os/exec"
"slices"
"strings"
"time"

Expand Down Expand Up @@ -410,10 +411,8 @@ func (a *App) trackCustomModel(modelRef string) {
}

// Check if already tracked
for _, existing := range a.session.CustomModelsUsed {
if existing == modelRef {
return
}
if slices.Contains(a.session.CustomModelsUsed, modelRef) {
return
}

a.session.CustomModelsUsed = append(a.session.CustomModelsUsed, modelRef)
Expand Down Expand Up @@ -508,56 +507,46 @@ func (a *App) applySessionModelOverrides(ctx context.Context, sess *session.Sess
func (a *App) throttleEvents(ctx context.Context, in <-chan tea.Msg) <-chan tea.Msg {
out := make(chan tea.Msg, 128)

go func() {
defer close(out)

var buffer []tea.Msg
ticker := time.NewTicker(a.throttleDuration)
defer ticker.Stop()
var buffer []tea.Msg
var timerCh <-chan time.Time

flush := func() {
if len(buffer) == 0 {
flush := func() {
for _, msg := range a.mergeEvents(buffer) {
select {
case out <- msg:
case <-ctx.Done():
return
}

// Merge events if possible
merged := a.mergeEvents(buffer)
for _, msg := range merged {
select {
case out <- msg:
case <-ctx.Done():
return
}
}
buffer = buffer[:0]
}

buffer = buffer[:0]
timerCh = nil
}
defer flush()

go func() {
defer close(out)

for {
select {
case <-ctx.Done():
flush()
return

case msg, ok := <-in:
if !ok {
flush()
return
}

// Check if this event type should be throttled
buffer = append(buffer, msg)
if a.shouldThrottle(msg) {
buffer = append(buffer, msg)
} else {
// Pass through immediately for important events
flush() // Flush any buffered events first
select {
case out <- msg:
case <-ctx.Done():
return
if timerCh == nil {
timerCh = time.After(a.throttleDuration)
}
} else {
flush()
}

case <-ticker.C:
case <-timerCh:
flush()
}
}
Expand Down Expand Up @@ -631,14 +620,14 @@ func (a *App) mergeEvents(events []tea.Msg) []tea.Msg {

case *runtime.PartialToolCallEvent:
// For PartialToolCallEvent, keep only the latest one per tool call ID
// Check if there's a newer one in the buffer
// Only merge consecutive events with the same ID
latest := ev
for j := i + 1; j < len(events); j++ {
if next, ok := events[j].(*runtime.PartialToolCallEvent); ok {
if next.ToolCall.ID == ev.ToolCall.ID {
latest = next
i = j // Skip to this position
}
for i+1 < len(events) {
if next, ok := events[i+1].(*runtime.PartialToolCallEvent); ok && next.ToolCall.ID == ev.ToolCall.ID {
latest = next
i++
} else {
break
}
}
result = append(result, latest)
Expand Down
5 changes: 1 addition & 4 deletions pkg/tui/components/sidebar/sidebar.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,10 +366,7 @@ func (m *model) Update(msg tea.Msg) (layout.Model, tea.Cmd) {
cmds = append(cmds, cmd)
}

if len(cmds) > 0 {
return m, tea.Batch(cmds...)
}
return m, nil
return m, tea.Batch(cmds...)
}
}

Expand Down
20 changes: 6 additions & 14 deletions pkg/tui/page/chat/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,6 @@ func (p *chatPage) Init() tea.Cmd {

// Update handles messages and updates the page state
func (p *chatPage) Update(msg tea.Msg) (layout.Model, tea.Cmd) {
var cmds []tea.Cmd

switch msg := msg.(type) {
case tea.KeyboardEnhancementsMsg:
// Track keyboard enhancement support and update help text
Expand All @@ -277,24 +275,20 @@ func (p *chatPage) Update(msg tea.Msg) (layout.Model, tea.Cmd) {
return p, editorCmd

case tea.WindowSizeMsg:
cmd := p.SetSize(msg.Width, msg.Height)
cmds = append(cmds, cmd)
cmdSize := p.SetSize(msg.Width, msg.Height)

// Forward to sidebar component
sidebarModel, sidebarCmd := p.sidebar.Update(msg)
p.sidebar = sidebarModel.(sidebar.Model)
cmds = append(cmds, sidebarCmd)

// Forward to chat component
chatModel, chatCmd := p.messages.Update(msg)
p.messages = chatModel.(messages.Model)
cmds = append(cmds, chatCmd)

// Forward to editor component
editorModel, editorCmd := p.editor.Update(msg)
p.editor = editorModel.(editor.Editor)
cmds = append(cmds, editorCmd)
return p, tea.Batch(cmds...)
return p, tea.Batch(cmdSize, sidebarCmd, chatCmd, editorCmd)

case tea.KeyPressMsg:
if model, cmd, handled := p.handleKeyPress(msg); handled {
Expand Down Expand Up @@ -351,23 +345,21 @@ func (p *chatPage) Update(msg tea.Msg) (layout.Model, tea.Cmd) {

sidebarModel, sidebarCmd := p.sidebar.Update(msg)
p.sidebar = sidebarModel.(sidebar.Model)
cmds = append(cmds, sidebarCmd)

chatModel, chatCmd := p.messages.Update(msg)
p.messages = chatModel.(messages.Model)
cmds = append(cmds, chatCmd)

editorModel, editorCmd := p.editor.Update(msg)
p.editor = editorModel.(editor.Editor)
cmds = append(cmds, editorCmd)

var cmdSpinner tea.Cmd
if p.working {
model, cmd := p.spinner.Update(msg)
var model layout.Model
model, cmdSpinner = p.spinner.Update(msg)
p.spinner = model.(spinner.Spinner)
cmds = append(cmds, cmd)
}

return p, tea.Batch(cmds...)
return p, tea.Batch(sidebarCmd, chatCmd, editorCmd, cmdSpinner)
}

func (p *chatPage) setWorking(working bool) tea.Cmd {
Expand Down
11 changes: 3 additions & 8 deletions pkg/tui/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,18 +377,13 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return a, dialogCmd
}

var cmds []tea.Cmd
var cmd tea.Cmd

updated, cmd := a.completions.Update(msg)
cmds = append(cmds, cmd)
updated, cmdCompletions := a.completions.Update(msg)
a.completions = updated.(completion.Manager)

updated, cmd = a.chatPage.Update(msg)
cmds = append(cmds, cmd)
updated, cmdChatPage := a.chatPage.Update(msg)
a.chatPage = updated.(chat.Page)

return a, tea.Batch(cmds...)
return a, tea.Batch(cmdCompletions, cmdChatPage)
}
}

Expand Down