magi-code 0.97.5

Repository-aware CLI coding agent for terminal work
Documentation
mod anthropic;
mod claude_admission;
pub(crate) mod claude_inert;
mod claude_projection;
pub(crate) mod claude_subscription;
pub(crate) mod claude_usage;
mod codex_session;
pub(crate) use codex_session::CodexTurnContext;
pub(crate) mod codex_usage;
pub(crate) mod error;
mod factory;
mod openai;
mod openai_stream;
mod replay_trace;
mod request;
mod skill_projection;
mod sse;
mod stream;
mod transport;

pub use anthropic::AnthropicProvider;
pub(crate) use factory::{
    provider_from_selection_with_settings_for_workload,
    provider_from_selection_with_settings_for_workload_with_resolved_auth,
    supported_custom_provider,
};
pub(crate) use openai::{
    CODEX_MODEL_CATALOG_CLIENT_VERSION, ModelCatalogRequestFailure, codex_account_id_for,
    codex_sse_headers_with_routing_hint, normalize_codex_model,
};
pub use openai::{OpenAiCodexProvider, OpenAiCompatibleProvider, Provider};
pub use request::{
    ChatMessage, MessageRole, ProviderConversationItem, ProviderRequest, ProviderSelection,
    ProviderToolResult,
};
pub(crate) use request::{conversation_id_for_session, default_model_for_provider};
pub use stream::{ProviderEvent, ReasoningSummary, ToolCall, Usage};
pub(crate) use stream::{StreamParser, UsageObservation, UsagePresence};
pub use transport::{HttpRequest, HttpResponseMetadata, HttpTransport, ReqwestHttpTransport};

pub const OPENAI_CODEX_PROVIDER: &str = "openai-codex";
pub const ANTHROPIC_PROVIDER: &str = "anthropic";
pub const CLAUDE_SUBSCRIPTION_PROVIDER: &str = "claude-subscription";

/// Conservative input ceiling for Claude CLI selections without extended context.
pub(crate) const CLAUDE_SUBSCRIPTION_MAX_PROMPT_TOKENS: usize = 202_000;

/// Versioned Opus 4.6+ and Fable 5+ models support explicit extended context.
pub(crate) fn claude_subscription_supports_extended_context(model: &str) -> bool {
    let (version, minimum) = if let Some(version) = model.strip_prefix("claude-opus-") {
        (version, (4, 6))
    } else if let Some(version) = model.strip_prefix("claude-fable-") {
        (version, (5, 0))
    } else {
        return false;
    };
    let mut components = version.split('-');
    let Some(major) = components
        .next()
        .and_then(|value| value.parse::<u32>().ok())
    else {
        return false;
    };
    let minor = match components.next() {
        Some(value) => match value.parse::<u32>() {
            Ok(minor) => minor,
            Err(_) => return false,
        },
        None => 0,
    };
    (major, minor) >= minimum
        && components.all(|value| !value.is_empty() && value.bytes().all(|b| b.is_ascii_digit()))
}

/// Explicit eligible `[1m]` selections use a one-million-token input ceiling.
pub(crate) fn claude_subscription_prompt_limit(model: &str) -> usize {
    if model
        .strip_suffix("[1m]")
        .is_some_and(claude_subscription_supports_extended_context)
    {
        1_000_000
    } else {
        CLAUDE_SUBSCRIPTION_MAX_PROMPT_TOKENS
    }
}

/// Providers whose usage follows Anthropic semantics: `input_tokens` excludes cache reads/writes.
pub(crate) fn reports_anthropic_usage(provider_id: &str) -> bool {
    matches!(
        provider_id,
        ANTHROPIC_PROVIDER | CLAUDE_SUBSCRIPTION_PROVIDER
    )
}
pub const DEFAULT_CODEX_MODEL: &str = "gpt-5.5";
pub const DEFAULT_ANTHROPIC_MODEL: &str = "claude-sonnet-4-5-20250929";
pub const CODEX_RESPONSES_URL: &str = "https://chatgpt.com/backend-api/codex/responses";
pub const CODEX_MODELS_URL: &str = "https://chatgpt.com/backend-api/codex/models";

#[cfg(test)]
pub(crate) use openai::{
    build_chat_completion_tools_json, chat_completion_tools_json,
    openai_compatible_chat_completions_body,
};