abortTurn winds down a turn that did not complete normally: flush in-flight text so the partial block lands in scrollback, post the explanatory banner, drop pending tool calls, reset per-turn counters and context. Pair to applyDone for the happy path.
(banner string)
| 847 | // drop pending tool calls, reset per-turn counters and context. Pair to |
| 848 | // applyDone for the happy path. |
| 849 | func (m *Model) abortTurn(banner string) { |
| 850 | m.flushStreaming() |
| 851 | m.reasoning.Reset() |
| 852 | if banner != "" { |
| 853 | m.appendLine(banner) |
| 854 | } |
| 855 | // A prompt queued mid-turn must NOT auto-fire on an abort: the user took back |
| 856 | // control, so its follow-up may no longer be wanted. Restore it to the |
| 857 | // textarea instead (editable, one Enter to send), which also avoids leaving an |
| 858 | // idle "queued" box that would orphan-fire after the next turn. Only when the |
| 859 | // textarea is empty, so a draft typed mid-turn isn't clobbered. |
| 860 | if m.queued != nil { |
| 861 | if m.ta.Value() == "" { |
| 862 | m.setPromptText(m.queued.send) |
| 863 | } |
| 864 | m.queued = nil |
| 865 | } |
| 866 | // finalizeTurn folds the in-flight estimate into the counters and zeroes it, |
| 867 | // so the avg counts what was generated up to the interrupt; don't drop it here. |
| 868 | m.finalizeTurn(outcomeStopped) |
| 869 | m.endTurn() // drops pending tool calls along with the rest of the turn state |
| 870 | } |
| 871 | |
| 872 | // finalizeTurn freezes the finished turn's wall-clock summary into the status |
| 873 | // bar (shown at idle until the next submit) and logs the totals. outcome is |
no test coverage detected