lean-ctx 3.1.5

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 MAVEN_DOWNLOAD_RE: OnceLock<Regex> = OnceLock::new();
static MAVEN_PROGRESS_RE: OnceLock<Regex> = OnceLock::new();
static GRADLE_DOWNLOAD_RE: OnceLock<Regex> = OnceLock::new();
static GRADLE_PROGRESS_RE: OnceLock<Regex> = OnceLock::new();
static TESTS_RUN_RE: OnceLock<Regex> = OnceLock::new();

fn maven_download_re() -> &'static Regex {
    MAVEN_DOWNLOAD_RE
        .get_or_init(|| Regex::new(r"(?i)\[INFO\]\s+(Downloading|Downloaded)\s+").unwrap())
}

fn maven_progress_re() -> &'static Regex {
    MAVEN_PROGRESS_RE.get_or_init(|| Regex::new(r"\[INFO\].*kB\s+\|").unwrap())
}

fn gradle_download_re() -> &'static Regex {
    GRADLE_DOWNLOAD_RE
        .get_or_init(|| Regex::new(r"(?i)^(Downloading|Download)\s+https?://").unwrap())
}

fn gradle_progress_re() -> &'static Regex {
    GRADLE_PROGRESS_RE.get_or_init(|| Regex::new(r"^[<>=\s]+$|^[0-9]+%\s+EXECUTING").unwrap())
}

fn tests_run_re() -> &'static Regex {
    TESTS_RUN_RE.get_or_init(|| Regex::new(r"Tests run:\s*\d+").unwrap())
}

fn is_maven_noise(line: &str) -> bool {
    let t = line.trim_start();
    if maven_download_re().is_match(t) {
        return true;
    }
    if maven_progress_re().is_match(t) {
        return true;
    }
    if t.contains("Progress (") && t.contains("):") && t.contains('%') {
        return true;
    }
    false
}

fn is_gradle_noise(line: &str) -> bool {
    let t = line.trim();
    if gradle_download_re().is_match(t) {
        return true;
    }
    if gradle_progress_re().is_match(t) {
        return true;
    }
    let tl = t.to_ascii_lowercase();
    if tl.starts_with("consider enabling configuration cache")
        || tl.contains("deprecated gradle features were used")
        || tl.starts_with("you can use '--warning-mode")
    {
        return true;
    }
    false
}

fn is_maven_or_gradle_command(command: &str) -> bool {
    let c = command.trim();
    let cl = c.to_ascii_lowercase();
    cl.starts_with("mvn ")
        || cl.starts_with("./mvnw ")
        || cl.starts_with("mvnw ")
        || cl.starts_with("gradle ")
        || cl.starts_with("./gradlew ")
        || cl.starts_with("gradlew ")
}

fn is_gradle_command(command: &str) -> bool {
    let cl = command.trim().to_ascii_lowercase();
    cl.starts_with("gradle ") || cl.starts_with("./gradlew ") || cl.starts_with("gradlew ")
}

pub fn compress(command: &str, output: &str) -> Option<String> {
    if !is_maven_or_gradle_command(command) {
        return None;
    }
    if is_gradle_command(command) {
        Some(compress_gradle(output))
    } else {
        Some(compress_maven(output))
    }
}

fn compress_maven(output: &str) -> String {
    let mut kept = Vec::new();

    for line in output.lines() {
        let t = line.trim_end();
        if t.trim().is_empty() {
            continue;
        }
        if is_maven_noise(t) {
            continue;
        }

        let tl = t.to_ascii_lowercase();
        if tl.contains("[error]")
            || tl.contains("[fatal]")
            || tl.contains("build failure")
            || tl.contains("build success")
            || tl.contains("failure!")
            || tl.contains("tests run:")
            || tl.contains("failures:")
            || tl.contains("errors:")
            || tl.contains("skipped:")
            || tests_run_re().is_match(t)
        {
            kept.push(t.trim().to_string());
            continue;
        }

        if tl.contains("[warning]") {
            kept.push(t.trim().to_string());
        }
    }

    if kept.is_empty() {
        "mvn (no build/test lines kept)".to_string()
    } else {
        kept.join("\n")
    }
}

fn compress_gradle(output: &str) -> String {
    let mut kept = Vec::new();
    let mut task_lines = Vec::new();

    for line in output.lines() {
        let t = line.trim_end();
        if t.trim().is_empty() {
            continue;
        }
        if is_gradle_noise(t) {
            continue;
        }

        let tl = t.to_ascii_lowercase();
        if tl.starts_with("> task ") {
            if tl.contains("failed")
                || tl.contains("failure")
                || tl.contains("skipped")
                || tl.contains("no-source")
            {
                task_lines.push(t.trim().to_string());
            }
            continue;
        }

        if tl.contains("actionable tasks:") {
            kept.push(t.trim().to_string());
            continue;
        }

        if tl.contains("build successful")
            || tl.contains("build failed")
            || tl.starts_with("failure:")
            || tl.contains("what went wrong:")
            || tl.contains("execution failed for task")
            || tl.contains("error:")
            || tl.contains("exception")
            || tl.contains("tests completed:")
            || (tl.contains("test ") && (tl.contains("failed") || tl.contains("passed")))
            || tl.contains("there were failing tests")
        {
            kept.push(t.trim().to_string());
        }
    }

    if !task_lines.is_empty() {
        kept.push("tasks:\n".to_string() + &task_lines.join("\n"));
    }

    if kept.is_empty() {
        "gradle (no summary kept)".to_string()
    } else {
        kept.join("\n")
    }
}