Skip to main content

vtcode_core/commands/
memory.rs

1//! Memory command implementation - show memory usage and pressure diagnostics
2
3use crate::memory::{MemoryMonitor, MemoryPressure, MemoryReport};
4use crate::utils::colors::style;
5use anyhow::Result;
6
7/// Handle the memory command - display memory usage and diagnostics
8pub async fn handle_memory_command() -> Result<MemoryReport> {
9    let monitor = MemoryMonitor::new();
10
11    // Generate the report
12    let report = monitor
13        .get_report()
14        .map_err(|e| anyhow::anyhow!("Failed to generate memory report: {}", e))?;
15
16    println!("{}", style("Memory Usage Report").cyan().bold());
17    display_memory_report(&report);
18
19    Ok(report)
20}
21
22/// Display memory report in human-readable format
23fn display_memory_report(report: &MemoryReport) {
24    println!("\n{} Current Memory Usage:", style("[MEMORY]").dim());
25    println!(
26        "  RSS (Resident Set): {} MB",
27        style(format!("{:.1}", report.current_rss_mb)).cyan()
28    );
29
30    println!("\n{} Thresholds:", style("[LIMITS]").dim());
31    println!(
32        "  Soft Limit: {} MB (warning level)",
33        style(format!("{:.1}", report.soft_limit_mb)).cyan()
34    );
35    println!(
36        "  Hard Limit: {} MB (critical level)",
37        style(format!("{:.1}", report.hard_limit_mb)).red()
38    );
39
40    println!("\n{} Pressure Status:", style("[PRESSURE]").dim());
41    let pressure_str = format!("{}", report.pressure);
42    let pressure_colored = match report.pressure {
43        MemoryPressure::Normal => style(pressure_str).green(),
44        MemoryPressure::Warning => style(pressure_str).red(),
45        MemoryPressure::Critical => style(pressure_str).red().bold(),
46    };
47    println!("  Level: {}", pressure_colored);
48    println!("  Description: {}", report.pressure.description());
49    println!(
50        "  Usage: {:.1}% of hard limit",
51        style(format!("{:.1}", report.usage_percent)).cyan()
52    );
53
54    println!("\n{} Recommendations:", style("[RECOMMENDATIONS]").dim());
55    match report.pressure {
56        MemoryPressure::Normal => {
57            println!("  ✓ Memory usage is healthy");
58            println!("  • Continue normal operation");
59        }
60        MemoryPressure::Warning => {
61            println!("  ⚠ Memory approaching soft limit (400 MB)");
62            println!("  • Cache TTL reduced to 2 minutes");
63            println!("  • Least-used entries being evicted");
64            println!("  • Consider reducing cache sizes if continues");
65        }
66        MemoryPressure::Critical => {
67            println!("  ⛔ CRITICAL: Memory at hard limit (600 MB)");
68            println!("  • Aggressive cache eviction active");
69            println!("  • Cache TTL reduced to 30 seconds");
70            println!("  • Immediate cleanup recommended");
71            println!("  • Risk of OOM if memory increases further");
72        }
73    }
74
75    // Display recent checkpoints if available
76    if !report.recent_checkpoints.is_empty() {
77        println!("\n{} Recent Memory Checkpoints:", style("[HISTORY]").dim());
78        for (i, checkpoint) in report.recent_checkpoints.iter().rev().take(5).enumerate() {
79            println!(
80                "  [{}] {} MB - {}",
81                i + 1,
82                style(format!(
83                    "{:.1}",
84                    checkpoint.rss_bytes as f64 / (1024.0 * 1024.0)
85                ))
86                .cyan(),
87                style(&checkpoint.label).dim()
88            );
89        }
90        if report.recent_checkpoints.len() > 5 {
91            println!(
92                "  ... and {} more checkpoint{}",
93                report.recent_checkpoints.len() - 5,
94                if report.recent_checkpoints.len() - 5 == 1 {
95                    ""
96                } else {
97                    "s"
98                }
99            );
100        }
101    }
102
103    println!("\n{} Tip:", style("[INFO]").dim());
104    println!("  Run 'cargo build --release' for optimized memory usage");
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110
111    #[test]
112    fn test_memory_command_execution() {
113        // This test would require tokio runtime or async test framework
114        // For now, we verify the command structure compiles
115        let _cmd = handle_memory_command();
116    }
117
118    #[test]
119    fn test_pressure_recommendations() {
120        // Verify that each pressure level has recommendations
121        assert!(!MemoryPressure::Normal.description().is_empty());
122        assert!(!MemoryPressure::Warning.description().is_empty());
123        assert!(!MemoryPressure::Critical.description().is_empty());
124    }
125}