magi-code 0.96.5

Repository-aware CLI coding agent for terminal work
Documentation
use super::*;

use super::super::protection::public_decision;

pub(super) fn humanize_protection_metadata(detail: Option<&ToolActivityDetail>) -> Vec<String> {
    public_decision(detail, "humanize_protection")
        .map(|(_, decision)| vec![format!("Jev: {decision}")])
        .unwrap_or_default()
}

pub(super) fn prompt_injection_protection_metadata(
    detail: Option<&ToolActivityDetail>,
) -> Option<String> {
    let protection = &detail?.metadata["prompt_injection_protection"];
    let action = match protection["action"].as_str()? {
        "allow" => "allow",
        "annotate" => "annotate",
        "quarantine" => "quarantine",
        "escalate" => "escalate",
        _ => return None,
    };
    let mode = match protection["enforced"].as_bool() {
        Some(true) => "enforced",
        Some(false) => "observe-only",
        None => "enforcement unavailable",
    };
    Some(format!("Jev: prompt injection: {action} • {mode}"))
}

pub(super) fn bash_jev_metadata(detail: Option<&ToolActivityDetail>) -> Vec<String> {
    let mut lines = humanize_protection_metadata(detail);
    if let Some((_, decision)) = public_decision(detail, "bash_protection") {
        lines.push(format!("Jev: {decision}"));
    }
    if let Some(status) =
        detail.and_then(|detail| detail.metadata["bash_file_tracking"]["status"].as_str())
    {
        let label = match status {
            "completed" => "completed",
            "command_limit" => "skipped (command limit)",
            "canceled" => "skipped (canceled)",
            "busy" => "skipped (worker busy)",
            "unavailable" => "skipped (worker unavailable)",
            "timed_out" => "timed out",
            "error" => "assessment failed",
            "redacted" => "skipped (sensitive command)",
            "unsupported" => "skipped (unsupported command)",
            "no_candidates" => "skipped (no literal paths)",
            "command_failed" => "skipped (command did not succeed)",
            _ => return lines,
        };
        lines.push(format!("Jev: file tracking • {label}"));
    }
    if let Some(activity) =
        detail.and_then(|detail| detail.metadata["inferred_file_activity"].as_array())
    {
        let mut files = std::collections::BTreeMap::<&str, u8>::new();
        for item in activity.iter().take(32) {
            let Some(path) = item["path"].as_str().filter(|path| !path.is_empty()) else {
                continue;
            };
            let bits = match item["operation"].as_str() {
                Some("read") => 1,
                Some("write") => 2,
                Some("edit") => 4,
                Some("read_write") => 3,
                _ => continue,
            };
            *files.entry(path).or_default() |= bits;
        }
        let count = |bit| files.values().filter(|bits| **bits & bit != 0).count();
        lines.push(format!(
            "Jev: file tracking • {} files inferred • R {} / W {} / E {}",
            files.len(),
            count(1),
            count(2),
            count(4)
        ));
    }
    lines
}

pub(super) fn attempted_change_preview(value: Option<&serde_json::Value>) -> Vec<String> {
    let Some(text) = value.and_then(serde_json::Value::as_str) else {
        return Vec::new();
    };
    let mut lines = text
        .lines()
        .take(TOOL_PREVIEW_LINES)
        .map(|line| truncate_preview_line(&sanitize_display_text(line), PREVIEW_LINE_MAX_CHARS))
        .collect::<Vec<_>>();
    if text.lines().count() > TOOL_PREVIEW_LINES {
        lines.push(format!(
            "… change preview limited to {TOOL_PREVIEW_LINES} lines"
        ));
    }
    lines
}
pub(super) fn bounded_preview_lines(text: &str) -> String {
    let safe = sanitize_display_text(text);
    let mut source = safe.lines();
    let mut lines = source
        .by_ref()
        .take(TOOL_PREVIEW_LINES)
        .map(|line| truncate_preview_line(line, PREVIEW_LINE_MAX_CHARS))
        .collect::<Vec<_>>();
    if source.next().is_some() {
        lines.push(format!(
            "… response preview limited to {TOOL_PREVIEW_LINES} lines"
        ));
    }
    lines.join("\n")
}

pub(in crate::output::tool_card) fn bounded_error_line(text: &str) -> String {
    let line = text
        .lines()
        .find(|line| !line.trim().is_empty())
        .unwrap_or("operation failed");
    truncate_preview_line(&sanitize_display_text(line), PREVIEW_LINE_MAX_CHARS)
}

pub(super) fn tool_was_canceled(detail: Option<&crate::output::ToolActivityDetail>) -> bool {
    detail.is_some_and(|detail| {
        detail
            .output
            .lines()
            .map(str::trim)
            .any(|line| line == "prompt canceled")
    })
}

pub(super) fn plural<'a>(count: usize, singular: &'a str, plural: &'a str) -> &'a str {
    if count == 1 { singular } else { plural }
}

// These spans describe already-sanitized adapter text, not source previews.
pub(super) fn split_role_line(
    text: &str,
    split: usize,
    prefix: TextMeaning,
    suffix: TextMeaning,
) -> TextLine {
    tool_display_line(vec![
        TextSpan::new(&text[..split], prefix),
        TextSpan::new(&text[split..], suffix),
    ])
}

pub(super) fn tool_display_line(spans: Vec<TextSpan>) -> TextLine {
    use unicode_segmentation::UnicodeSegmentation;
    let line = TextLine { spans };
    let text = line.plain_text();
    let mut boundary = 0;
    for span in line.spans.iter().take(line.spans.len().saturating_sub(1)) {
        boundary += span.text.len();
        if boundary != text.len()
            && !text
                .grapheme_indices(true)
                .any(|(index, _)| index == boundary)
        {
            // Keep combining sequences intact rather than splitting them between styles.
            return TextLine::plain(text);
        }
    }
    line
}