1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! Context-aware request budgets.
//!
//! A model context window is shared by input, hidden reasoning, and output.
//! Reserving the global 65,536-token output cap unchanged on a 200K route
//! leaves barely 134K for the conversation and makes every tool round collide
//! with compaction. Keep this arithmetic pure and provider-agnostic: the caller
//! supplies the active context window, and this module leaves at least 80% for
//! input while respecting the configured output ceiling.
/// Maximum share of a context window one request may reserve for output.
const OUTPUT_WINDOW_PERCENT: u32 = 20;
/// Cap `configured_max` so output cannot consume more than 20% of `context_window`.
///
/// A zero window means "unknown"; preserve the configured value rather than
/// inventing a capacity. Non-zero windows use integer arithmetic deliberately:
/// rounding down leaves the extra fraction to input headroom.
pub
/// The compaction continuation DOCUMENT budget, in tokens.
///
/// This is the size the continuation document *should* be, and the value
/// `enforce_summary_budget` trims to. It is deliberately NOT the summariser
/// request's output allowance: on providers that bill hidden reasoning inside
/// `max_output_tokens`, a request allowed only this much comes back CUT at this
/// size, with the reasoning counted inside it (#1933). The request is allowed
/// `compaction_summary_request_allowance()` instead — the document budget plus
/// a reasoning allowance — and the guard trims the result back to this budget.
///
/// The request allowance and the input-side `output_reserve` MUST derive from
/// the SAME arithmetic. When they disagree the request reserves less room than
/// the call is allowed to consume, and nothing trims the result: measured
/// 2026-10-04 the allowance was `bounded_output_tokens(65_536, 200_000)` =
/// 40 000 tokens while the reserve was a hard-coded 9 000 (4.44x), and 208 of
/// 210 live markers exceeded this budget (mean 27.8 KB, max 69.2 KB).
/// See opencrabs/opencrabs#1930.
pub const COMPACTION_SUMMARY_MAX_TOKENS: u32 = 3_000;
/// Reasoning tokens the summariser may burn INSIDE its output allowance.
///
/// On providers that bill hidden reasoning inside `max_output_tokens`, the
/// allowance bounds reasoning + visible text TOGETHER. Measured 2026-10-04
/// (#1933): a 3 000-token allowance returned `usage_output=3000,
/// usage_reasoning=1842`, so the visible document was cut to ~1 158 tokens and
/// lost its §10 fence before it was ever persisted. Sized above that
/// measurement with margin, so a full document still fits once the reasoning is
/// paid for.
pub const COMPACTION_SUMMARY_REASONING_HEADROOM_TOKENS: u32 = 2_500;
/// Headroom the summariser *prompt* needs on top of its output allowance (~1k tokens).
const COMPACTION_PROMPT_HEADROOM_TOKENS: usize = 1_000;
/// The continuation DOCUMENT budget, in tokens.
///
/// Single source for the size the document should be and the value the trim
/// guard enforces. NOT the request's output allowance — see
/// `compaction_summary_request_allowance()`.
pub
/// The summariser REQUEST's output allowance, in tokens.
///
/// The document budget PLUS a reasoning allowance: this is what is passed to
/// `LLMRequest::with_max_tokens`, and it is deliberately LARGER than the
/// document budget because reasoning is billed inside the allowance (#1933).
/// A generous request allowance is safe precisely BECAUSE
/// `enforce_summary_budget` trims the result to the DOCUMENT budget — #1930's
/// protection is intact.
///
/// Single source for BOTH call sites (background `compaction.rs`, manual
/// `/compact` in `context.rs`) so they cannot drift apart again.
pub
/// Room the input budget must reserve for the summariser call: its output
/// allowance plus the prompt headroom.
///
/// `context.rs` subtracts this from the snapshot's context window to size the
/// messages sent to the summariser. Deriving it from the same arithmetic is the
/// whole point: a reserve smaller than the allowance means the summariser is
/// handed more input than the window can hold.
pub