| 90 | } |
| 91 | |
| 92 | type Model struct { |
| 93 | Version string |
| 94 | |
| 95 | cfg *config.Config |
| 96 | cli *llm.Client |
| 97 | |
| 98 | history []chmctx.Message // full conversation minus the system prompt |
| 99 | system string // embedded system prompt + working-directory anchor |
| 100 | |
| 101 | // streaming is the live raw token buffer for the current content block, |
| 102 | // rendered above the prompt by View() while the model talks. On flush |
| 103 | // (block end, tool call, cancel, error) it's rendered through glamour, |
| 104 | // queued into outbox for tea.Println, then reset. |
| 105 | streaming *strings.Builder |
| 106 | |
| 107 | // outbox holds lines bound for terminal scrollback via tea.Println on the |
| 108 | // next Update cycle. The Update wrapper drains it every cycle, so handlers |
| 109 | // can call appendLine / flushStreaming without threading a Cmd back. |
| 110 | outbox []string |
| 111 | |
| 112 | // scroll is the in-memory transcript of every appendLine / flushStreaming |
| 113 | // line. The real scrollback lives in the user's terminal; this copy is |
| 114 | // replayed in handleResizeSettle after a width change wipes the terminal, |
| 115 | // and tests read it to verify what was emitted. |
| 116 | scroll *strings.Builder |
| 117 | |
| 118 | // reasoning accumulates the current round's chain-of-thought (EventReasoning) |
| 119 | // for the debug log only; it never enters history (see llm.EventReasoning). |
| 120 | // Pointer like streaming/scroll: Model is copied by value across bubbletea |
| 121 | // and strings.Builder must not be copied after first use. Only written when |
| 122 | // logging is on; reset every round in applyDone and on abort. |
| 123 | reasoning *strings.Builder |
| 124 | |
| 125 | ta promptInput |
| 126 | renderer *glamour.TermRenderer |
| 127 | spinner spinner.Model |
| 128 | |
| 129 | // streaming state |
| 130 | stream <-chan llm.Event |
| 131 | |
| 132 | // pending tool calls waiting to be executed after an assistant turn |
| 133 | pending []chmctx.ToolCall |
| 134 | |
| 135 | // turn-level stats (reset in finalizeTurn) + session-cumulative count |
| 136 | // (reset only by /clear, so the status bar carries the running session |
| 137 | // total). |
| 138 | turnTokens int |
| 139 | sessionTokens int |
| 140 | // turnStart stamps the wall-clock start of the current turn, set in beginTurn |
| 141 | // (the user-submit path only; tool re-entry bypasses it), so it spans every |
| 142 | // tool round rather than resetting per round. The status bar ticks |
| 143 | // liveElapsed(time.Since(turnStart)) while a turn runs. |
| 144 | turnStart time.Time |
| 145 | // last* hold the finished turn's frozen footer summary, shown at idle until |
| 146 | // the next submit: outcome marker, wall-clock duration, and the token count |
| 147 | // the avg tok/s divides by. lastTokens ÷ lastElapsed IS the displayed rate, |
| 148 | // so it stays self-verifying against the shown duration. |
| 149 | lastElapsed time.Duration |
nothing calls this directly
no outgoing calls
no test coverage detected