use serde_json::Value;
use super::ToolDefinition;
use crate::context::read_modes::estimate_tokens;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BaselinePolicy {
FullFile,
Reference,
}
const REF_CAP_K: u64 = 4;
pub fn baseline_policy(_tool_name: &str) -> BaselinePolicy {
BaselinePolicy::Reference
}
pub fn cap_baseline(policy: BaselinePolicy, full_file_tokens: u64, content_tokens: u64) -> u64 {
match policy {
BaselinePolicy::FullFile => full_file_tokens,
BaselinePolicy::Reference => full_file_tokens.min(content_tokens.saturating_mul(REF_CAP_K)),
}
}
const FRAMING_CONST: u64 = 8;
pub fn request_overhead_tokens(tool_name: &str, arguments: &Value) -> u64 {
u64::from(estimate_tokens(tool_name))
+ u64::from(estimate_tokens(&arguments.to_string()))
+ FRAMING_CONST
}
pub fn schema_overhead_tokens(definitions: &[ToolDefinition]) -> u64 {
let json = serde_json::to_string(definitions).unwrap_or_default();
u64::from(estimate_tokens(&json))
}
pub fn settle_session_debt(debt: i64, raw_delta: i64) -> (i64, u64) {
let available = raw_delta - debt;
if available >= 0 {
(0, available as u64)
} else {
(-available, 0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn variable_delivery_tools_default_to_reference() {
assert_eq!(baseline_policy("tokensave_read"), BaselinePolicy::Reference);
assert_eq!(baseline_policy("tokensave_body"), BaselinePolicy::Reference);
assert_eq!(
baseline_policy("tokensave_diff_context"),
BaselinePolicy::Reference
);
assert_eq!(baseline_policy("tokensave_diff"), BaselinePolicy::Reference);
assert_eq!(
baseline_policy("tokensave_blame"),
BaselinePolicy::Reference
);
}
#[test]
fn unknown_and_reference_tools_default_to_reference() {
assert_eq!(
baseline_policy("tokensave_dead_code"),
BaselinePolicy::Reference
);
assert_eq!(
baseline_policy("tokensave_search"),
BaselinePolicy::Reference
);
assert_eq!(
baseline_policy("tokensave_some_future_tool"),
BaselinePolicy::Reference
);
}
#[test]
fn reference_cap_is_a_no_op_when_content_matches_or_exceeds_the_file() {
let full_file_tokens = 10_000;
let content_tokens = 10_500; assert_eq!(
cap_baseline(BaselinePolicy::Reference, full_file_tokens, content_tokens),
full_file_tokens
);
}
#[test]
fn full_file_baseline_is_never_capped() {
assert_eq!(cap_baseline(BaselinePolicy::FullFile, 100_000, 10), 100_000);
}
#[test]
fn reference_baseline_is_capped_at_k_times_content() {
assert_eq!(cap_baseline(BaselinePolicy::Reference, 100_000, 10), 40);
}
#[test]
fn reference_baseline_passes_through_when_under_the_cap() {
assert_eq!(cap_baseline(BaselinePolicy::Reference, 30, 100), 30);
}
#[test]
fn reference_baseline_with_zero_content_tokens_caps_to_zero() {
assert_eq!(cap_baseline(BaselinePolicy::Reference, 100_000, 0), 0);
}
#[test]
fn request_overhead_is_never_zero() {
let overhead = request_overhead_tokens("tokensave_status", &serde_json::json!({}));
assert!(overhead >= FRAMING_CONST);
}
#[test]
fn request_overhead_grows_with_argument_size() {
let small = request_overhead_tokens("tokensave_context", &serde_json::json!({"task": "x"}));
let large = request_overhead_tokens(
"tokensave_context",
&serde_json::json!({"task": "x".repeat(1000)}),
);
assert!(large > small);
}
#[test]
fn settle_session_debt_defers_a_shortfall_instead_of_discarding_it() {
let (debt, credited) = settle_session_debt(0, -9_800);
assert_eq!(debt, 9_800);
assert_eq!(credited, 0);
}
#[test]
fn settle_session_debt_pays_down_before_crediting_anything() {
let (debt, credited) = settle_session_debt(9_800, 900);
assert_eq!(debt, 8_900);
assert_eq!(credited, 0);
}
#[test]
fn settle_session_debt_credits_the_remainder_once_debt_is_cleared() {
let (debt, credited) = settle_session_debt(100, 150);
assert_eq!(debt, 0);
assert_eq!(credited, 50);
}
#[test]
fn settle_session_debt_over_a_session_matches_the_signed_total() {
let mut debt = 0i64;
let mut total_credited = 0u64;
for raw_delta in [-1_700, 900, 900] {
let (new_debt, credited) = settle_session_debt(debt, raw_delta);
debt = new_debt;
total_credited += credited;
}
assert_eq!(debt, 0);
assert_eq!(total_credited, 100);
}
#[test]
fn schema_overhead_scales_with_definition_count() {
let def = |name: &str| ToolDefinition {
name: name.to_string(),
description: "d".repeat(100),
input_schema: serde_json::json!({}),
annotations: None,
meta: None,
};
let few = schema_overhead_tokens(&[def("a")]);
let many = schema_overhead_tokens(&[def("a"), def("b"), def("c"), def("d"), def("e")]);
assert!(many > few);
assert!(few > 0);
}
}