MCPcopy Create free account
hub / github.com/codehamr/codehamr / update

Method update

internal/tui/model.go:391–507  ·  view source on GitHub ↗
(msg tea.Msg)

Source from the content-addressed store, hash-verified

389
390// eraseScrollback wipes the terminal's saved-lines buffer (DECSED 3); no
391// tea.ClearScreen equivalent clears scrollback.
392var eraseScrollback tea.Cmd = func() tea.Msg {
393 os.Stdout.WriteString(ansi.EraseDisplay(3))
394 return nil
395}
396
397// pingMsg carries a backend-reachability result. baseURL is the URL probed;
398// Update drops the message when it no longer matches the live client's URL,
399// else a stale ping from the prior profile (a mid-flight /models switch) would
400// overwrite connected state with the wrong endpoint's reachability.
401type pingMsg struct {
402 ok bool
403 baseURL string
404}
405
406// quitArmResetMsg fires ~3s after Ctrl+C arms the quit: if not already quit or
407// re-armed, clear the hint from the status bar.
408type quitArmResetMsg struct{}
409
410func (m Model) Init() tea.Cmd {
411 // Keyed (cloud) profiles get a silent Probe at startup so the status bar
412 // renders the live budget / context window from the first frame. Keyless
413 // (local Ollama) profiles get the cheaper Reachable ping: no headers to
414 // harvest, so a full probe would buy nothing.
415 connectivity := pingBackend(m.cli.BaseURL)
416 if p := m.cfg.ActiveProfile(); p != nil && p.ResolvedKey() != "" {
417 connectivity = probeBackend(m.cli, m.cfg.Active, true)
418 }
419 return tea.Batch(
420 textarea.Blink,
421 m.spinner.Tick,
422 connectivity,
423 )
424}
425
426// Update is the bubbletea entry point: it dispatches to update()'s typed
427// handlers then drains the outbox into a single tea.Println, so lines land in
428// scrollback in the exact order appendLine / flushStreaming queued them. One
429// Println per cycle, never a Batch; Batch runs children concurrently, leaving
430// arrival order undefined, so splash lines and tool-call banners would shuffle.
431func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
432 next, cmd := m.update(msg)
433 nm := next.(Model)
434 if len(nm.outbox) > 0 {
435 printCmd := tea.Println(wrapForScrollback(strings.Join(nm.outbox, "\n"), nm.width))
436 nm.outbox = nil
437 cmd = tea.Batch(printCmd, cmd)
438 }
439 return nm, cmd
440}
441
442func (m Model) update(msg tea.Msg) (tea.Model, tea.Cmd) {
443 switch msg := msg.(type) {
444 case tea.FocusMsg, tea.BlurMsg:
445 // Terminal focus reports (CSI I / CSI O) arrive as these typed msgs
446 // under tea.WithReportFocus. Swallow them so they never reach
447 // textarea.Update; otherwise the escape fragments get parsed as
448 // printable runes, inserted into the prompt, and bloat textarea height

Callers 2

UpdateMethod · 0.95

Calls 15

preGrowTextareaMethod · 0.95
handleKeyMethod · 0.95
recomputeLayoutMethod · 0.95
handleWindowSizeMethod · 0.95
handleResizeSettleMethod · 0.95
handleProbeMethod · 0.95
handleStreamMethod · 0.95
handleStreamClosedMethod · 0.95
recordToolOutcomeMethod · 0.95
dispatchNextToolMethod · 0.95
maybeFailureNudgeMethod · 0.95
maybeRunawayNudgeMethod · 0.95

Tested by 1