magi-code 0.96.1

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

impl MissionControlState {
    pub(crate) fn invalidate_transcript_cache(&self) {
        self.final_assistant_plain_first_entries
            .borrow_mut()
            .clear();
        self.final_assistant_rich_refresh_entries
            .borrow_mut()
            .clear();
        self.final_assistant_plain_first_enabled.set(false);
        self.bump_transcript_visual_generation();
        self.transcript_cache.borrow_mut().clear();
    }

    pub(crate) fn transcript_absolute_index(&self, local_index: usize) -> Option<usize> {
        self.transcript.absolute_index(local_index)
    }

    pub(crate) fn transcript_local_index(&self, absolute_index: usize) -> Option<usize> {
        self.transcript.local_index(absolute_index)
    }

    pub(crate) fn transcript_timestamp(&self, local_index: usize) -> Option<DateTime<Local>> {
        self.transcript.timestamp(local_index)
    }

    pub(super) fn invalidate_transcript_front_cache(&self, old_base: usize, drained: usize) {
        if drained == 0 {
            return;
        }
        for index in old_base..old_base.saturating_add(drained) {
            self.final_assistant_plain_first_entries
                .borrow_mut()
                .remove(&index);
            self.final_assistant_rich_refresh_entries
                .borrow_mut()
                .remove(&index);
        }
        self.final_assistant_plain_first_enabled.set(false);
        self.bump_transcript_visual_generation();
        self.transcript_cache
            .borrow_mut()
            .evict_front(old_base, drained);
    }

    pub(super) fn invalidate_transcript_visual_projection_cache(&self) {
        self.bump_transcript_visual_generation();
        self.transcript_cache.borrow_mut().clear_visual_aggregates();
    }

    pub(super) fn invalidate_transcript_entry_cache(&self, entry_index: usize) {
        let Some(absolute_index) = self.transcript_absolute_index(entry_index) else {
            return;
        };
        self.mark_transcript_entry_changed(absolute_index);
        self.final_assistant_plain_first_entries
            .borrow_mut()
            .remove(&absolute_index);
        self.final_assistant_rich_refresh_entries
            .borrow_mut()
            .remove(&absolute_index);
        self.final_assistant_plain_first_enabled.set(false);
        self.bump_transcript_visual_generation();
        self.transcript_cache
            .borrow_mut()
            .evict_card(absolute_index);
    }

    pub(super) fn invalidate_transcript_entries_cache(
        &self,
        entry_indices: impl IntoIterator<Item = usize>,
    ) {
        let entry_indices = entry_indices
            .into_iter()
            .filter_map(|index| self.transcript_absolute_index(index))
            .collect::<Vec<_>>();
        if entry_indices.is_empty() {
            return;
        }
        for &entry_index in &entry_indices {
            self.mark_transcript_entry_changed(entry_index);
        }
        self.bump_transcript_visual_generation();
        self.transcript_cache
            .borrow_mut()
            .evict_cards(entry_indices);
    }

    pub(super) fn mark_transcript_entry_changed(&self, absolute_index: usize) {
        self.transcript.mark_changed(absolute_index);
    }

    pub(crate) fn transcript_entry_revision(&self, local_index: usize) -> u64 {
        self.transcript.entry_revision(local_index)
    }

    pub(crate) fn transcript_visual_generation(&self) -> u64 {
        self.transcript_visual_generation.get()
    }

    pub(super) fn bump_transcript_visual_generation(&self) {
        self.transcript_visual_generation
            .set(self.transcript_visual_generation.get().wrapping_add(1));
    }

    pub(crate) fn final_assistant_plain_first_marker(&self, entry_index: usize) -> u8 {
        let Some(entry_index) = self.transcript_absolute_index(entry_index) else {
            return 0;
        };
        if self.final_assistant_plain_first_enabled.get()
            && self
                .final_assistant_plain_first_entries
                .borrow()
                .contains(&entry_index)
        {
            1
        } else if self
            .final_assistant_rich_refresh_entries
            .borrow()
            .contains(&entry_index)
        {
            2
        } else {
            0
        }
    }

    pub(crate) fn begin_final_assistant_plain_first_paint(&mut self) -> bool {
        if self.transcript_selection_active()
            || self.final_assistant_plain_first_enabled.get()
            || self.final_assistant_plain_first_entries.borrow().is_empty()
        {
            return false;
        }
        self.final_assistant_plain_first_enabled.set(true);
        self.bump_transcript_visual_generation();
        true
    }

    pub(crate) fn finish_final_assistant_plain_first_paint(&mut self) -> bool {
        if !self.final_assistant_plain_first_enabled.get() {
            return false;
        }
        let entries = self
            .final_assistant_plain_first_entries
            .borrow_mut()
            .drain()
            .collect::<Vec<_>>();
        self.final_assistant_plain_first_enabled.set(false);
        if entries.is_empty() {
            return false;
        }
        self.final_assistant_rich_refresh_entries
            .borrow_mut()
            .extend(entries);
        self.bump_transcript_visual_generation();
        true
    }

    pub(super) fn mark_final_assistant_plain_first(&self, entry_index: Option<usize>) {
        let Some(entry_index) = entry_index.and_then(|index| self.transcript_absolute_index(index))
        else {
            return;
        };
        self.final_assistant_rich_refresh_entries
            .borrow_mut()
            .remove(&entry_index);
        self.final_assistant_plain_first_entries
            .borrow_mut()
            .insert(entry_index);
        self.bump_transcript_visual_generation();
    }

    pub(super) fn invalidate_transcript_append_cache(&self, drained: usize) {
        if drained == 0 {
            self.invalidate_transcript_visual_projection_cache();
        }
    }

    pub(super) fn invalidate_transcript_changed_entry_cache(
        &self,
        drained: usize,
        entry_index: Option<usize>,
    ) {
        if drained == 0 {
            if let Some(entry_index) = entry_index {
                self.invalidate_transcript_entry_cache(entry_index);
            } else {
                self.invalidate_transcript_visual_projection_cache();
            }
        }
    }

    pub(crate) fn transcript_selection_active(&self) -> bool {
        self.selection
            .as_ref()
            .is_some_and(|selection| selection.pane == TuiPane::Transcript)
    }
}