magi-code 0.96.1

Repository-aware CLI coding agent for terminal work
Documentation
use crate::{
    instructions::InstructionFile,
    sessions::{
        MAX_METADATA_VISIT_BYTES, MAX_METADATA_VISIT_LINES, Session, SessionEventKind,
        report_session_diagnostic,
    },
};
use std::{collections::HashSet, path::PathBuf};

#[derive(Debug, Default)]
pub(crate) struct SubdirInstructionState {
    claimed: HashSet<PathBuf>,
}

impl SubdirInstructionState {
    pub(crate) fn new(initial_instructions: &[InstructionFile], session: Option<&Session>) -> Self {
        let mut state = Self::default();
        state.seed_initial(initial_instructions);
        if let Some(session) = session {
            state.seed_from_full_session_log(session);
        }
        state
    }

    pub(crate) fn claimed_mut(&mut self) -> &mut HashSet<PathBuf> {
        &mut self.claimed
    }

    pub(crate) fn seed_initial(&mut self, instructions: &[InstructionFile]) {
        for instruction in instructions {
            let canonical = instruction
                .path
                .canonicalize()
                .unwrap_or_else(|_| instruction.path.clone());
            self.claimed.insert(canonical);
        }
    }

    pub(crate) fn seed_from_full_session_log(&mut self, session: &Session) {
        let events = match session
            .read_events_tolerant_bounded(MAX_METADATA_VISIT_LINES, MAX_METADATA_VISIT_BYTES)
        {
            Ok(events) => events,
            Err(error) => {
                report_session_diagnostic(
                    crate::sessions::SessionDiagnosticOperation::Replay,
                    session.path(),
                    &error,
                );
                return;
            }
        };
        for event in events.events {
            match event.kind() {
                Some(SessionEventKind::SubdirInstructionLoad) => {
                    if event
                        .payload
                        .get("source")
                        .and_then(serde_json::Value::as_str)
                        == Some("subdir_agents")
                        && event
                            .payload
                            .get("status")
                            .and_then(serde_json::Value::as_str)
                            == Some("success")
                        && let Some(path) = event
                            .payload
                            .get("path")
                            .and_then(serde_json::Value::as_str)
                    {
                        self.claimed.insert(PathBuf::from(path));
                    }
                }
                Some(SessionEventKind::ProviderContextItem) => {
                    if event
                        .payload
                        .get("source")
                        .and_then(serde_json::Value::as_str)
                        == Some("subdir_agents")
                        && let Some(path) = event
                            .payload
                            .get("path")
                            .and_then(serde_json::Value::as_str)
                    {
                        self.claimed.insert(PathBuf::from(path));
                    }
                }
                _ => {}
            }
        }
    }
}