vv_agent/memory/manager/
emergency.rs1use super::{
2 helpers::{adjust_start_for_tool_context, sanitize_empty_assistant_messages},
3 MemoryManager,
4};
5use crate::types::{Message, MessageRole};
6
7impl MemoryManager {
8 pub fn emergency_compact(&self, messages: &[Message], drop_ratio: f64) -> Vec<Message> {
9 if messages.len() <= 2 {
10 return messages.to_vec();
11 }
12
13 let (system_message, non_system) = if messages
14 .first()
15 .is_some_and(|message| message.role == MessageRole::System)
16 {
17 (messages.first().cloned(), &messages[1..])
18 } else {
19 (None, messages)
20 };
21 if non_system.is_empty() {
22 return system_message.into_iter().collect();
23 }
24
25 let keep_count = self.config.keep_recent_messages.max(1);
26 let clamped_ratio = drop_ratio.clamp(0.0, 0.95);
27 let max_droppable = non_system.len().saturating_sub(keep_count);
28 let drop_count = if max_droppable == 0 {
29 0
30 } else {
31 ((non_system.len() as f64 * clamped_ratio).floor() as usize)
32 .max(1)
33 .min(max_droppable)
34 };
35 let mut start_index = drop_count.min(non_system.len());
36 if non_system.len().saturating_sub(start_index) < keep_count {
37 start_index = non_system.len().saturating_sub(keep_count);
38 }
39 start_index = adjust_start_for_tool_context(non_system, start_index);
40
41 let mut compacted = Vec::new();
42 if let Some(system_message) = system_message {
43 compacted.push(system_message);
44 }
45 compacted.extend_from_slice(&non_system[start_index..]);
46 sanitize_empty_assistant_messages(compacted)
47 }
48}