magi-code 0.96.2

Repository-aware CLI coding agent for terminal work
Documentation
use serde::{Deserialize, Serialize};
use std::{
    collections::BTreeMap,
    fs,
    path::{Path, PathBuf},
};
mod selection;
pub(crate) use selection::{
    resolve_persisted_primary_agent_selection, sanitized_primary_agent_diagnostic_text,
};

pub(crate) const MAX_PRIMARY_AGENT_PROFILE_BYTES: u64 = 64 * 1024;
const ID_RULES: &str = "primary agent id must use only ASCII letters, digits, '_' or '-'";

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct PrimaryAgentProfile {
    pub(crate) id: String,
    pub(crate) name: String,
    pub(crate) description: String,
    pub(crate) path: PathBuf,
    pub(crate) prompt: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct PrimaryAgentProfileDiagnostic {
    pub(crate) id: Option<String>,
    pub(crate) path: Option<PathBuf>,
    pub(crate) message: String,
}

#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct PrimaryAgentProfileDiscovery {
    pub(crate) profiles: BTreeMap<String, PrimaryAgentProfile>,
    pub(crate) diagnostics: Vec<PrimaryAgentProfileDiagnostic>,
}

pub(crate) fn validate_primary_agent_id(id: &str) -> anyhow::Result<String> {
    if id.is_empty() {
        anyhow::bail!("primary agent id must not be empty; {ID_RULES}");
    }
    if id != id.trim() {
        anyhow::bail!("primary agent id must not have leading or trailing whitespace; {ID_RULES}");
    }
    if id == "." || id == ".." {
        anyhow::bail!("primary agent id must not be a path segment; {ID_RULES}");
    }
    if !id
        .chars()
        .all(|ch| ch.is_ascii_alphanumeric() || ch == '_' || ch == '-')
    {
        anyhow::bail!("{ID_RULES}");
    }
    Ok(id.to_string())
}

pub(crate) fn discover_primary_agent_profiles(root: &Path) -> PrimaryAgentProfileDiscovery {
    let mut discovery = PrimaryAgentProfileDiscovery::default();
    let entries = match fs::read_dir(root) {
        Ok(entries) => entries,
        Err(error) if error.kind() == std::io::ErrorKind::NotFound => return discovery,
        Err(error) => {
            discovery.diagnostics.push(PrimaryAgentProfileDiagnostic {
                id: None,
                path: Some(root.to_path_buf()),
                message: format!("could not read primary agent profiles directory: {error}"),
            });
            return discovery;
        }
    };

    let mut paths = entries
        .filter_map(|entry| match entry {
            Ok(entry) => Some(entry.path()),
            Err(error) => {
                discovery.diagnostics.push(PrimaryAgentProfileDiagnostic {
                    id: None,
                    path: Some(root.to_path_buf()),
                    message: format!(
                        "could not inspect primary agent profile directory entry: {error}"
                    ),
                });
                None
            }
        })
        .filter(|path| path.extension().and_then(|ext| ext.to_str()) == Some("md"))
        .collect::<Vec<_>>();
    paths.sort();

    for path in paths {
        match load_primary_agent_profile(&path) {
            Ok(profile) => {
                discovery.profiles.insert(profile.id.clone(), profile);
            }
            Err(error) => discovery.diagnostics.push(PrimaryAgentProfileDiagnostic {
                id: path
                    .file_stem()
                    .and_then(|stem| stem.to_str())
                    .map(ToString::to_string),
                path: Some(path.clone()),
                message: format!("skipping primary agent profile: {error}"),
            }),
        }
    }
    discovery
}

