pub const COMPACTION_BUFFER: usize = 20_000;
#[must_use]
pub fn usable_tokens(model_context: u32, max_output: u32, reserved: Option<usize>) -> usize {
if model_context == 0 {
return usize::MAX;
}
let reserved = reserved.unwrap_or_else(|| COMPACTION_BUFFER.min(max_output as usize));
let context = model_context as usize;
context
.saturating_sub(max_output as usize)
.saturating_sub(reserved)
}
#[must_use]
pub fn is_overflow(
total_tokens: usize,
model_context: u32,
max_output: u32,
auto_enabled: bool,
) -> bool {
if !auto_enabled || model_context == 0 {
return false;
}
let usable = usable_tokens(model_context, max_output, None);
total_tokens >= usable
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
#[test]
fn usable_with_typical_gpt4o() {
let usable = usable_tokens(128_000, 16_384, None);
assert_eq!(usable, 95_232);
}
#[test]
fn usable_with_large_output() {
let usable = usable_tokens(200_000, 32_000, None);
assert_eq!(usable, 148_000);
}
#[test]
fn usable_with_small_output() {
let usable = usable_tokens(8_000, 4_000, None);
assert_eq!(usable, 0);
}
#[test]
fn usable_unlimited_context() {
assert_eq!(usable_tokens(0, 16_384, None), usize::MAX);
}
#[test]
fn usable_with_explicit_reserved() {
let usable = usable_tokens(128_000, 16_384, Some(10_000));
assert_eq!(usable, 101_616);
}
#[test]
fn overflow_detected() {
assert!(!is_overflow(90_000, 128_000, 16_384, true));
assert!(is_overflow(96_000, 128_000, 16_384, true));
}
#[test]
fn overflow_skipped_when_auto_disabled() {
assert!(!is_overflow(200_000, 128_000, 16_384, false));
}
#[test]
fn overflow_skipped_when_unlimited_context() {
assert!(!is_overflow(1_000_000, 0, 16_384, true));
}
}