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.
This commit is contained in:
ParthSareen
2026-07-17 13:29:32 -07:00
parent 573386c35e
commit f5d565c798
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