1use super::base::{BaseMemory, MemoryError};
8use async_trait::async_trait;
9
10#[async_trait]
29pub trait PersistentMemory: BaseMemory {
30 async fn load_from_store(&mut self, session_id: &str) -> Result<(), MemoryError>;
38
39 async fn save_to_store(&mut self, session_id: &str) -> Result<(), MemoryError>;
46
47 async fn delete_session(&self, session_id: &str) -> Result<(), MemoryError>;
52
53 async fn session_exists(&self, session_id: &str) -> Result<bool, MemoryError>;
58
59 fn current_session_id(&self) -> Option<String>;
64
65 fn set_session_id(&mut self, session_id: String);
67}
68
69#[derive(Debug, Clone)]
75pub struct PersistenceConfig {
76 pub auto_save: bool,
78
79 pub auto_load: bool,
81
82 pub token_limit: usize,
84}
85
86impl Default for PersistenceConfig {
87 fn default() -> Self {
88 Self {
89 auto_save: true,
90 auto_load: true,
91 token_limit: 4000,
92 }
93 }
94}
95
96impl PersistenceConfig {
97 pub fn new() -> Self {
98 Self::default()
99 }
100
101 pub fn with_auto_save(mut self, auto_save: bool) -> Self {
102 self.auto_save = auto_save;
103 self
104 }
105
106 pub fn with_auto_load(mut self, auto_load: bool) -> Self {
107 self.auto_load = auto_load;
108 self
109 }
110
111 pub fn with_token_limit(mut self, token_limit: usize) -> Self {
112 self.token_limit = token_limit;
113 self
114 }
115}
116
117#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
119pub struct MemoryData {
120 pub session_id: String,
122
123 pub messages: Vec<lc_schema::Message>,
125
126 pub summary: Option<String>,
128
129 pub metadata: std::collections::HashMap<String, String>,
131
132 pub created_at: String,
134
135 pub updated_at: String,
137
138 #[serde(default)]
141 pub version: u64,
142}
143
144impl MemoryData {
145 pub fn new(session_id: String) -> Self {
146 let now = chrono::Utc::now().to_rfc3339();
147 Self {
148 session_id,
149 messages: Vec::new(),
150 summary: None,
151 metadata: std::collections::HashMap::new(),
152 created_at: now.clone(),
153 updated_at: now,
154 version: 0,
155 }
156 }
157
158 pub fn with_messages(mut self, messages: Vec<lc_schema::Message>) -> Self {
159 self.messages = messages;
160 self.updated_at = chrono::Utc::now().to_rfc3339();
161 self
162 }
163
164 pub fn with_summary(mut self, summary: String) -> Self {
165 self.summary = Some(summary);
166 self.updated_at = chrono::Utc::now().to_rfc3339();
167 self
168 }
169
170 pub fn add_message(&mut self, message: lc_schema::Message) {
171 self.messages.push(message);
172 self.updated_at = chrono::Utc::now().to_rfc3339();
173 }
174
175 pub fn set_summary(&mut self, summary: String) {
176 self.summary = Some(summary);
177 self.updated_at = chrono::Utc::now().to_rfc3339();
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184
185 #[test]
186 fn test_persistence_config_default() {
187 let config = PersistenceConfig::default();
188 assert!(config.auto_save);
189 assert!(config.auto_load);
190 assert_eq!(config.token_limit, 4000);
191 }
192
193 #[test]
194 fn test_persistence_config_custom() {
195 let config = PersistenceConfig::new()
196 .with_auto_save(false)
197 .with_token_limit(2000);
198
199 assert!(!config.auto_save);
200 assert_eq!(config.token_limit, 2000);
201 }
202
203 #[test]
204 fn test_memory_data_new() {
205 let data = MemoryData::new("session_123".to_string());
206 assert_eq!(data.session_id, "session_123");
207 assert!(data.messages.is_empty());
208 assert!(data.summary.is_none());
209 }
210
211 #[test]
212 fn test_memory_data_with_messages() {
213 let messages = vec![
214 lc_schema::Message::human("Hello"),
215 lc_schema::Message::ai("Hi!"),
216 ];
217
218 let data = MemoryData::new("session_123".to_string()).with_messages(messages);
219
220 assert_eq!(data.messages.len(), 2);
221 }
222}