dbgWriteRequest records, per LLM round, what newest-first packing actually sent: how much of history survived the budget and how many tool outputs are truncated. The message bodies are already captured as user/assistant/ tool_result records, so this logs only the packing decisions those per-message
(model string, ctxSize, budget, historyLen int, packed []chmctx.Message)
| 117 | // records cannot show: what the model saw versus what was dropped. packed |
| 118 | // includes the prepended system message; historyLen is the pre-pack history. |
| 119 | func dbgWriteRequest(model string, ctxSize, budget, historyLen int, packed []chmctx.Message) { |
| 120 | if !dbgEnabled() { |
| 121 | return |
| 122 | } |
| 123 | // packed[0] is the prepended system message (buildMessages always prepends |
| 124 | // it). Count AND sum over history messages only (packed[1:]) so the token |
| 125 | // figure matches the message count and is directly comparable to budget, |
| 126 | // which is the *history* budget (ctx.Budget already subtracts the system and |
| 127 | // tool reservations). Summing the ~3k-token system prompt into a "packed=1 |
| 128 | // msgs" line would read as if that one history message were 3k tokens. |
| 129 | tokens, truncated := 0, 0 |
| 130 | for _, msg := range packed[1:] { |
| 131 | tokens += msg.Tokens() |
| 132 | if strings.Contains(msg.Content, "───── truncated:") { |
| 133 | truncated++ |
| 134 | } |
| 135 | } |
| 136 | note := "" |
| 137 | if truncated > 0 { |
| 138 | note = fmt.Sprintf(" · %d tool output(s) truncated", truncated) |
| 139 | } |
| 140 | // kept = packed minus the system message; dropped covers both budget |
| 141 | // eviction and orphan-tool drops. |
| 142 | kept := len(packed) - 1 |
| 143 | dbgWritef("request", |
| 144 | "model=%s · ctx=%d (history budget=%d) · history=%d msgs → packed=%d msgs (~%d tokens) · dropped=%d oldest%s", |
| 145 | model, ctxSize, budget, historyLen, kept, tokens, historyLen-kept, note) |
| 146 | } |
| 147 | |
| 148 | // dbgWriteMessage records a chmctx.Message readably: content and tool calls |
| 149 | // each get a labeled section. No-op when logging is off, so callers needn't guard. |
no test coverage detected