talos_session/
tool_compression.rs1#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct ToolOutputCompression {
10 pub model_content: String,
12 pub raw_content: Option<String>,
14 pub raw_flag: u8,
16}
17
18pub fn compress_tool_output(content: &str, threshold: usize) -> ToolOutputCompression {
27 if content.is_empty() || content.len() <= threshold {
28 return ToolOutputCompression {
29 model_content: content.to_string(),
30 raw_content: None,
31 raw_flag: 0,
32 };
33 }
34
35 let total = content.len();
36 let prefix_end = content
37 .char_indices()
38 .map(|(index, _)| index)
39 .take_while(|index| *index <= threshold)
40 .last()
41 .unwrap_or(0);
42 let summary = format!(
43 "{}\n... [truncated, {total} bytes total]",
44 &content[..prefix_end]
45 );
46
47 ToolOutputCompression {
48 model_content: summary,
49 raw_content: Some(content.to_string()),
50 raw_flag: 1,
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn under_threshold_no_compression() {
60 let result = compress_tool_output("hello world", 100);
61 assert_eq!(result.model_content, "hello world");
62 assert_eq!(result.raw_content, None);
63 assert_eq!(result.raw_flag, 0);
64 }
65
66 #[test]
67 fn over_threshold_summary_and_raw() {
68 let content = "A".repeat(200);
69 let result = compress_tool_output(&content, 50);
70
71 assert_eq!(result.raw_flag, 1);
72 assert_eq!(result.raw_content, Some(content.clone()));
73 assert_eq!(
74 result.model_content,
75 format!("{}\n... [truncated, 200 bytes total]", "A".repeat(50))
76 );
77 }
78
79 #[test]
80 fn empty_content_no_compression() {
81 let result = compress_tool_output("", 100);
82 assert_eq!(result.model_content, "");
83 assert_eq!(result.raw_content, None);
84 assert_eq!(result.raw_flag, 0);
85 }
86
87 #[test]
88 fn exactly_at_threshold_no_compression() {
89 let content = "B".repeat(50);
90 let result = compress_tool_output(&content, 50);
91 assert_eq!(result.model_content, content);
92 assert_eq!(result.raw_content, None);
93 assert_eq!(result.raw_flag, 0);
94 }
95
96 #[test]
97 fn truncation_preserves_utf8_boundaries() {
98 let result = compress_tool_output("你好世界", 5);
99 assert_eq!(result.model_content, "你\n... [truncated, 12 bytes total]");
100 assert_eq!(result.raw_content.as_deref(), Some("你好世界"));
101 }
102}