handleStream dispatches one llm.Event to the matching apply* helper and re-arms the stream reader; EventError unwinds the turn instead of looping. Events arriving after cancellation are drained quietly; acting on them would corrupt scroll (EventContent), re-populate pending (EventToolCall), or credi
(e llm.Event)
| 712 | m.pending = nil |
| 713 | m.toolRounds = 0 |
| 714 | m.turnActed = false |
| 715 | m.llmRounds = 0 |
| 716 | m.lastRunawayRound = 0 |
| 717 | m.streamReplays = 0 |
| 718 | m.emptyNudged = false |
| 719 | m.verifyNudged = false |
| 720 | // The queue-refusal hint says "send it when the turn ends"; that moment is |
| 721 | // now, so the advice would be stale from the next render on. |
| 722 | if m.status == queueSlashHint { |
| 723 | m.status = "" |
| 724 | } |
| 725 | // A retry hint dies with its turn: a Ctrl+C during the backoff wait would |
| 726 | // otherwise leave "retry 1/3 in 15s" stranded in the idle status bar. |
| 727 | if m.retrying { |
| 728 | m.retrying = false |
| 729 | m.status = "" |
| 730 | } |
| 731 | } |
| 732 | |
| 733 | // minUsableBudget is the history budget below which the agent is effectively |
| 734 | // amnesiac: Pack keeps little beyond the newest message, so every round |
| 735 | // forgets the last. Budget(8192) is already 0 and Budget(16384) ~5k, so this |
| 736 | // fires only on genuinely misconfigured small windows. |
| 737 | const minUsableBudget = 4096 |
| 738 | |
| 739 | func (m *Model) buildMessages() []chmctx.Message { |
| 740 | ctxSize := m.activeContextSize() |
| 741 | budget := chmctx.Budget(ctxSize) |
| 742 | if budget < minUsableBudget && !m.budgetFloorWarned { |
| 743 | m.budgetFloorWarned = true |
| 744 | m.appendLine(styleError.Render(fmt.Sprintf( |
| 745 | "⚠ context_size %d leaves only %d tokens for history after fixed reservations - the agent will forget almost everything between rounds. Raise context_size in .codehamr/config.yaml (and the server's real window) to 32768+.", |
| 746 | ctxSize, budget))) |
| 747 | } |
| 748 | r := chmctx.Pack(m.history, budget) |
| 749 | out := make([]chmctx.Message, 0, len(r.Messages)+1) |
| 750 | out = append(out, chmctx.Message{Role: chmctx.RoleSystem, Content: m.system}) |
| 751 | out = append(out, r.Messages...) |
| 752 | est := 0 |
| 753 | for i := range out { |
| 754 | est += out[i].Tokens() |