magi-code 0.102.1

Repository-aware CLI coding agent for terminal work
Documentation
use super::*;

fn append_display_body_line(
    lines: &mut Vec<TranscriptVisualLine>,
    card: &TranscriptCard,
    line: &crate::rendering::DisplayLine,
    theme: MissionControlTheme,
    body_style: Style,
    width: u16,
) {
    if let Some(table) = &line.table {
        let available = body_text_wrap_width(width);
        for row in tables::layout_table(table, available, theme, card.role) {
            push_wide_assistant_spans(lines, card, row, true, width, body_style);
        }
        return;
    }
    let mut spans = Vec::with_capacity(line.spans.len().saturating_add(1));
    let assistant = card.role == TranscriptCardRole::Assistant;
    let body_style = if card.role == TranscriptCardRole::CodeMode {
        match line.spans.first().and_then(|span| span.text.chars().next()) {
            Some('✓') => body_style.fg(theme.activity_status_color(ActivityStatus::Success)),
            Some('✗') => body_style.fg(theme.activity_status_color(ActivityStatus::Failed)),
            Some('⚠' | '●') => {
                body_style.fg(theme.activity_status_color(ActivityStatus::Running))
            }
            Some('⊘') => body_style.fg(theme.activity_status_color(ActivityStatus::Canceled)),
            _ => body_style,
        }
    } else {
        body_style
    };
    spans.extend(line.spans.iter().map(|span| {
        AssistantVisualSpan::styled(
            span.text.clone(),
            if span.role == DisplayRole::Plain && !assistant {
                body_style
            } else {
                theme
                    .display_role(span.role)
                    .bg(card_body_background(card.role, theme))
            },
            Some(span.role),
        )
    }));
    push_wide_assistant_spans(lines, card, spans, true, width, body_style);
}

fn push_box_visual_row(
    lines: &mut Vec<TranscriptVisualLine>,
    display: String,
    copy_text: String,
    copy_continuation: bool,
    style: Style,
    width: u16,
    body_style: Style,
) {
    super::subagent::push_activity_card_row(
        lines,
        vec![ActivityCardSegment::plain(display, style)],
        width,
        body_style,
    );
    if let Some(line) = lines.last_mut() {
        line.copyable = !copy_text.is_empty();
        line.copy_text = copy_text;
        line.copy_continuation = copy_continuation;
        line.visual_copy_column_offset = body_line_copy_offset(width, 4);
    }
}

fn push_bordered_text_box(
    lines: &mut Vec<TranscriptVisualLine>,
    card: &TranscriptCard,
    text_rows: impl IntoIterator<Item = String>,
    style: Style,
    width: u16,
    body_style: Style,
) {
    let available = activity_card_content_width(width);
    if available < 5 {
        for text in text_rows {
            push_text_line(lines, card, text, style, false, width, body_style);
        }

        return;
    }
    push_box_visual_row(
        lines,
        format!("╭{}╮", "─".repeat(available - 2)),
        String::new(),
        false,
        style,
        width,
        body_style,
    );
    let inner_width = available - 4;
    for text in text_rows {
        for (index, wrapped) in wrap_spans_to_width(vec![Span::styled(text, style)], inner_width)
            .into_iter()
            .enumerate()
        {
            let text = spans_text(&wrapped);
            let padding = inner_width.saturating_sub(UnicodeWidthStr::width(text.as_str()));
            push_box_visual_row(
                lines,
                format!("│ {text}{} │", " ".repeat(padding)),
                text,
                index > 0,
                style,
                width,
                body_style,
            );
        }
    }
    push_box_visual_row(
        lines,
        format!("╰{}╯", "─".repeat(available - 2)),
        String::new(),
        false,
        style,
        width,
        body_style,
    );
}

/// Bordered intent box replaces body rows that repeat the intent: Bash's leading
/// intent row and Code Mode's `Code Mode intent` fact.
fn body_row_repeats_intent(card: &TranscriptCard, index: usize, text: &str) -> bool {
    card.intent.is_some()
        && match card.role {
            TranscriptCardRole::Bash => index == 0,
            TranscriptCardRole::CodeMode => text.starts_with("Code Mode intent • "),
            _ => false,
        }
}

