use lellm_core::ContentBlock;
#[derive(Debug, Clone)]
pub struct ContextBudget {
pub max_tokens: usize,
pub warning_ratio: f32,
pub keep_recent_turns: usize,
pub max_tool_result_chars: usize,
}
impl Default for ContextBudget {
fn default() -> Self {
Self {
max_tokens: 128_000,
warning_ratio: 0.8,
keep_recent_turns: 5,
max_tool_result_chars: 4096,
}
}
}
impl ContextBudget {
pub fn should_compact(&self, current_tokens: usize) -> bool {
let threshold = (self.max_tokens as f32 * self.warning_ratio) as usize;
current_tokens > threshold
}
pub fn truncate_tool_result(&self, text: String) -> String {
if text.chars().count() <= self.max_tool_result_chars {
return text;
}
let truncated: String = text.chars().take(self.max_tool_result_chars).collect();
format!(
"{}\n[truncated, original {} chars]",
truncated,
text.chars().count()
)
}
pub fn truncate_tool_result_blocks(&self, content: &[ContentBlock]) -> Vec<ContentBlock> {
content
.iter()
.map(|b| match b {
ContentBlock::Text(t) => {
let truncated = self.truncate_tool_result(t.text.clone());
if truncated != t.text {
ContentBlock::Text(lellm_core::TextBlock { text: truncated })
} else {
b.clone()
}
}
_ => b.clone(),
})
.collect()
}
}