#![allow(dead_code)]
pub(crate) fn archived_budget(
context_budget: usize,
core: usize,
tools: usize,
tail: usize,
current_reserve: usize,
output_reserve: usize,
safety_margin: f64,
) -> usize {
let evictable =
context_budget.saturating_sub(core + tools + tail + current_reserve + output_reserve);
((evictable as f64) * (1.0 - safety_margin)) as usize
}
pub(crate) fn low_water(archived_budget: usize) -> usize {
(archived_budget as f64 * 0.60) as usize
}
pub(crate) struct RenderedTurn {
pub turn_seq: i64,
pub est_tokens: usize,
}
pub(crate) struct EvictionPlan {
pub new_anchor_turn_seq: i64, pub kept_est_tokens: usize,
pub evicted_count: usize,
pub degenerate: bool, }
pub(crate) fn plan_eviction(turns: &[RenderedTurn], archived_budget: usize) -> EvictionPlan {
let total: usize = turns.iter().map(|t| t.est_tokens).sum();
if archived_budget == 0 {
let anchor = turns.last().map(|t| t.turn_seq + 1).unwrap_or(0); return EvictionPlan {
new_anchor_turn_seq: anchor,
kept_est_tokens: 0,
evicted_count: turns.len(),
degenerate: true,
};
}
if total <= archived_budget {
let anchor = turns.first().map(|t| t.turn_seq).unwrap_or(0);
return EvictionPlan {
new_anchor_turn_seq: anchor,
kept_est_tokens: total,
evicted_count: 0,
degenerate: false,
};
}
let lw = low_water(archived_budget);
let mut kept: usize = total;
let mut evicted = 0;
for t in turns {
if kept <= lw {
break;
}
kept -= t.est_tokens;
evicted += 1;
}
let anchor = turns.get(evicted).map(|t| t.turn_seq).unwrap_or(0);
EvictionPlan {
new_anchor_turn_seq: anchor,
kept_est_tokens: kept,
evicted_count: evicted,
degenerate: false,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn archived_budget_and_low_water() {
let b = archived_budget(
32000, 4000, 3000, 2000,
4000, 1536,
0.10,
);
assert_eq!(b, 15717);
assert_eq!(low_water(b), (b as f64 * 0.60) as usize); }
#[test]
fn evict_oldest_until_low_water() {
let budget = 1000usize;
let turns = vec![
RenderedTurn {
turn_seq: 1,
est_tokens: 400,
},
RenderedTurn {
turn_seq: 2,
est_tokens: 400,
},
RenderedTurn {
turn_seq: 3,
est_tokens: 400,
},
RenderedTurn {
turn_seq: 4,
est_tokens: 400,
}, ];
let plan = plan_eviction(&turns, budget);
assert_eq!(plan.evicted_count, 3);
assert_eq!(plan.kept_est_tokens, 400);
assert!(plan.kept_est_tokens <= low_water(budget));
assert_eq!(plan.new_anchor_turn_seq, 4); assert!(!plan.degenerate);
}
#[test]
fn degenerate_zero_archived_when_non_evictable_exceeds_budget() {
let b = archived_budget(8000, 5000, 2000, 1500, 1000, 1536, 0.10);
assert_eq!(b, 0);
let plan = plan_eviction(
&[RenderedTurn {
turn_seq: 1,
est_tokens: 100,
}],
b,
);
assert_eq!(plan.kept_est_tokens, 0, "zero archived turns carried");
assert!(
plan.degenerate,
"degenerate flag set for warn! at the call site"
);
}
}