magi-code 0.77.1

Repository-aware CLI coding agent for terminal work
Documentation
#[cfg(test)]
mod cache;
mod replay;
mod replay_cache;
mod tokens;

#[cfg(test)]
pub(crate) use cache::conversation_cache_material;
#[cfg(test)]
pub(crate) use replay::{
    ConversationReplay, REPLAY_TOOL_RESULT_OUTPUT_CHAR_LIMIT, build_conversation_replay,
    build_conversation_replay_with_limits, compact_historical_tool_output,
};
pub(crate) use replay::{
    ConversationReplayLimits, REPLAY_JSONL_MAX_BYTES, REPLAY_JSONL_MAX_LINES,
    build_conversation_replay_from_events, build_frontend_conversation_from_events,
};
pub(crate) use replay_cache::ConversationReplayCache;
#[cfg(test)]
pub(crate) use replay_cache::ReplayCacheMetrics;
#[cfg(test)]
pub(crate) use tokens::estimate_provider_request_input_tokens;
#[cfg(test)]
pub(crate) use tokens::estimate_text_tokens;
pub use tokens::{
    ContextBudget, ContextBudgetOverride, estimate_messages_tokens, usage_input_tokens,
};
pub(crate) use tokens::{
    ContextTokenCount, count_supported_provider_conversation_item_tokens,
    project_provider_conversation_items_tokens, project_provider_request_input_tokens,
    project_text_tokens, token_encoding_family_for_model,
};

#[cfg(test)]
pub(crate) use crate::providers::{ChatMessage, ProviderConversationItem, ProviderToolResult};
#[cfg(test)]
use crate::sessions::{
    Session, SessionDiagnosticOperation, SessionReadDiagnostic, report_session_diagnostic,
};
use crate::sessions::{SessionEvent, SessionEventKind};
use serde_json::Value;
#[cfg(test)]
pub(crate) use serde_json::json;

#[cfg(test)]
const RECENT_EVENTS_CONTEXT_MAX_EVENTS: usize = 10_000;
#[cfg(test)]
const RECENT_EVENTS_CONTEXT_MAX_BYTES: usize = 2 * 1024 * 1024;
// Tail read cap matches retained-byte budget: one bounded read can fill recent-context window.
#[cfg(test)]
const RECENT_EVENTS_CONTEXT_MAX_READ_BYTES: usize = RECENT_EVENTS_CONTEXT_MAX_BYTES;

#[cfg(test)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct RecentEventsContext {
    pub text: String,
    pub diagnostics: Vec<SessionReadDiagnostic>,
}

#[cfg(test)]
pub(crate) fn recent_events_context(
    session: &Session,
    keep_recent_tokens: usize,
) -> anyhow::Result<String> {
    Ok(recent_events_context_report(session, keep_recent_tokens)?.text)
}

#[cfg(test)]
pub(crate) fn recent_events_context_report(
    session: &Session,
    keep_recent_tokens: usize,
) -> anyhow::Result<RecentEventsContext> {
    let mut selected = Vec::new();
    let mut tokens = 0;
    let recent = session
        .read_recent_events_tolerant_tail(
            RECENT_EVENTS_CONTEXT_MAX_EVENTS,
            RECENT_EVENTS_CONTEXT_MAX_BYTES,
            RECENT_EVENTS_CONTEXT_MAX_READ_BYTES,
        )
        .inspect_err(|error| {
            report_session_diagnostic(
                SessionDiagnosticOperation::RecentContext,
                session.path(),
                error,
            );
        })?;
    for event in recent.events.into_iter().rev() {
        if !is_provider_visible_session_event(&event) {
            continue;
        }
        let line = event_line(&event);
        let line_tokens = estimate_text_tokens(&line);
        if !selected.is_empty() && tokens + line_tokens > keep_recent_tokens {
            break;
        }
        tokens += line_tokens;
        selected.push(line);
    }
    selected.reverse();
    Ok(RecentEventsContext {
        text: selected.join("\n"),
        diagnostics: recent.diagnostics,
    })
}

#[cfg(test)]
fn is_provider_visible_session_event(event: &SessionEvent) -> bool {
    !is_local_only_session_event(event) && event.kind() != Some(SessionEventKind::ReasoningSummary)
}

pub(crate) fn is_local_only_session_event(event: &SessionEvent) -> bool {
    event.kind().is_some_and(SessionEventKind::is_local_only)
}

pub(crate) fn event_line(event: &SessionEvent) -> String {
    let compact_payload = if event.kind() == Some(SessionEventKind::Compaction) {
        event
            .payload
            .get("summary")
            .and_then(Value::as_str)
            .unwrap_or("[invalid compaction summary]")
            .to_string()
    } else if let Some(text) = event.payload.get("text").and_then(Value::as_str) {
        text.to_string()
    } else if let Some(message) = event.payload.get("message").and_then(Value::as_str) {
        message.to_string()
    } else {
        event.payload.to_string()
    };
    format!(
        "{}: {}",
        event.event_type,
        compact_payload.replace('\n', "\\n")
    )
}

pub(crate) fn canonical_json(value: &Value) -> String {
    serde_json::to_string(value).unwrap_or_else(|_| "null".to_string())
}

#[cfg(test)]
mod tests;