vv-agent 0.4.8

VectorVein agent runtime, SDK, CLI, tools, and workspace backends
Documentation
use super::{
    helpers::{adjust_start_for_tool_context, sanitize_empty_assistant_messages},
    MemoryManager,
};
use crate::types::{Message, MessageRole};

impl MemoryManager {
    pub fn emergency_compact(&self, messages: &[Message], drop_ratio: f64) -> Vec<Message> {
        if messages.len() <= 2 {
            return messages.to_vec();
        }

        let (system_message, non_system) = if messages
            .first()
            .is_some_and(|message| message.role == MessageRole::System)
        {
            (messages.first().cloned(), &messages[1..])
        } else {
            (None, messages)
        };
        if non_system.is_empty() {
            return system_message.into_iter().collect();
        }

        let keep_count = self.config.keep_recent_messages.max(1);
        let clamped_ratio = drop_ratio.clamp(0.0, 0.95);
        let max_droppable = non_system.len().saturating_sub(keep_count);
        let drop_count = if max_droppable == 0 {
            0
        } else {
            ((non_system.len() as f64 * clamped_ratio).floor() as usize)
                .max(1)
                .min(max_droppable)
        };
        let mut start_index = drop_count.min(non_system.len());
        if non_system.len().saturating_sub(start_index) < keep_count {
            start_index = non_system.len().saturating_sub(keep_count);
        }
        start_index = adjust_start_for_tool_context(non_system, start_index);

        let mut compacted = Vec::new();
        if let Some(system_message) = system_message {
            compacted.push(system_message);
        }
        compacted.extend_from_slice(&non_system[start_index..]);
        sanitize_empty_assistant_messages(compacted)
    }
}