magi-code 0.104.0

Repository-aware CLI coding agent for terminal work
Documentation
use super::MissionControlApp;
use crate::tui::state::{MissionControlState, ModalKind};
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use std::time::{Duration, Instant};

impl MissionControlApp {
    pub(super) fn open_background_jobs(&mut self, ui: &mut MissionControlState) {
        if ui.transcript_only_layout {
            ui.status = "/background-jobs is available in the primary conversation".into();
            return;
        }
        ui.focus_header_modal(ModalKind::BackgroundJobs);
        ui.hide_autocomplete();
        self.background_jobs_refresh = None;
        self.refresh_background_jobs(ui);
    }

    pub(super) fn refresh_background_jobs(&mut self, ui: &mut MissionControlState) -> bool {
        if !ui.modals.header_modals.contains(&ModalKind::BackgroundJobs) {
            return false;
        }
        if self
            .background_jobs_refresh
            .is_some_and(|last| last.elapsed() < Duration::from_millis(250))
        {
            return false;
        }
        self.background_jobs_refresh = Some(Instant::now());
        let Some(jobs) = self.state.bash_jobs.running_snapshot() else {
            return false;
        };
        let modal = &mut ui.modals.background_jobs;
        let changed = modal.jobs != jobs || !modal.loaded;
        let selected_id = modal.jobs.get(modal.selected).map(|job| job.id.as_str());
        modal.selected = selected_id
            .and_then(|id| jobs.iter().position(|job| job.id == id))
            .unwrap_or_else(|| modal.selected.min(jobs.len().saturating_sub(1)));
        modal.jobs = jobs;
        modal.loaded = true;
        changed
    }

    pub(super) fn handle_background_jobs_key(
        &mut self,
        key: KeyEvent,
        ui: &mut MissionControlState,
    ) {
        if key.modifiers != KeyModifiers::NONE {
            return;
        }
        let modal = &mut ui.modals.background_jobs;
        match key.code {
            KeyCode::Up => modal.selected = modal.selected.saturating_sub(1),
            KeyCode::Down => {
                modal.selected = (modal.selected + 1).min(modal.jobs.len().saturating_sub(1))
            }
            crate::tui::input::BACKGROUND_JOB_KILL_KEY => {
                if let Some(job) = modal.jobs.get(modal.selected) {
                    modal.notice = match self.state.bash_jobs.request_stop(&job.id) {
                        Ok(()) => format!("Stop requested for PID {}", job.pid),
                        Err(error) => error.to_string(),
                    };
                    self.background_jobs_refresh = None;
                    self.refresh_background_jobs(ui);
                }
            }
            _ => {}
        }
    }
}