use std::sync::Arc;
use async_trait::async_trait;
use synaptic_core::{MemoryStore, Message, SynapticError};
pub struct ConversationTokenBufferMemory {
store: Arc<dyn MemoryStore>,
max_tokens: usize,
}
impl ConversationTokenBufferMemory {
pub fn new(store: Arc<dyn MemoryStore>, max_tokens: usize) -> Self {
Self { store, max_tokens }
}
pub fn estimate_tokens(text: &str) -> usize {
text.len() / 4 + 1
}
}
#[async_trait]
impl MemoryStore for ConversationTokenBufferMemory {
async fn append(&self, session_id: &str, message: Message) -> Result<(), SynapticError> {
self.store.append(session_id, message).await
}
async fn load(&self, session_id: &str) -> Result<Vec<Message>, SynapticError> {
let messages = self.store.load(session_id).await?;
let total_tokens: usize = messages
.iter()
.map(|m| Self::estimate_tokens(m.content()))
.sum();
if total_tokens <= self.max_tokens {
return Ok(messages);
}
let mut kept = messages;
let mut current_tokens: usize = kept
.iter()
.map(|m| Self::estimate_tokens(m.content()))
.sum();
while current_tokens > self.max_tokens && !kept.is_empty() {
let removed = kept.remove(0);
current_tokens -= Self::estimate_tokens(removed.content());
}
Ok(kept)
}
async fn clear(&self, session_id: &str) -> Result<(), SynapticError> {
self.store.clear(session_id).await
}
}