Skip to main content

vtcode_core/core/
context_optimizer.rs

1//! Context optimization for efficient context usage.
2//!
3//! Delegates tool-result reduction to the shared harness kernel used by both harnesses.
4
5use crate::core::agent::harness_kernel::reduce_tool_result;
6
7/// Context optimization manager
8pub struct ContextOptimizer;
9
10impl ContextOptimizer {
11    /// Create a new context optimizer
12    pub fn new() -> Self {
13        Self
14    }
15
16    /// Optimize tool result with the shared reducer used by both harnesses.
17    pub fn optimize_result(&self, tool_name: &str, result: serde_json::Value) -> serde_json::Value {
18        reduce_tool_result(tool_name, result)
19    }
20}
21
22impl Default for ContextOptimizer {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31    use crate::config::constants::tools;
32    use serde_json::json;
33
34    #[tokio::test]
35    async fn test_grep_optimization() {
36        let optimizer = ContextOptimizer::new();
37
38        let matches: Vec<_> = (0..20)
39            .map(|i| json!({"line": i, "path": "src/main.rs", "text": "match"}))
40            .collect();
41        let result = json!({"matches": matches});
42
43        let optimized = optimizer.optimize_result(tools::UNIFIED_SEARCH, result);
44
45        let opt_matches = optimized["matches"].as_array().unwrap();
46        assert_eq!(opt_matches.len(), 5);
47        assert!(optimized["overflow"].is_string());
48    }
49
50    #[tokio::test]
51    async fn test_grep_deduplicates_by_path_and_line() {
52        let optimizer = ContextOptimizer::new();
53        let matches = vec![
54            json!({"line": 10, "path": "src/lib.rs", "text": "hit A"}),
55            json!({"line": 10, "path": "src/lib.rs", "text": "hit A duplicate"}),
56            json!({"line": 20, "path": "src/lib.rs", "text": "hit B"}),
57        ];
58        let result = json!({"matches": matches});
59
60        let optimized = optimizer.optimize_result(tools::UNIFIED_SEARCH, result);
61        let opt_matches = optimized["matches"].as_array().unwrap();
62        assert_eq!(opt_matches.len(), 2);
63        assert_eq!(optimized["total"], 2);
64        assert!(optimized["note"].as_str().unwrap().contains("unique"));
65    }
66
67    #[tokio::test]
68    async fn test_list_files_optimization() {
69        let optimizer = ContextOptimizer::new();
70
71        let files: Vec<_> = (0..100).map(|i| json!(format!("file{}.rs", i))).collect();
72        let result = json!({"files": files});
73
74        let optimized = optimizer.optimize_result(tools::UNIFIED_SEARCH, result);
75
76        assert_eq!(optimized["total_files"], 100);
77        assert!(optimized["sample"].is_array());
78        assert!(optimized["note"].is_string());
79    }
80
81    #[tokio::test]
82    async fn test_unified_exec_output_optimization_with_output_field() {
83        let optimizer = ContextOptimizer::new();
84        let long_output = (0..2505)
85            .map(|i| format!("line-{i}"))
86            .collect::<Vec<_>>()
87            .join("\n");
88        let result = json!({
89            "command": "ls -la",
90            "output": long_output,
91            "exit_code": 0,
92            "is_exited": true
93        });
94
95        let optimized = optimizer.optimize_result(tools::UNIFIED_EXEC, result);
96        assert_eq!(optimized["is_truncated"], true);
97        assert!(optimized["output"].as_str().unwrap().lines().count() <= 2000);
98    }
99}