lean-ctx 3.9.16

Context Runtime for AI Agents with CCP. 71 MCP tools, 10 read modes, 95+ compression patterns, cross-session memory (CCP), persistent AI knowledge with temporal facts + contradiction detection, multi-agent context sharing, 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 std::path::PathBuf;

use super::{apply_or_report, parse_flag};

pub(super) fn cmd_pack_send(args: &[String], project_root: &str) {
    use crate::core::a2a_transport::{
        AgentIdentityV1, TransportContentType, TransportEnvelopeV1, serialize_envelope,
    };

    let file: Option<String> = args
        .iter()
        .find(|a| crate::core::contracts::is_package_file(std::path::Path::new(a.as_str())))
        .cloned();
    let target_url = parse_flag(args, "--target");
    let recipient = parse_flag(args, "--to");
    let secret = parse_flag(args, "--secret");

    let Some(f) = file else {
        eprintln!(
            "Usage: lean-ctx pack send <file.{ext}> [--target <url>] [--to <agent>] [--secret <key>]",
            ext = crate::core::contracts::PACKAGE_EXTENSION
        );
        return;
    };
    let pkg_file = PathBuf::from(f);

    let content = match std::fs::read_to_string(&pkg_file) {
        Ok(c) => c,
        Err(e) => {
            eprintln!("Error reading {}: {e}", pkg_file.display());
            return;
        }
    };

    let sender = AgentIdentityV1::from_current("cli", "lean-ctx-cli");
    let mut envelope = TransportEnvelopeV1::new(
        sender,
        recipient.as_deref(),
        TransportContentType::ContextPackage,
        content,
    );
    envelope
        .metadata
        .insert("source_file".to_string(), pkg_file.display().to_string());

    {
        use sha2::{Digest, Sha256};
        let hash =
            crate::core::agent_identity::hex_encode(&Sha256::digest(project_root.as_bytes()));
        envelope
            .metadata
            .insert("project_root_hash".to_string(), hash[..16].to_string());
    }

    if let Some(ref s) = secret {
        envelope.sign(s.as_bytes());
    }

    let json = match serialize_envelope(&envelope) {
        Ok(j) => j,
        Err(e) => {
            eprintln!("Error serializing envelope: {e}");
            return;
        }
    };

    if let Some(ref url) = target_url {
        let endpoint = format!("{}/v1/a2a/handoff", url.trim_end_matches('/'));
        let body = json.as_bytes().to_vec();
        match ureq::post(&endpoint)
            .header("Content-Type", "application/json")
            .send(&body)
        {
            Ok(resp) => {
                let status = resp.status();
                if (200..300).contains(&status.as_u16()) {
                    eprintln!("Sent to {endpoint} — HTTP {status}");
                } else {
                    eprintln!("ERROR: server returned HTTP {status} for {endpoint}");
                }
            }
            Err(e) => eprintln!("Send failed: {e}"),
        }
    } else {
        let out_path = pkg_file.with_extension(format!(
            "{}.envelope.json",
            crate::core::contracts::PACKAGE_EXTENSION
        ));
        match std::fs::write(&out_path, &json) {
            Ok(()) => eprintln!("Envelope written: {}", out_path.display()),
            Err(e) => eprintln!("Write failed: {e}"),
        }
    }
}

pub(super) fn cmd_pack_receive(args: &[String], project_root: &str) {
    use crate::core::a2a_transport::{TransportContentType, parse_envelope};

    let file: Option<String> = args
        .iter()
        .find(|a| {
            let p = std::path::Path::new(a.as_str());
            p.extension()
                .and_then(|ext| ext.to_str())
                .is_some_and(|ext| ext == "json" || crate::core::contracts::is_package_file(p))
        })
        .cloned();
    let secret = parse_flag(args, "--secret");
    let apply = args.iter().any(|a| a == "--apply");

    let Some(f) = file else {
        eprintln!("Usage: lean-ctx pack receive <envelope.json> [--secret <key>] [--apply]");
        return;
    };
    let envelope_file = PathBuf::from(f);

    let json = match std::fs::read_to_string(&envelope_file) {
        Ok(c) => c,
        Err(e) => {
            eprintln!("Error reading {}: {e}", envelope_file.display());
            return;
        }
    };

    let envelope = match parse_envelope(&json) {
        Ok(env) => env,
        Err(e) => {
            eprintln!("Error parsing envelope: {e}");
            return;
        }
    };

    if let Some(ref s) = secret {
        if !envelope.verify_signature(s.as_bytes()) {
            eprintln!("ERROR: Signature verification failed. Envelope may be tampered.");
            return;
        }
        eprintln!("Signature verified.");
    } else if envelope.signature.is_some() {
        eprintln!("WARNING: Envelope is signed but no --secret provided. Skipping verification.");
    }

    eprintln!(
        "Received from: {} ({})",
        envelope.sender.agent_id, envelope.sender.agent_type
    );
    eprintln!("Content type: {:?}", envelope.content_type);
    eprintln!("Payload size: {} bytes", envelope.payload_json.len());

    match envelope.content_type {
        TransportContentType::ContextPackage => {
            let tmp = std::env::temp_dir().join(format!(
                "lean-ctx-received-{}.{}",
                std::process::id(),
                crate::core::contracts::PACKAGE_EXTENSION
            ));
            if let Err(e) = std::fs::write(&tmp, &envelope.payload_json) {
                eprintln!("Error writing temp file: {e}");
                return;
            }
            if apply {
                let registry = match crate::core::context_package::LocalRegistry::open() {
                    Ok(r) => r,
                    Err(e) => {
                        eprintln!("ERROR: {e}");
                        return;
                    }
                };
                match registry.import_from_file(&tmp) {
                    Ok(manifest) => {
                        eprintln!("Imported: {} v{}", manifest.name, manifest.version);
                        apply_or_report(&manifest.name, &manifest.version, project_root);
                    }
                    Err(e) => eprintln!("ERROR: import failed: {e}"),
                }
            } else {
                eprintln!("Package saved to {}. Use --apply to import.", tmp.display());
            }
        }
        TransportContentType::HandoffBundle => {
            let out_path = std::path::Path::new(project_root)
                .join(".lean-ctx")
                .join("handoffs")
                .join("received-bundle.json");
            if let Some(parent) = out_path.parent() {
                let _ = std::fs::create_dir_all(parent);
            }
            match std::fs::write(&out_path, &envelope.payload_json) {
                Ok(()) => eprintln!("Handoff bundle saved: {}", out_path.display()),
                Err(e) => eprintln!("Write failed: {e}"),
            }
        }
        _ => {
            eprintln!(
                "Content type {:?} — payload printed to stdout.",
                envelope.content_type
            );
            println!("{}", envelope.payload_json);
        }
    }
}