pub const MAX_PROTECTED_TURNS: usize = 8;
pub const DEFAULT_KEEP_LAST_TURNS: usize = 4;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct WindowReport {
pub kept: usize,
pub dropped: usize,
pub truncated: bool,
pub over_budget: bool,
pub dropped_tokens: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct WindowPolicy {
pub history_budget: usize,
pub keep_last_turns: usize,
}
impl WindowPolicy {
#[cfg(test)]
pub fn new(context_tokens: usize, reply_tokens: usize, reserve_tokens: usize) -> Self {
let reply = reply_tokens.max(1);
let reserve = reserve_tokens.max(reply);
let history_budget = context_tokens.saturating_sub(reserve).max(reply);
Self {
history_budget,
keep_last_turns: DEFAULT_KEEP_LAST_TURNS,
}
}
#[cfg(test)]
pub fn with_keep_last(mut self, turns: usize) -> Self {
self.keep_last_turns = turns.min(MAX_PROTECTED_TURNS);
self
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Turn {
pub role: String,
pub tokens: usize,
}
pub fn conservative_token_estimate(text: &str) -> usize {
let words = text.split_whitespace().count();
let chars = text.chars().count();
let total = words + chars * 15 / 100;
total.max(1)
}
pub fn history_budget(configured: usize, reserve: usize, actual_ctx: u32) -> usize {
let ceiling = if actual_ctx == 0 {
configured
} else {
configured.min(actual_ctx as usize)
};
ceiling.saturating_sub(reserve).max(1)
}
pub fn bound_turns<T, F>(turns: &[T], budget: usize, cost: F) -> &[T]
where
F: Fn(&T) -> usize,
{
if turns.is_empty() {
return turns;
}
let mut used = 0usize;
let mut start = turns.len();
for (i, turn) in turns.iter().enumerate().rev() {
let c = cost(turn).max(1);
if i == turns.len() - 1 {
used += c;
start = i;
continue;
}
if used + c > budget {
break;
}
used += c;
start = i;
}
&turns[start..]
}
pub fn apply(turns: &[Turn], policy: WindowPolicy) -> (Vec<Turn>, WindowReport) {
let mut report = WindowReport::default();
if turns.is_empty() {
return (Vec::new(), report);
}
let mut used = 0usize;
let mut keep_from = turns.len(); let mut over_budget = false;
for (i, turn) in turns.iter().enumerate().rev() {
let cost = turn.tokens.max(1);
let within_budget = used + cost <= policy.history_budget;
let protected = turns.len() - i <= policy.keep_last_turns;
if within_budget {
used += cost;
keep_from = i;
} else if protected {
used += cost;
keep_from = i;
over_budget = true;
} else {
break;
}
}
let kept: Vec<Turn> = turns[keep_from..].to_vec();
report.kept = kept.len();
report.dropped = turns.len() - kept.len();
report.truncated = report.dropped > 0;
report.over_budget = over_budget;
report.dropped_tokens = turns[..keep_from].iter().map(|t| t.tokens).sum();
(kept, report)
}
#[cfg(test)]
mod tests {
use super::*;
fn turns(costs: &[usize]) -> Vec<Turn> {
costs
.iter()
.enumerate()
.map(|(i, &tokens)| Turn {
role: if i % 2 == 0 {
"user".into()
} else {
"assistant".into()
},
tokens,
})
.collect()
}
#[test]
fn an_empty_history_is_untouched() {
let (kept, r) = apply(&[], WindowPolicy::new(4096, 512, 1024));
assert!(kept.is_empty());
assert!(!r.truncated);
assert_eq!(r.dropped, 0);
}
#[test]
fn a_history_that_fits_is_kept_whole() {
let t = turns(&[100, 90, 80, 70]);
let (kept, r) = apply(&t, WindowPolicy::new(4096, 512, 1024).with_keep_last(0));
assert_eq!(kept.len(), 4);
assert!(!r.truncated);
assert_eq!(r.dropped_tokens, 0);
}
#[test]
fn old_turns_are_dropped_before_recent_ones() {
let t = turns(&[500, 100, 100, 100]);
let (kept, r) = apply(
&t,
WindowPolicy {
history_budget: 300,
keep_last_turns: 0,
},
);
assert_eq!(kept.len(), 3, "the oldest turn should go first");
assert_eq!(kept[0].tokens, 100);
assert!(r.truncated);
assert_eq!(r.dropped, 1);
assert_eq!(r.dropped_tokens, 500);
}
#[test]
fn the_recent_exchange_survives_even_when_it_exceeds_the_budget() {
let t = turns(&[10, 400, 400, 400]);
let (kept, r) = apply(
&t,
WindowPolicy {
history_budget: 100,
keep_last_turns: 3,
},
);
assert_eq!(kept.len(), 3, "the protected tail must survive");
assert_eq!(
kept[0].tokens, 400,
"the protected window starts at the oldest protected turn"
);
assert!(r.over_budget, "overflow must be reported, not silent");
assert!(r.truncated);
}
#[test]
fn the_floor_never_protects_unbounded_history() {
let t = turns(&vec![200usize; 40]);
let policy = WindowPolicy::new(300, 50, 0).with_keep_last(1000);
assert_eq!(policy.keep_last_turns, MAX_PROTECTED_TURNS);
let (kept, _) = apply(&t, policy);
assert!(
kept.len() <= MAX_PROTECTED_TURNS + 1,
"protected tail was {} turns",
kept.len()
);
}
#[test]
fn a_zero_budget_cannot_silently_drop_all_history() {
let policy = WindowPolicy::new(100, 512, 4096);
assert!(policy.history_budget >= 512, "budget must stay usable");
}
#[test]
fn the_reserve_actually_reduces_the_history_budget() {
let full = WindowPolicy::new(8192, 512, 0);
let reserved = WindowPolicy::new(8192, 512, 1024);
assert_eq!(full.history_budget, 8192 - 512);
assert!(
reserved.history_budget < full.history_budget,
"a reserve must cost history something"
);
}
#[test]
fn the_reserve_defaults_to_at_least_the_reply() {
let policy = WindowPolicy::new(4096, 512, 0);
assert!(policy.history_budget <= 4096 - 512);
}
#[test]
fn dropped_tokens_are_counted_from_what_was_actually_dropped() {
let t = turns(&[100, 200, 300, 400]);
let (kept, r) = apply(
&t,
WindowPolicy {
history_budget: 400,
keep_last_turns: 0,
},
);
let dropped: usize = t.len() - kept.len();
assert_eq!(r.dropped, dropped);
assert_eq!(
r.dropped_tokens,
t[..dropped].iter().map(|x| x.tokens).sum::<usize>()
);
}
#[test]
fn a_zero_token_turn_is_treated_as_costing_something() {
let t = vec![
Turn {
role: "user".into(),
tokens: 0,
},
Turn {
role: "assistant".into(),
tokens: 0,
},
];
let (kept, r) = apply(
&t,
WindowPolicy {
history_budget: 1,
keep_last_turns: 0,
},
);
assert_eq!(kept.len(), 1, "a zero-token turn still costs something");
assert!(r.truncated);
}
#[test]
fn order_is_preserved() {
let t = turns(&[90, 80, 70, 60, 50]);
let (kept, _) = apply(
&t,
WindowPolicy {
history_budget: 150,
keep_last_turns: 1,
},
);
let kept_tokens: Vec<usize> = kept.iter().map(|x| x.tokens).collect();
let original: Vec<usize> = t.iter().map(|x| x.tokens).collect();
let start = original.len() - kept_tokens.len();
assert_eq!(
kept_tokens,
original[start..],
"must stay a contiguous suffix"
);
}
#[test]
fn history_budget_is_clamped_to_the_context_the_model_actually_runs() {
let b = history_budget(16384, 1024, 8192);
assert!(
b <= 8192,
"budget {b} exceeds the real context; long turns would 400"
);
assert_eq!(b, 7168);
}
#[test]
fn an_unknown_running_context_leaves_the_setting_alone() {
assert_eq!(history_budget(16384, 1024, 0), 15360);
}
#[test]
fn a_setting_below_the_real_context_is_respected() {
assert_eq!(history_budget(2048, 512, 8192), 1536);
}
#[test]
fn the_reserve_is_subtracted_before_the_ceiling_is_applied() {
let b = history_budget(8192, 2048, 8192);
assert_eq!(b, 6144);
assert!(b + 2048 <= 8192);
}
#[test]
fn a_reserve_larger_than_the_context_still_yields_a_usable_budget() {
let b = history_budget(1024, 4096, 1024);
assert!(b >= 1, "budget collapsed to {b}");
}
#[test]
fn the_keep_last_floor_stays_bounded() {
assert_eq!(DEFAULT_KEEP_LAST_TURNS, 4);
assert_eq!(
MAX_PROTECTED_TURNS, 8,
"the floor must stay bounded or the budget stops meaning anything"
);
}
#[test]
fn the_fallback_estimate_never_undercounts_real_tokens() {
let text = "explain the deploy pipeline in exhaustive detail. ".repeat(60);
let ws = text.split_whitespace().count();
let est = conservative_token_estimate(&text);
assert_eq!(ws, 420, "the whitespace count this replaces is 420");
assert!(
est >= 481,
"estimate {est} is below the 481 real tokens; it must be conservative"
);
}
#[test]
fn the_fallback_estimate_never_returns_zero() {
assert_eq!(conservative_token_estimate(""), 1);
}
#[test]
fn the_fallback_estimate_handles_short_text() {
assert_eq!(conservative_token_estimate("hi"), 1);
assert_eq!(conservative_token_estimate("one two three"), 4);
assert!(
conservative_token_estimate(&"word ".repeat(200))
> conservative_token_estimate(&"word ".repeat(100))
);
}
#[test]
fn bounded_turns_drops_the_oldest_when_over_budget() {
let t: Vec<usize> = vec![100, 100, 100, 100];
let kept = bound_turns(&t, 250, |x| *x);
assert_eq!(kept, &[100, 100], "oldest goes first");
assert_eq!(kept.iter().sum::<usize>(), 200);
}
#[test]
fn bounded_turns_keeps_everything_that_fits() {
let t: Vec<usize> = vec![10, 20, 30];
assert_eq!(bound_turns(&t, 100, |x| *x), &t[..]);
}
#[test]
fn bounded_turns_always_keeps_the_newest_even_when_alone_it_overflows() {
let t: Vec<usize> = vec![10, 10_000];
let kept = bound_turns(&t, 100, |x| *x);
assert_eq!(kept, &[10_000]);
}
#[test]
fn bounded_turns_is_empty_in_and_empty_out() {
let t: Vec<usize> = vec![];
assert!(bound_turns(&t, 100, |x| *x).is_empty());
}
#[test]
fn eighty_large_turns_fit_inside_a_small_budget() {
let t: Vec<String> = (0..80)
.map(|i| {
format!(
"turn {i}: {}",
"explain the deploy pipeline in detail. ".repeat(45)
)
})
.collect();
let kept = bound_turns(&t, 2048, |s| conservative_token_estimate(s));
let total: usize = kept.iter().map(|s| conservative_token_estimate(s)).sum();
assert!(total <= 2048 * 2, "bound overshot: {total} tokens");
assert!(kept.len() < 80, "nothing was dropped");
}
#[test]
fn bounded_turns_keeps_the_newest_marked_turn() {
let t: Vec<String> = (0..80).map(|i| format!("MARKER-{i}")).collect();
let kept = bound_turns(&t, 40, |s| s.len());
assert!(
kept.iter().any(|s| s == "MARKER-79"),
"the newest turn must survive"
);
assert!(
!kept.iter().any(|s| s == "MARKER-0"),
"the oldest should have been dropped"
);
}
}