lellm_agent/runtime/context/
budget.rs1use lellm_core::ContentBlock;
4
5#[derive(Debug, Clone)]
9pub struct ContextBudget {
10 pub max_tokens: usize,
15 pub warning_ratio: f32,
17 pub keep_recent_turns: usize,
19 pub max_tool_result_chars: usize,
21}
22
23impl Default for ContextBudget {
24 fn default() -> Self {
25 Self {
26 max_tokens: 128_000,
27 warning_ratio: 0.8,
28 keep_recent_turns: 5,
29 max_tool_result_chars: 4096,
30 }
31 }
32}
33
34impl ContextBudget {
35 pub fn should_compact(&self, current_tokens: usize) -> bool {
37 let threshold = (self.max_tokens as f32 * self.warning_ratio) as usize;
38 current_tokens > threshold
39 }
40
41 pub fn truncate_tool_result(&self, text: String) -> String {
43 if text.chars().count() <= self.max_tool_result_chars {
44 return text;
45 }
46 let truncated: String = text.chars().take(self.max_tool_result_chars).collect();
47 format!(
48 "{}\n[truncated, original {} chars]",
49 truncated,
50 text.chars().count()
51 )
52 }
53
54 pub fn truncate_tool_result_blocks(&self, content: &[ContentBlock]) -> Vec<ContentBlock> {
56 content
57 .iter()
58 .map(|b| match b {
59 ContentBlock::Text(t) => {
60 let truncated = self.truncate_tool_result(t.text.clone());
61 if truncated != t.text {
62 ContentBlock::Text(lellm_core::TextBlock {
63 text: truncated,
64 cache_control: None,
65 })
66 } else {
67 b.clone()
68 }
69 }
70 _ => b.clone(),
71 })
72 .collect()
73 }
74}