codex-cli-captain 0.0.9

Codex-Cli-Captain runtime, installer, and MCP server for Codex CLI.
use crate::specialist_roles::{
    fallback_specialist_execution_mode, load_role_config_snapshot,
    preferred_specialist_execution_mode,
};
use serde_json::{json, Value};

fn role_model_entry(role: &str) -> Value {
    let snapshot = load_role_config_snapshot(role);
    let model = snapshot.get("model").cloned().unwrap_or(Value::Null);
    let variant = snapshot.get("variant").cloned().unwrap_or(Value::Null);
    let fast_mode = snapshot
        .get("fast_mode")
        .and_then(Value::as_bool)
        .unwrap_or(false);
    let uses_low_cost_model = model
        .as_str()
        .map(|value| value.contains("mini"))
        .unwrap_or(false);

    json!({
        "role": role,
        "agent_id": crate::specialist_roles::agent_id_for_role(role).unwrap_or(role),
        "model": model,
        "variant": variant,
        "fast_mode": fast_mode,
        "source": snapshot.get("source").cloned().unwrap_or(Value::Null),
        "uses_low_cost_model": uses_low_cost_model,
    })
}

fn roles_low_cost(roles: &[&str]) -> bool {
    roles.iter().all(|role| {
        role_model_entry(role)
            .get("uses_low_cost_model")
            .and_then(Value::as_bool)
            .unwrap_or(false)
    })
}

fn create_simple_task_route(label: &str, roles: &[&str]) -> Value {
    json!({
        "task": label,
        "roles": roles.iter().map(|role| role_model_entry(role)).collect::<Vec<_>>(),
        "uses_low_cost_model": roles_low_cost(roles),
    })
}

pub(crate) fn create_cost_routing_payload(runtime_config: &Value, payload: &Value) -> Value {
    let preferred_execution_mode = preferred_specialist_execution_mode(runtime_config);
    let fallback_execution_mode = fallback_specialist_execution_mode(runtime_config);
    let subagents_enabled = preferred_execution_mode == "codex_subagent";
    let current_task = payload.get("current_task_card").unwrap_or(&Value::Null);
    let current_role = current_task
        .get("assigned_role")
        .and_then(Value::as_str)
        .unwrap_or("unassigned");
    let current_role_model = if current_role == "unassigned" {
        Value::Null
    } else {
        role_model_entry(current_role)
    };
    let simple_task_routes = vec![
        create_simple_task_route(
            "simple_search_and_collection",
            &["explorer", "companion_reader"],
        ),
        create_simple_task_route("documentation_update", &["documenter"]),
        create_simple_task_route("git_or_filesystem_lookup", &["companion_reader"]),
        create_simple_task_route("narrow_git_or_release_mutation", &["companion_operator"]),
    ];
    let simple_routes_low_cost = simple_task_routes
        .iter()
        .all(|route| route.get("uses_low_cost_model").and_then(Value::as_bool) == Some(true));
    let status = if subagents_enabled && simple_routes_low_cost {
        "configured"
    } else {
        "needs_attention"
    };

    json!({
        "status": status,
        "summary": if status == "configured" {
            "CCC is configured to prefer host custom subagents, and simple search/collection/docs companion routes use mini-class models."
        } else {
            "CCC cost routing needs attention; inspect preferred execution mode and simple task role models."
        },
        "subagents": {
            "preferred_execution_mode": preferred_execution_mode,
            "fallback_execution_mode": fallback_execution_mode,
            "enabled": subagents_enabled,
            "host_update_mode": "ccc_cli_subcommand",
            "current_task_role": current_role,
            "current_task_agent_id": current_task.get("assigned_agent_id").cloned().unwrap_or(Value::Null),
            "current_task_preferred_custom_agent": current_task.pointer("/delegation_plan/preferred_custom_agent_name").cloned().unwrap_or(Value::Null),
            "current_task_model": current_role_model,
        },
        "simple_task_routes": simple_task_routes,
        "simple_routes_use_low_cost_models": simple_routes_low_cost,
        "token_usage_observation": {
            "status": payload.pointer("/token_usage_visibility/status").cloned().unwrap_or(Value::String("unknown".to_string())),
            "reason": payload.pointer("/token_usage_visibility/unavailable_reason").cloned().unwrap_or(Value::Null),
            "note": "Host custom subagent token usage is visible only when the host supplies raw usage events; launch routing is still recorded in CCC status."
        }
    })
}