magi-code 0.77.1

Repository-aware CLI coding agent for terminal work
Documentation
use super::{
    PICKER_MODAL, draw_modal_panel, picker_list_area, picker_modal_list_area, render_picker_list,
};
use crate::tui::state::MissionControlState;
use ratatui::{
    Frame,
    layout::Rect,
    text::{Line, Span},
    widgets::{ListItem, Paragraph},
};

pub(crate) fn model_picker_list_area(area: Rect, has_notice: bool) -> Option<Rect> {
    let header_rows = 1 + u16::from(has_notice);
    picker_modal_list_area(area, "Model Picker", header_rows)
}

pub(in crate::tui::render) fn draw_model_picker(
    frame: &mut Frame<'_>,
    area: Rect,
    state: &MissionControlState,
) {
    let Some(picker) = &state.modals.model_picker else {
        return;
    };
    let theme = state.theme;
    let Some(text_area) = draw_modal_panel(frame, area, "Model Picker", PICKER_MODAL, theme) else {
        return;
    };
    if text_area.height == 0 {
        return;
    }
    let header = format!("current: {}", picker.current_model_id);
    frame.render_widget(
        Paragraph::new(header).style(theme.pane()),
        Rect::new(text_area.x, text_area.y, text_area.width, 1),
    );
    let header_rows = 1 + u16::from(picker.notice.is_some());
    let notice_y = text_area.y.saturating_add(1);
    if let Some(notice) = &picker.notice
        && notice_y < text_area.y.saturating_add(text_area.height)
    {
        frame.render_widget(
            Paragraph::new(notice.clone()).style(theme.muted(false)),
            Rect::new(text_area.x, notice_y, text_area.width, 1),
        );
    }
    let Some(list_area) = picker_list_area(text_area, header_rows) else {
        return;
    };
    let items = picker
        .entries
        .iter()
        .map(|entry| {
            let current = if entry.id == picker.current_model_id {
                ""
            } else {
                "  "
            };
            let mut parts = vec![Span::raw(format!("{current}{}", entry.id))];
            if let Some(context) = entry.context_window {
                parts.push(Span::raw(format!("  ctx:{context}")));
            }
            if let Some(name) = &entry.display_name {
                parts.push(Span::raw(format!("  {name}")));
            }
            ListItem::new(Line::from(parts))
        })
        .collect::<Vec<_>>();
    render_picker_list(
        frame,
        list_area,
        items,
        picker.selected,
        &state.scroll_views.model_picker,
        theme,
    );
}