Skip to main content

synaptic_condenser/
rolling.rs

1use crate::Condenser;
2use async_trait::async_trait;
3use synaptic_core::{Message, SynapticError};
4
5/// Keeps only the most recent N messages, optionally preserving the system message.
6pub struct RollingCondenser {
7    pub max_messages: usize,
8    pub preserve_system: bool,
9}
10
11impl RollingCondenser {
12    pub fn new(max_messages: usize) -> Self {
13        Self {
14            max_messages,
15            preserve_system: true,
16        }
17    }
18
19    pub fn with_preserve_system(mut self, preserve: bool) -> Self {
20        self.preserve_system = preserve;
21        self
22    }
23}
24
25#[async_trait]
26impl Condenser for RollingCondenser {
27    async fn condense(&self, messages: Vec<Message>) -> Result<Vec<Message>, SynapticError> {
28        if messages.len() <= self.max_messages {
29            return Ok(messages);
30        }
31
32        if self.preserve_system && !messages.is_empty() && messages[0].is_system() {
33            let system = messages[0].clone();
34            let rest = &messages[1..];
35            let keep = if self.max_messages > 0 {
36                self.max_messages - 1
37            } else {
38                0
39            };
40            let start = rest.len().saturating_sub(keep);
41            let mut result = vec![system];
42            result.extend_from_slice(&rest[start..]);
43            Ok(result)
44        } else {
45            let start = messages.len().saturating_sub(self.max_messages);
46            Ok(messages[start..].to_vec())
47        }
48    }
49}