lean-ctx 3.1.3

Context Runtime for AI Agents with CCP. 42 MCP tools, 10 read modes, 90+ compression patterns, cross-session memory (CCP), persistent AI knowledge with temporal facts + contradiction detection, multi-agent context sharing + diaries, LITM-aware positioning, AAAK compact format, adaptive compression with Thompson Sampling bandits. Supports 24 AI tools. Reduces LLM token consumption by up to 99%.
Documentation
use regex::Regex;
use std::sync::OnceLock;

static PNPM_ADDED_RE: OnceLock<Regex> = OnceLock::new();

fn pnpm_added_re() -> &'static Regex {
    PNPM_ADDED_RE.get_or_init(|| {
        Regex::new(r"(\d+) packages? (?:are )?(?:installed|added|updated)").unwrap()
    })
}

pub fn compress(command: &str, output: &str) -> Option<String> {
    if command.contains("install") || command.contains("add") || command.contains("i ") {
        return Some(compress_install(output));
    }
    if command.contains("list") || command.contains("ls") {
        return Some(compress_list(output));
    }
    if command.contains("outdated") {
        return Some(compress_outdated(output));
    }
    if command.contains("run") || command.contains("exec") {
        return Some(compress_run(output));
    }
    if command.contains("test") {
        return Some(compress_test(output));
    }
    if command.contains("why") {
        return Some(compact_output(output, 10));
    }
    if command.contains("store") {
        return Some(compress_store(output));
    }
    None
}

fn compress_install(output: &str) -> String {
    let trimmed = output.trim();
    if trimmed.is_empty() {
        return "ok".to_string();
    }

    let mut pkg_count = 0u32;
    if let Some(caps) = pnpm_added_re().captures(trimmed) {
        pkg_count = caps[1].parse().unwrap_or(0);
    }

    let progress_free: Vec<&str> = trimmed
        .lines()
        .filter(|l| {
            let t = l.trim();
            !t.is_empty()
                && !t.starts_with("Progress:")
                && !t.starts_with("Already up to date")
                && !t.contains("Downloading")
                && !t.contains("fetched from")
        })
        .collect();

    if pkg_count > 0 {
        return format!("ok ({pkg_count} packages installed)");
    }
    if progress_free.len() <= 3 {
        return progress_free.join("\n");
    }
    format!(
        "ok\n{}",
        progress_free[progress_free.len() - 3..].join("\n")
    )
}

fn compress_list(output: &str) -> String {
    let lines: Vec<&str> = output.lines().collect();
    if lines.len() <= 5 {
        return output.to_string();
    }

    let _deps: Vec<&str> = lines
        .iter()
        .filter(|l| l.contains("dependencies:") || l.starts_with(' '))
        .copied()
        .collect();

    let top: Vec<String> = lines
        .iter()
        .filter(|l| {
            let trimmed = l.trim();
            !trimmed.is_empty()
                && (trimmed.starts_with('+')
                    || trimmed.starts_with("")
                    || trimmed.starts_with(""))
        })
        .map(|l| {
            l.replace("├──", "")
                .replace("└──", "")
                .replace("├─", "")
                .replace("└─", "")
                .trim()
                .to_string()
        })
        .collect();

    if !top.is_empty() {
        return format!("{} packages:\n{}", top.len(), top.join("\n"));
    }
    compact_output(output, 15)
}

fn compress_outdated(output: &str) -> String {
    let lines: Vec<&str> = output.lines().collect();
    if lines.len() <= 1 {
        return "all up-to-date".to_string();
    }

    let mut packages = Vec::new();
    for line in &lines[1..] {
        let parts: Vec<&str> = line.split_whitespace().collect();
        if parts.len() >= 3 {
            packages.push(format!("{}: {}{}", parts[0], parts[1], parts[2]));
        }
    }

    if packages.is_empty() {
        return "all up-to-date".to_string();
    }
    format!("{} outdated:\n{}", packages.len(), packages.join("\n"))
}

fn compress_run(output: &str) -> String {
    let lines: Vec<&str> = output
        .lines()
        .filter(|l| {
            let t = l.trim();
            !t.is_empty() && !t.starts_with(">")
        })
        .collect();

    if lines.len() <= 5 {
        return lines.join("\n");
    }
    let tail = &lines[lines.len() - 3..];
    format!("...({} lines)\n{}", lines.len(), tail.join("\n"))
}

fn compress_test(output: &str) -> String {
    compress_run(output)
}

fn compress_store(output: &str) -> String {
    let trimmed = output.trim();
    if trimmed.is_empty() {
        return "ok".to_string();
    }
    compact_output(trimmed, 5)
}

fn compact_output(text: &str, max: usize) -> String {
    let lines: Vec<&str> = text.lines().filter(|l| !l.trim().is_empty()).collect();
    if lines.len() <= max {
        return lines.join("\n");
    }
    format!(
        "{}\n... ({} more lines)",
        lines[..max].join("\n"),
        lines.len() - max
    )
}