use async_trait::async_trait;
use super::base::{BaseMemory, MemoryError};
#[async_trait]
pub trait PersistentMemory: BaseMemory {
async fn load_from_store(&mut self, session_id: &str) -> Result<(), MemoryError>;
async fn save_to_store(&mut self, session_id: &str) -> Result<(), MemoryError>;
async fn delete_session(&self, session_id: &str) -> Result<(), MemoryError>;
async fn session_exists(&self, session_id: &str) -> Result<bool, MemoryError>;
fn current_session_id(&self) -> Option<&str>;
fn set_session_id(&mut self, session_id: String);
}
#[derive(Debug, Clone)]
pub struct PersistenceConfig {
pub auto_save: bool,
pub auto_load: bool,
pub max_messages: usize,
pub token_limit: usize,
}
impl Default for PersistenceConfig {
fn default() -> Self {
Self {
auto_save: true,
auto_load: true,
max_messages: 100,
token_limit: 4000,
}
}
}
impl PersistenceConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_auto_save(mut self, auto_save: bool) -> Self {
self.auto_save = auto_save;
self
}
pub fn with_auto_load(mut self, auto_load: bool) -> Self {
self.auto_load = auto_load;
self
}
pub fn with_max_messages(mut self, max_messages: usize) -> Self {
self.max_messages = max_messages;
self
}
pub fn with_token_limit(mut self, token_limit: usize) -> Self {
self.token_limit = token_limit;
self
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct MemoryData {
pub session_id: String,
pub messages: Vec<crate::schema::Message>,
pub summary: Option<String>,
pub metadata: std::collections::HashMap<String, String>,
pub created_at: String,
pub updated_at: String,
}
impl MemoryData {
pub fn new(session_id: String) -> Self {
let now = chrono::Utc::now().to_rfc3339();
Self {
session_id,
messages: Vec::new(),
summary: None,
metadata: std::collections::HashMap::new(),
created_at: now.clone(),
updated_at: now,
}
}
pub fn with_messages(mut self, messages: Vec<crate::schema::Message>) -> Self {
self.messages = messages;
self.updated_at = chrono::Utc::now().to_rfc3339();
self
}
pub fn with_summary(mut self, summary: String) -> Self {
self.summary = Some(summary);
self.updated_at = chrono::Utc::now().to_rfc3339();
self
}
pub fn add_message(&mut self, message: crate::schema::Message) {
self.messages.push(message);
self.updated_at = chrono::Utc::now().to_rfc3339();
}
pub fn set_summary(&mut self, summary: String) {
self.summary = Some(summary);
self.updated_at = chrono::Utc::now().to_rfc3339();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_persistence_config_default() {
let config = PersistenceConfig::default();
assert!(config.auto_save);
assert!(config.auto_load);
assert_eq!(config.max_messages, 100);
assert_eq!(config.token_limit, 4000);
}
#[test]
fn test_persistence_config_custom() {
let config = PersistenceConfig::new()
.with_auto_save(false)
.with_max_messages(50)
.with_token_limit(2000);
assert!(!config.auto_save);
assert_eq!(config.max_messages, 50);
assert_eq!(config.token_limit, 2000);
}
#[test]
fn test_memory_data_new() {
let data = MemoryData::new("session_123".to_string());
assert_eq!(data.session_id, "session_123");
assert!(data.messages.is_empty());
assert!(data.summary.is_none());
}
#[test]
fn test_memory_data_with_messages() {
let messages = vec![
crate::schema::Message::human("Hello"),
crate::schema::Message::ai("Hi!"),
];
let data = MemoryData::new("session_123".to_string())
.with_messages(messages);
assert_eq!(data.messages.len(), 2);
}
}