pub(super) fn append_card_body_lines(
    lines: &mut Vec<TranscriptVisualLine>,
    state: &MissionControlState,
    card: &TranscriptCard,
    active: bool,
    body_style: Style,
    width: u16,
) {
    let theme = state.theme;
    if card.role == TranscriptCardRole::SubagentBatch {
        append_subagent_card_body_lines(lines, state, card, active, width, body_style);
        return;
    }
    let has_bordered_intent = card.intent.is_some();
    let metadata_style = theme.dim(active).bg(card_body_background(card.role, theme));
    let jev_metadata = card
        .metadata
        .iter()
        .filter(|metadata| metadata.starts_with("Jev:"))
        .cloned()
        .collect::<Vec<_>>();
    if !jev_metadata.is_empty() {
        push_bordered_text_box(lines, card, jev_metadata, metadata_style, width, body_style);
        if !has_bordered_intent {
            push_body_blank(lines, card, width, theme);
        }
    }
    for metadata in card
        .metadata
        .iter()
        .filter(|metadata| !metadata.starts_with("Jev:"))
    {
        push_text_line(
            lines,
            card,
            metadata.clone(),
            metadata_style,
            false,
            width,
            body_style,
        );
    }
    if let Some(intent) = &card.intent {
        let intent_style = theme
            .transcript_tool_body()
            .bg(card_body_background(card.role, theme));
        push_bordered_text_box(
            lines,
            card,
            [format!("Intent: {intent}")],
            intent_style,
            width,
            body_style,
        );
        push_body_blank(lines, card, width, theme);
    }
    if streaming::is_windowed(card) {
        return;
    }
    let summary_in_box =
        card.role == TranscriptCardRole::CodeMode && activity_card_content_width(width) >= 8;
    if !card.body_lines.is_empty() {
        for (index, line) in card.body_lines.iter().enumerate() {
            if summary_in_box && index == 0 {
                continue;
            }
            if !body_row_repeats_intent(card, index, &line.plain_text()) {
                append_display_body_line(lines, card, line, theme, body_style, width);
            }
        }
    } else {
        for (index, body_line) in card.body.lines().enumerate() {
            if summary_in_box && index == 0 {
                continue;
            }
            if body_row_repeats_intent(card, index, body_line) {
                continue;
            }
            push_text_line(
                lines,
                card,
                body_line.to_string(),
                body_style,
                true,
                width,
                body_style,
            );
        }
    }
    if card.role == TranscriptCardRole::CodeMode {
        append_activity_feed_lines(lines, card, width, body_style, theme);
    }
    for child in &card.children {
        let child_status = status_mark(child.status);
        let label = if child_status.is_empty() {
            format!("- {}", child.label)
        } else {
            format!("- {child_status} {}", child.label)
        };
        push_text_line(
            lines,
            card,
            label,
            theme
                .transcript_tool_body()
                .bg(card_body_background(card.role, theme)),
            true,
            width,
            body_style,
        );
    }
}

fn append_activity_feed_lines(
    lines: &mut Vec<TranscriptVisualLine>,
    card: &TranscriptCard,
    width: u16,
    body_style: Style,
    theme: MissionControlTheme,
) {
    // The first visible semantic row is Code Mode's outcome/count summary.
    let summary = card
        .body_lines
        .first()
        .map(|line| line.plain_text())
        .or_else(|| card.body.lines().next().map(str::to_owned));
    let title = summary
        .into_iter()
        .map(|summary| {
            let style = match summary.chars().next() {
                Some('✓') => body_style.fg(theme.activity_status_color(ActivityStatus::Success)),
                Some('✗') => body_style.fg(theme.activity_status_color(ActivityStatus::Failed)),
                Some('⚠' | '●') => {
                    body_style.fg(theme.activity_status_color(ActivityStatus::Running))
                }
                Some('⊘') => body_style.fg(theme.activity_status_color(ActivityStatus::Canceled)),
                _ => body_style,
            };
            ActivityCardSegment::plain(summary, style)
        })
        .collect();
    push_activity_card_box_edge(lines, width, body_style, theme, true, title);
    for row in &card.activity_rows {
        let segment = ActivityCardSegment::plain(
            format!("{} {}", activity_card_status_glyph(row.status), row.label),
            activity_card_status_style(row.status, theme).bg(theme.surface_background()),
        )
        .with_status_indicator(row.status, Some(0), Some(row.activity_id.clone()));
        push_activity_card_feed_row(lines, Some(segment), width, body_style, theme);
    }
    for _ in card.activity_rows.len()..super::TOOL_PREVIEW_LINES {
        push_activity_card_feed_row(lines, None, width, body_style, theme);
    }
    push_activity_card_box_edge(lines, width, body_style, theme, false, Vec::new());
}