magi-code 0.77.1

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

#[test]
fn submit_help_opens_help_without_worker_or_provider_run() {
    assert_eq!(
        tui_submit_command(" /help ignored ", &CommandRegistry::mvp()),
        TuiSubmitCommand::Help
    );
    assert!(!tui_submit_command("/help", &CommandRegistry::mvp()).requires_idle());

    let temp = tempfile::TempDir::new().unwrap();
    let (sender, receiver) = bounded::<TuiEvent>(4);
    let mut app = test_app(&temp, sender);
    app.active_run = true;
    let mut ui_state = state::MissionControlState {
        ..Default::default()
    };

    let submitted = app.submit("/help".to_string(), &mut ui_state, &receiver, test_area());

    assert!(!submitted);
    assert!(ui_state.show_help);
    assert_eq!(ui_state.help_offset(), 0);
    assert_eq!(ui_state.status, "showing help");
    assert!(app.active_run);
    assert!(app.worker.is_none());
    assert!(receiver.try_recv().is_err());
}

#[test]
fn submit_system_prompt_and_quit_preserve_active_run_bypass_behavior() {
    let temp = tempfile::TempDir::new().unwrap();
    let (sender, receiver) = bounded::<TuiEvent>(4);
    let mut app = test_app(&temp, sender);
    app.active_run = true;
    let mut ui_state = state::MissionControlState::default();

    app.submit(
        "/system-prompt".to_string(),
        &mut ui_state,
        &receiver,
        test_area(),
    );

    assert!(ui_state.system_prompt_modal_visible());
    assert!(app.active_run);
    assert!(app.worker.is_none());
    assert!(receiver.try_recv().is_err());

    app.submit("/quit".to_string(), &mut ui_state, &receiver, test_area());

    assert!(app.active_run);
    assert!(app.worker.is_none());
    assert!(receiver.try_recv().is_err());
}

#[test]
fn submit_system_prompt_prepares_modal_without_provider_worker_or_session_event() {
    let temp = tempfile::TempDir::new().unwrap();
    let (sender, receiver) = bounded::<TuiEvent>(4);
    let session = SessionManager::new(temp.path().join("sessions"))
        .create()
        .unwrap();
    let paths = test_paths(temp.path());
    fs::create_dir_all(&paths.subagents).unwrap();
    fs::write(
        paths.subagents.join("reviewer.md"),
        "---\nname: Reviewer\ndescription: Code review\n---\nSECRET REVIEW PROMPT\n",
    )
    .unwrap();
    let mut app = test_app_with_active_session(&temp, sender, Some(session.clone()));
    let mut ui_state = state::MissionControlState {
        prompt_editor: state::PromptEditor::new("preserved draft", "preserved draft".len()),
        transcript: vec!["existing transcript".to_string()].into(),
        model: "test-model".to_string(),
        provider_ready: false,
        ..Default::default()
    };
    ui_state.set_scroll_offset(&ui_state.scroll_views.detail, 3);

    app.submit(
        "/system-prompt".to_string(),
        &mut ui_state,
        &receiver,
        test_area(),
    );
    assert_eq!(ui_state.status, "preparing system prompt…");
    reap_owned_worker(
        &mut app,
        &mut ui_state,
        MissionControlApp::reconcile_system_prompt_worker,
    );

    let modal = ui_state.modals.system_prompt_modal.as_ref().unwrap();
    assert!(!modal.content.trim().is_empty());
    assert!(modal.content.contains("tokens /"));
    assert!(modal.content.contains("max ("));
    assert!(modal.content.contains("<Tools>"));
    assert!(!modal.content.contains("Available tools:"));
    assert!(modal.content.contains("<Subagents>"));
    assert!(modal.content.contains("- `reviewer` — Code review"));
    let tools_index = modal.content.find("<Tools>").unwrap();
    let subagents_index = modal.content.find("<Subagents>").unwrap();
    let skills_index = modal.content.find("<Available-Skills>").unwrap();
    let instructions_index = modal
        .content
        .find("No AGENTS.md instruction files")
        .unwrap();
    assert!(tools_index < subagents_index);
    assert!(subagents_index < skills_index);
    assert!(skills_index < instructions_index);
    assert!(!modal.content.contains("SECRET REVIEW PROMPT"));
    assert_eq!(
        ui_state.scroll_offset(&ui_state.scroll_views.system_prompt),
        0
    );
    assert_eq!(ui_state.prompt_plain_text(), "preserved draft");
    assert_eq!(ui_state.transcript, vec!["existing transcript"]);
    assert_eq!(ui_state.detail_offset(), 3);
    assert!(!app.active_run);
    assert!(app.worker.is_none());
    assert!(matches!(
        receiver.recv_timeout(Duration::from_secs(1)),
        Ok(TuiEvent::WorkerOutcomeReady)
    ));
    assert!(session.read_events().unwrap().is_empty());
}

