a3s-code-core 8.5.4

A3S Code Core - Embeddable AI agent library with tool execution
Documentation
use std::path::Path;

pub use a3s_code_core::llm::CodexLoginClient;

pub fn default_codex_model() -> String {
    std::env::var("A3S_CODEX_MODEL")
        .ok()
        .filter(|model| !model.trim().is_empty())
        .unwrap_or_else(|| {
            codex_models_from_cache()
                .into_iter()
                .next()
                .unwrap_or_else(|| "gpt-5.5".to_string())
        })
}

fn codex_models_from_cache() -> Vec<String> {
    let Some(home) = std::env::var_os("HOME") else {
        return Vec::new();
    };
    let path = Path::new(&home).join(".codex/models_cache.json");
    let Ok(raw) = std::fs::read_to_string(path) else {
        return Vec::new();
    };
    let Ok(cache) = serde_json::from_str::<serde_json::Value>(&raw) else {
        return Vec::new();
    };

    let Some(models) = cache.get("models").and_then(serde_json::Value::as_array) else {
        return Vec::new();
    };
    let mut listed: Vec<(i64, String)> = models
        .iter()
        .filter_map(|model| {
            if model.get("visibility").and_then(serde_json::Value::as_str) != Some("list") {
                return None;
            }
            let slug = model
                .get("slug")
                .and_then(serde_json::Value::as_str)?
                .to_string();
            let priority = model
                .get("priority")
                .and_then(serde_json::Value::as_i64)
                .unwrap_or(999);
            Some((priority, slug))
        })
        .collect();
    listed.sort_by_key(|(priority, _)| *priority);
    listed.into_iter().map(|(_, slug)| slug).collect()
}