magi-code 0.96.1

Repository-aware CLI coding agent for terminal work
Documentation
use std::{
    io::Write,
    marker::PhantomData,
    panic::{self, PanicHookInfo},
    rc::Rc,
    sync::{Arc, Mutex},
    thread,
};

type PanicHook = dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static;

#[derive(Default)]
struct BackgroundPanicReport {
    count: usize,
    first_location: Option<String>,
}

/// Outlives the app and its terminal guard, so deferred diagnostics are printed
/// only after terminal cleanup. Worker results still report failures in the UI.
pub(in crate::tui) struct TerminalPanicHook {
    previous: Arc<PanicHook>,
    background_panics: Arc<Mutex<Option<BackgroundPanicReport>>>,
    // Installation and teardown belong to the terminal owner.
    _owner_only: PhantomData<Rc<()>>,
}

impl TerminalPanicHook {
    pub(in crate::tui) fn install() -> Self {
        Self::install_with_restore(super::restore_terminal_best_effort)
    }

    fn install_with_restore(restore: impl Fn() + Send + Sync + 'static) -> Self {
        let owner = thread::current().id();
        let previous: Arc<PanicHook> = panic::take_hook().into();
        let background_panics = Arc::new(Mutex::new(Some(BackgroundPanicReport::default())));
        let hook_previous = Arc::clone(&previous);
        let hook_panics = Arc::clone(&background_panics);
        panic::set_hook(Box::new(move |info| {
            let active = {
                let mut panics = hook_panics.lock().unwrap_or_else(|e| e.into_inner());
                if let Some(report) = panics.as_mut() {
                    // An aborting build cannot reconcile worker failures: restore
                    // immediately on every thread before the process terminates.
                    if cfg!(panic = "unwind") && thread::current().id() != owner {
                        report.count = report.count.saturating_add(1);
                        if report.first_location.is_none() {
                            report.first_location = info.location().map(|location| {
                                let file: String = location.file().chars().take(256).collect();
                                format!("{file}:{}", location.line())
                            });
                        }
                        return;
                    }
                    true
                } else {
                    false
                }
            };
            if active {
                restore();
            }
            hook_previous(info);
        }));
        Self {
            previous,
            background_panics,
            _owner_only: PhantomData,
        }
    }
}

impl Drop for TerminalPanicHook {
    fn drop(&mut self) {
        let report = self
            .background_panics
            .lock()
            .unwrap_or_else(|e| e.into_inner())
            .take()
            .unwrap_or_default();
        // set_hook is forbidden while unwinding. The installed closure becomes
        // a passthrough in that case, without retaining terminal ownership.
        if !thread::panicking() {
            let previous = Arc::clone(&self.previous);
            panic::set_hook(Box::new(move |info| previous(info)));
        }
        if report.count > 0 {
            // Retain only bounded source metadata, never arbitrary panic payloads.
            let location = report
                .first_location
                .as_deref()
                .unwrap_or("unknown location");
            let _ = writeln!(
                std::io::stderr(),
                "Mission Control: {} background worker panic(s) occurred; first at {location}.",
                report.count
            );
        }
    }
}