#[test]
fn submit_mcp_opens_modal_with_settings_rows() {
    let temp = tempfile::TempDir::new().unwrap();
    let (sender, receiver) = bounded::<TuiEvent>(4);
    let mut app = test_app(&temp, sender);
    crate::config::write_settings(
        &app.config.paths,
        &crate::config::Settings {
            mcp_servers: std::collections::BTreeMap::from([
                (
                    "alpha".to_string(),
                    crate::config::McpServerConfig::Stdio(crate::config::McpStdioServerConfig {
                        command: "alpha-mcp".to_string(),
                        args: Vec::new(),
                        env: std::collections::BTreeMap::new(),
                        enabled: true,
                        timeout: None,
                    }),
                ),
                (
                    "beta".to_string(),
                    crate::config::McpServerConfig::Http(crate::config::McpHttpServerConfig {
                        url: "https://mcp.example.test/beta".to_string(),
                        headers: std::collections::BTreeMap::new(),
                        oauth: None,
                        enabled: false,
                        timeout: None,
                    }),
                ),
            ]),
            ..Default::default()
        },
    )
    .unwrap();
    let mut ui_state = state::MissionControlState::default();

    let submitted = app.submit("/mcp".to_string(), &mut ui_state, &receiver, test_area());

    assert!(!submitted);
    assert_eq!(ui_state.status, "showing MCP servers");
    let modal = ui_state.modals.mcp_modal.as_ref().unwrap();
    assert_eq!(modal.rows.len(), 2);
    assert_eq!(modal.rows[0].name, "alpha");
    assert_eq!(modal.rows[0].kind, "stdio");
    assert!(modal.rows[0].enabled);
    assert_eq!(modal.rows[1].name, "beta");
    assert_eq!(modal.rows[1].kind, "http");
    assert!(!modal.rows[1].enabled);
    assert!(app.worker.is_none());
    assert!(!app.active_run);
    assert!(receiver.try_recv().is_err());
}

#[test]
fn submit_mcp_extra_reports_usage_without_opening_modal() {
    let temp = tempfile::TempDir::new().unwrap();
    let (sender, receiver) = bounded::<TuiEvent>(4);
    let mut app = test_app(&temp, sender);
    let mut ui_state = state::MissionControlState::default();

    let submitted = app.submit(
        "/mcp extra".to_string(),
        &mut ui_state,
        &receiver,
        test_area(),
    );

    assert!(!submitted);
    assert_eq!(ui_state.status, "usage: /mcp");
    assert!(!ui_state.mcp_modal_visible());
    assert!(app.worker.is_none());
    assert!(!app.active_run);
    assert!(receiver.try_recv().is_err());
}

#[test]
fn set_mcp_server_enabled_persists_setting_without_reloading_runtime_manager() {
    let temp = tempfile::TempDir::new().unwrap();
    let (sender, _receiver) = bounded::<TuiEvent>(1);
    let mut app = test_app(&temp, sender);
    crate::config::write_settings(
        &app.config.paths,
        &crate::config::Settings {
            mcp_servers: std::collections::BTreeMap::from([(
                "alpha".to_string(),
                crate::config::McpServerConfig::Stdio(crate::config::McpStdioServerConfig {
                    command: "alpha-mcp".to_string(),
                    args: Vec::new(),
                    env: std::collections::BTreeMap::new(),
                    enabled: true,
                    timeout: None,
                }),
            )]),
            ..Default::default()
        },
    )
    .unwrap();
    let runtime_manager = std::sync::Arc::new(std::sync::Mutex::new(
        crate::mcp::manager::McpManager::from_settings(&crate::config::McpServersSettings::new()),
    ));
    app.mcp = Some(std::sync::Arc::clone(&runtime_manager));
    let mut ui_state = state::MissionControlState::default();

    app.set_mcp_server_enabled("alpha", false, &mut ui_state);
    reap_owned_worker(
        &mut app,
        &mut ui_state,
        MissionControlApp::reap_settings_persistence_worker,
    );

    assert_eq!(
        ui_state.status,
        "MCP server setting saved; takes effect next magi-code launch"
    );
    assert!(
        app.mcp
            .as_ref()
            .is_some_and(|current| std::sync::Arc::ptr_eq(current, &runtime_manager))
    );
    let settings = crate::config::read_settings(&app.config.paths).unwrap();
    assert!(!settings.mcp_servers.get("alpha").unwrap().enabled());
    let raw: serde_json::Value =
        serde_json::from_str(&std::fs::read_to_string(&app.config.paths.settings_file).unwrap())
            .unwrap();
    assert_eq!(raw["capabilities"]["mcp"]["alpha"]["enabled"], false);
}

#[test]
fn failed_mcp_server_enabled_save_rolls_back_optimistic_row() {
    let temp = tempfile::TempDir::new().unwrap();
    let (sender, _receiver) = bounded::<TuiEvent>(1);
    let mut app = test_app(&temp, sender);
    crate::config::write_settings(&app.config.paths, &crate::config::Settings::default()).unwrap();
    let mut ui_state = state::MissionControlState::default();
    ui_state.open_mcp_modal(
        vec![state::McpServerToggleRow {
            name: "missing-server".to_string(),
            kind: "stdio",
            enabled: false,
        }],
        1,
    );

    app.set_mcp_server_enabled("missing-server", false, &mut ui_state);
    reap_owned_worker(
        &mut app,
        &mut ui_state,
        MissionControlApp::reap_settings_persistence_worker,
    );

    let modal = ui_state.modals.mcp_modal.as_ref().unwrap();
    assert!(modal.rows[0].enabled);
    assert!(
        ui_state
            .status
            .contains("failed to save setting: mcp server not found: missing-server"),
        "{}",
        ui_state.status
    );
}

#[test]
fn submit_compact_requires_active_session_and_creates_no_worker() {
    let temp = tempfile::TempDir::new().unwrap();
    let (sender, receiver) = bounded::<TuiEvent>(4);
    let mut app = test_app(&temp, sender);
    let mut ui_state = state::MissionControlState::default();

    app.submit(
        "/compact".to_string(),
        &mut ui_state,
        &receiver,
        test_area(),
    );

    assert_eq!(
        ui_state.status,
        "/compact requires an active persisted session; start without --no-session or run /new"
    );
    assert!(receiver.try_recv().is_err());
}