magi-code 0.96.1

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

pub(super) fn find_card(
    state: &MissionControlState,
    id: TranscriptCardId,
    link: Option<TranscriptActivityLink>,
) -> TranscriptCard {
    const DEFAULT_LIMIT: usize = 50;
    let node = link
        .as_ref()
        .and_then(|link| state.nodes.get(&link.activity_id));
    let detail = node.and_then(|node| node.tool_detail.as_ref());
    let status = node
        .map(|node| transcript_status_from_activity(node.status))
        .or_else(|| detail.map(|detail| transcript_status_from_activity(detail.status)))
        .unwrap_or_else(|| transcript_tool_status(state, id.entry_index));
    let query = find_metadata_str(detail, "query")
        .or_else(|| find_param(detail, "query"))
        .unwrap_or("");
    let path = find_param(detail, "path").unwrap_or(".");
    let kind = find_param(detail, "kind").unwrap_or("files");
    let offset = find_param_usize(detail, "offset").unwrap_or(0);
    let limit = find_param_usize(detail, "limit").unwrap_or(DEFAULT_LIMIT);
    let returned = find_usize(detail, "matches_returned")
        .or_else(|| detail.map(|detail| find_output_paths(detail.output.as_ref()).len()))
        .unwrap_or(0);
    let total = find_usize(detail, "total_matched");
    let incomplete = find_bool(detail, "truncated")
        || offset != 0
        || total.is_some_and(|total| returned != total);
    let title = match status {
        TranscriptCardStatus::Success => format!(
            "Find • {returned} {}{}",
            plural(returned, "path", "paths"),
            if incomplete { " returned" } else { "" }
        ),
        TranscriptCardStatus::Canceled => "Find • canceled".to_string(),
        _ => "Find".to_string(),
    };
    let mut lines = vec![
        find_quoted(query),
        format!("{} in {}", find_kind(kind), sanitized_single_line(path)),
    ];
    if offset != 0 || limit != DEFAULT_LIMIT {
        lines.push(format!("offset {offset} · limit {limit}"));
    }
    match status {
        TranscriptCardStatus::Running => {}
        TranscriptCardStatus::Success => {
            let paths = detail
                .map(|detail| find_output_paths(detail.output.as_ref()))
                .unwrap_or_default();
            lines.extend(paths.iter().take(TOOL_PREVIEW_LINES).cloned());
            if paths.len() > TOOL_PREVIEW_LINES {
                lines.push(format!("… preview limited to {TOOL_PREVIEW_LINES} paths"));
            }
            if incomplete {
                if let Some(total) = total {
                    if returned == 0 || offset >= total {
                        lines.push(format!("… showing 0 of {total} paths"));
                    } else {
                        let start = offset.saturating_add(1);
                        let end = offset.saturating_add(returned).min(total);
                        lines.push(format!("… showing {start}–{end} of {total} paths"));
                    }
                } else {
                    lines.push("… more paths may exist".to_string());
                }
            }
            if detail
                .and_then(|detail| detail.metadata.get("index_ready"))
                .and_then(serde_json::Value::as_bool)
                == Some(false)
            {
                lines.push("… index not ready; results may be incomplete".to_string());
            }
        }
        TranscriptCardStatus::Failed => lines.push(
            detail
                .and_then(|detail| find_first_non_empty_line(detail.output.as_ref()))
                .or_else(|| node.and_then(|node| find_first_non_empty_line(&node.preview)))
                .unwrap_or_else(|| "find failed".to_string()),
        ),
        TranscriptCardStatus::Canceled => lines.push("canceled".to_string()),
        TranscriptCardStatus::None => {}
    }
    TranscriptCard {
        id,
        role: TranscriptCardRole::Find,
        status,
        title,
        metadata: Vec::new(),
        body: lines.join("\n"),
        body_lines: Vec::new(),
        children: Vec::new(),
        activity_rows: Vec::new(),
        subagent_card: None,
    }
}

fn find_param<'a>(
    detail: Option<&'a crate::output::ToolActivityDetail>,
    key: &str,
) -> Option<&'a str> {
    detail?
        .params
        .get(key)?
        .as_str()
        .filter(|value| !value.is_empty())
}
fn find_metadata_str<'a>(
    detail: Option<&'a crate::output::ToolActivityDetail>,
    key: &str,
) -> Option<&'a str> {
    detail?
        .metadata
        .get(key)?
        .as_str()
        .filter(|value| !value.is_empty())
}

fn find_param_usize(
    detail: Option<&crate::output::ToolActivityDetail>,
    key: &str,
) -> Option<usize> {
    detail
        .and_then(|detail| detail.params.get(key))
        .and_then(serde_json::Value::as_u64)
        .and_then(|value| usize::try_from(value).ok())
        .or_else(|| find_usize(detail, key))
}
fn find_usize(detail: Option<&crate::output::ToolActivityDetail>, key: &str) -> Option<usize> {
    detail?
        .metadata
        .get(key)?
        .as_u64()
        .and_then(|value| usize::try_from(value).ok())
}
fn find_bool(detail: Option<&crate::output::ToolActivityDetail>, key: &str) -> bool {
    detail
        .and_then(|detail| detail.metadata.get(key))
        .and_then(serde_json::Value::as_bool)
        .unwrap_or(false)
}
fn find_kind(kind: &str) -> &'static str {
    match kind {
        "directories" | "dirs" => "directories",
        "mixed" | "both" | "files_and_directories" => "files and directories",
        _ => "files",
    }
}
fn find_quoted(query: &str) -> String {
    serde_json::to_string(&transcript::sanitize_preview(query))
        .unwrap_or_else(|_| "\"find query\"".to_string())
}
fn find_output_paths(output: &str) -> Vec<String> {
    output
        .lines()
        .filter(|line| !line.is_empty())
        .map(|line| {
            let safe = sanitized_single_line(line);
            truncate_preview_line(&safe, PREVIEW_LINE_MAX_DISPLAY_WIDTH)
        })
        .collect()
}

fn find_first_non_empty_line(text: &str) -> Option<String> {
    transcript::sanitize_preview(text)
        .lines()
        .map(str::trim)
        .find(|line| !line.is_empty())
        .map(normalize_inline_separators)
}