finalizeTurn freezes the finished turn's wall-clock summary into the status bar (shown at idle until the next submit) and logs the totals. outcome is the finish glyph: ✓ clean, ✗ abort/stall. The bar's avg tok/s divides lastTokens by lastElapsed (wall-clock), so it stays self-verifying against the d
(outcome turnOutcome)
| 877 | // owns the run summary, and the precise wall time lands in the turn_end log. |
| 878 | // Common to every wind-down (handleStreamClosed and abortTurn both call it). |
| 879 | func (m *Model) finalizeTurn(outcome turnOutcome) { |
| 880 | if m.turnStart.IsZero() { |
| 881 | return // defensive: finalizeTurn only runs inside a turn beginTurn started |
| 882 | } |
| 883 | // Commit the in-flight round's live estimate before measuring. On a clean |
| 884 | // finish it's already 0 (applyDone folded the round into turnTokens at |
| 885 | // EventDone). But a Ctrl+C or error mid-stream interrupts before EventDone, |
| 886 | // so the cancelled round's tokens (often the whole generation) sit only in |
| 887 | // streamingEstimate; without this they'd vanish from the avg and the session |
| 888 | // total would drop backward. char/4 is the best count for a round that never |
| 889 | // reported usage. |
| 890 | m.turnTokens += m.streamingEstimate |
| 891 | m.sessionTokens += m.streamingEstimate |
| 892 | m.streamingEstimate = 0 |
| 893 | wall := time.Since(m.turnStart) |
| 894 | m.lastElapsed = wall |
| 895 | m.lastTokens = m.turnTokens |
| 896 | m.lastOutcome = outcome |
| 897 | avg := humanRate(m.turnTokens, wall) |
| 898 | if avg != "" { |
| 899 | avg = " · " + avg + " avg" |
| 900 | } |
| 901 | dbgWritef("turn_end", "%s · %s wall%s · session_total=%s", |
| 902 | humanTokens(m.turnTokens), wall.Round(time.Millisecond), avg, humanTokens(m.sessionTokens)) |
| 903 | m.turnStart = time.Time{} |
| 904 | m.turnTokens = 0 |
| 905 | } |
| 906 | |
| 907 | // handleStreamClosed drives what happens after one round's stream finishes: |
| 908 | // dispatch the next pending tool call, or, if none, finalize the turn and |