magi-code 0.77.1

Repository-aware CLI coding agent for terminal work
Documentation
use reqwest::header::HeaderValue;

use std::collections::BTreeMap;

use super::CODEX_MODEL_CATALOG_CLIENT_VERSION;

pub(crate) fn package_user_agent() -> String {
    format!("magi-code/{}", env!("CARGO_PKG_VERSION"))
}

fn codex_user_agent() -> String {
    format!("codex_cli_rs/{CODEX_MODEL_CATALOG_CLIENT_VERSION}")
}

pub(crate) fn sse_json_headers(token: Option<&str>) -> BTreeMap<String, String> {
    let mut headers = BTreeMap::from([
        ("accept".to_string(), "text/event-stream".to_string()),
        ("content-type".to_string(), "application/json".to_string()),
        ("user-agent".to_string(), package_user_agent()),
    ]);
    if let Some(token) = token.filter(|token| !token.is_empty()) {
        headers.insert("authorization".to_string(), format!("Bearer {token}"));
    }
    headers
}

pub(crate) fn model_catalog_headers(token: Option<&str>) -> BTreeMap<String, String> {
    let mut headers = BTreeMap::from([
        ("accept".to_string(), "application/json".to_string()),
        ("user-agent".to_string(), package_user_agent()),
    ]);
    if let Some(token) = token.filter(|token| !token.is_empty()) {
        headers.insert("authorization".to_string(), format!("Bearer {token}"));
    }
    headers
}

pub(crate) fn codex_sse_headers(token: &str, account_id: &str) -> BTreeMap<String, String> {
    let mut headers = sse_json_headers(Some(token));
    headers.insert("chatgpt-account-id".to_string(), account_id.to_string());
    headers.insert("originator".to_string(), "codex_cli_rs".to_string());
    headers.insert("user-agent".to_string(), codex_user_agent());
    headers.insert(
        "openai-beta".to_string(),
        "responses=experimental".to_string(),
    );
    headers
}

fn codex_routing_hint(model: &str, service_tier: Option<&str>) -> Option<String> {
    let routing_hint = match service_tier {
        Some(tier) => format!("model={model};tier={tier}"),
        None => format!("model={model}"),
    };
    HeaderValue::from_str(&routing_hint)
        .ok()
        .map(|_| routing_hint)
}

pub(crate) fn codex_sse_headers_with_routing_hint(
    token: &str,
    account_id: &str,
    model: &str,
    service_tier: Option<&str>,
) -> BTreeMap<String, String> {
    let mut headers = codex_sse_headers(token, account_id);
    if let Some(routing_hint) = codex_routing_hint(model, service_tier) {
        headers.insert("x-codex-routing-hint".to_string(), routing_hint);
    }
    headers
}

pub(crate) fn codex_model_catalog_headers(
    token: &str,
    account_id: &str,
) -> BTreeMap<String, String> {
    BTreeMap::from([
        ("authorization".to_string(), format!("Bearer {token}")),
        ("chatgpt-account-id".to_string(), account_id.to_string()),
        ("originator".to_string(), "codex_cli_rs".to_string()),
        ("user-agent".to_string(), codex_user_agent()),
        ("accept".to_string(), "application/json".to_string()),
    ])
}