Compare commits

...

1 Commits

Author SHA1 Message Date
ParthSareen f5d565c798 agent/tui: remove redundant context-window refreshes from event loop
refreshContextWindowTokens is synchronous — it blocks the Bubble Tea
Update loop with an HTTP call. It was being called on every tool start,
tool finish, run start, and run completion, even though the context
window is settled at preload time (local num_ctx from /api/ps) or is
static (cloud models). Removing these calls eliminates unnecessary
blocking network round-trips from the UI thread during agentic sessions
with many tool calls.

The preload path (chatModelPreloadDoneMsg) still resolves the
authoritative context window, so no behavior change for the user — just
fewer blocking calls in the event loop.
2026-07-17 15:54:36 -07:00
3 changed files with 7 additions and 19 deletions
+7 -5
View File
@@ -224,9 +224,11 @@ func Run(ctx context.Context, opts Options) (*Result, error) {
m.nextImageID, m.nextAudioID = nextInputAttachmentIDsFromMessages(m.messages)
m.nextPastedTextID = nextInputPastedTextIDFromMessages(m.messages)
m.entries = entriesFromMessages(m.messages)
if !m.openModelOnInit {
m.refreshContextWindowTokens(m.opts.Model)
}
// Context window is resolved post-load (chatModelPreloadDoneMsg) rather than
// here: for local models /api/ps only reports the running num_ctx after the
// model loads, and opts.ContextWindowTokens already holds Show's max as a
// pre-load fallback. Refreshing now would just re-derive that same value
// (and block construction on a network call).
m.contextTokens = m.estimatePromptTokens(m.messages, "")
m.contextEstimate = true
if m.openModelOnInit {
@@ -375,7 +377,8 @@ func (m chatModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if msg.result.WorkingDir != "" {
m.workingDir = msg.result.WorkingDir
}
m.refreshContextWindowTokens(m.responseModelName(&msg.result.Latest))
// Context window is settled by preload (local num_ctx) or is
// static (cloud); no refresh needed post-run.
m.contextTokens = m.estimatePromptTokens(m.messages, "")
m.contextEstimate = true
if !messagesEndWithCompactionResult(m.messages) {
@@ -1093,7 +1096,6 @@ func (m *chatModel) startSkillRun(name, prompt string) (tea.Model, tea.Cmd) {
}
func (m *chatModel) startRunWithMessages(displayInput, historyInput string, newMessages []api.Message, extraSystemPrompt, skillName string) (tea.Model, tea.Cmd) {
m.refreshContextWindowTokens(m.opts.Model)
m.addPromptHistory(historyInput)
m.entries = append(m.entries, newChatEntry(chatEntry{role: "user", content: displayInput}))
if len(newMessages) > 1 {
-2
View File
@@ -109,7 +109,6 @@ func (m *chatModel) applyAgentEvent(event coreagent.Event) {
contextChanged = true
case coreagent.EventToolStarted:
m.resetStreamingState()
m.refreshContextWindowTokens(m.opts.Model)
startedAt := time.Now()
idx := m.findActiveToolEntry(event.ToolCallID)
if idx < 0 {
@@ -127,7 +126,6 @@ func (m *chatModel) applyAgentEvent(event coreagent.Event) {
m.markEntryDirty(idx)
case coreagent.EventToolFinished:
m.resetStreamingState()
m.refreshContextWindowTokens(m.opts.Model)
if event.WorkingDir != "" {
m.workingDir = event.WorkingDir
}
-12
View File
@@ -1435,18 +1435,6 @@ func (m *chatModel) updateContextWindowTokens(tokens int) {
}
}
func (m chatModel) responseModelName(response *api.ChatResponse) string {
if response != nil {
if strings.TrimSpace(response.Model) != "" {
return response.Model
}
if strings.TrimSpace(response.RemoteModel) != "" {
return response.RemoteModel
}
}
return m.opts.Model
}
func (m chatModel) currentWorkingDir() string {
if strings.TrimSpace(m.workingDir) != "" {
return m.workingDir