pub(crate) fn load_primary_agent_profile(path: &Path) -> anyhow::Result<PrimaryAgentProfile> {
    let id = path
        .file_stem()
        .and_then(|stem| stem.to_str())
        .ok_or_else(|| anyhow::anyhow!("profile filename stem must be valid UTF-8"))?;
    let id = validate_primary_agent_id(id)?;
    let text =
        crate::prompt_file::read_prompt_file(path, MAX_PRIMARY_AGENT_PROFILE_BYTES, true)?.text;
    let (frontmatter, body) = parse_profile_markdown(&text)?;
    let name = required_string(&frontmatter, "name")?;
    let description = required_string(&frontmatter, "description")?;
    let prompt = body.trim().to_string();
    if prompt.is_empty() {
        anyhow::bail!("profile body must not be empty");
    }
    Ok(PrimaryAgentProfile {
        id,
        name,
        description,
        path: path.to_path_buf(),
        prompt,
    })
}

pub(crate) fn render_your_role_prompt(persona: &str, prompt: &str) -> String {
    format!(
        "<Your-Role Persona={}>\nYou must always follow the instructions of your assigned persona:\n{}\n</Your-Role>",
        persona.trim(),
        prompt.trim()
    )
}

pub(crate) fn render_primary_agent_prompt_append(profile: &PrimaryAgentProfile) -> String {
    render_your_role_prompt(&profile.name, &profile.prompt)
}

fn parse_profile_markdown(text: &str) -> anyhow::Result<(BTreeMap<String, String>, String)> {
    if !text.starts_with("---\n") {
        anyhow::bail!("missing YAML frontmatter with required 'name' and 'description'");
    }
    let rest = &text[4..];
    let Some(end) = rest.find("\n---\n") else {
        anyhow::bail!("frontmatter start marker without closing marker");
    };
    let frontmatter_text = &rest[..end];
    let body = rest[end + 5..].to_string();
    let mut frontmatter = BTreeMap::new();
    for line in frontmatter_text
        .lines()
        .filter(|line| !line.trim().is_empty())
    {
        let Some((key, value)) = line.split_once(':') else {
            anyhow::bail!("malformed frontmatter line");
        };
        let key = key.trim();
        let value = parse_frontmatter_string_field(key, value.trim())?;
        frontmatter.insert(key.to_string(), value);
    }
    Ok((frontmatter, body))
}

fn parse_frontmatter_string_field(key: &str, value: &str) -> anyhow::Result<String> {
    if value.is_empty() {
        return Ok(String::new());
    }
    if let Some(quoted) = quoted_yaml_string(value) {
        return Ok(quoted.to_string());
    }
    if value.starts_with('[')
        || value.starts_with('{')
        || is_yaml_bool(value)
        || is_yaml_null(value)
        || is_yaml_number(value)
    {
        anyhow::bail!("frontmatter field '{key}' must be a YAML string");
    }
    Ok(value.to_string())
}

fn quoted_yaml_string(value: &str) -> Option<&str> {
    let bytes = value.as_bytes();
    if bytes.len() >= 2
        && ((bytes[0] == b'"' && bytes[bytes.len() - 1] == b'"')
            || (bytes[0] == b'\'' && bytes[bytes.len() - 1] == b'\''))
    {
        Some(&value[1..value.len() - 1])
    } else {
        None
    }
}

fn is_yaml_bool(value: &str) -> bool {
    matches!(
        value,
        "true"
            | "True"
            | "TRUE"
            | "false"
            | "False"
            | "FALSE"
            | "yes"
            | "Yes"
            | "YES"
            | "no"
            | "No"
            | "NO"
            | "on"
            | "On"
            | "ON"
            | "off"
            | "Off"
            | "OFF"
    )
}

fn is_yaml_null(value: &str) -> bool {
    matches!(value, "~" | "null" | "Null" | "NULL")
}

fn is_yaml_number(value: &str) -> bool {
    let value = value.replace('_', "");
    value.parse::<i64>().is_ok() || value.parse::<f64>().is_ok()
}

fn required_string(frontmatter: &BTreeMap<String, String>, key: &str) -> anyhow::Result<String> {
    let value = frontmatter
        .get(key)
        .map(|value| value.trim())
        .filter(|value| !value.is_empty())
        .ok_or_else(|| anyhow::anyhow!("missing required frontmatter field '{key}'"))?;
    Ok(value.to_string())
}