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<&str>;
61
62 fn set_session_id(&mut self, session_id: String);
64}
65
66#[derive(Debug, Clone)]
68pub struct PersistenceConfig {
69 pub auto_save: bool,
71
72 pub auto_load: bool,
74
75 pub max_messages: usize,
77
78 pub token_limit: usize,
80}
81
82impl Default for PersistenceConfig {
83 fn default() -> Self {
84 Self {
85 auto_save: true,
86 auto_load: true,
87 max_messages: 100,
88 token_limit: 4000,
89 }
90 }
91}
92
93impl PersistenceConfig {
94 pub fn new() -> Self {
95 Self::default()
96 }
97
98 pub fn with_auto_save(mut self, auto_save: bool) -> Self {
99 self.auto_save = auto_save;
100 self
101 }
102
103 pub fn with_auto_load(mut self, auto_load: bool) -> Self {
104 self.auto_load = auto_load;
105 self
106 }
107
108 pub fn with_max_messages(mut self, max_messages: usize) -> Self {
109 self.max_messages = max_messages;
110 self
111 }
112
113 pub fn with_token_limit(mut self, token_limit: usize) -> Self {
114 self.token_limit = token_limit;
115 self
116 }
117}
118
119#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
121pub struct MemoryData {
122 pub session_id: String,
124
125 pub messages: Vec<lc_schema::Message>,
127
128 pub summary: Option<String>,
130
131 pub metadata: std::collections::HashMap<String, String>,
133
134 pub created_at: String,
136
137 pub updated_at: String,
139}
140
141impl MemoryData {
142 pub fn new(session_id: String) -> Self {
143 let now = chrono::Utc::now().to_rfc3339();
144 Self {
145 session_id,
146 messages: Vec::new(),
147 summary: None,
148 metadata: std::collections::HashMap::new(),
149 created_at: now.clone(),
150 updated_at: now,
151 }
152 }
153
154 pub fn with_messages(mut self, messages: Vec<lc_schema::Message>) -> Self {
155 self.messages = messages;
156 self.updated_at = chrono::Utc::now().to_rfc3339();
157 self
158 }
159
160 pub fn with_summary(mut self, summary: String) -> Self {
161 self.summary = Some(summary);
162 self.updated_at = chrono::Utc::now().to_rfc3339();
163 self
164 }
165
166 pub fn add_message(&mut self, message: lc_schema::Message) {
167 self.messages.push(message);
168 self.updated_at = chrono::Utc::now().to_rfc3339();
169 }
170
171 pub fn set_summary(&mut self, summary: String) {
172 self.summary = Some(summary);
173 self.updated_at = chrono::Utc::now().to_rfc3339();
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 #[test]
182 fn test_persistence_config_default() {
183 let config = PersistenceConfig::default();
184 assert!(config.auto_save);
185 assert!(config.auto_load);
186 assert_eq!(config.max_messages, 100);
187 assert_eq!(config.token_limit, 4000);
188 }
189
190 #[test]
191 fn test_persistence_config_custom() {
192 let config = PersistenceConfig::new()
193 .with_auto_save(false)
194 .with_max_messages(50)
195 .with_token_limit(2000);
196
197 assert!(!config.auto_save);
198 assert_eq!(config.max_messages, 50);
199 assert_eq!(config.token_limit, 2000);
200 }
201
202 #[test]
203 fn test_memory_data_new() {
204 let data = MemoryData::new("session_123".to_string());
205 assert_eq!(data.session_id, "session_123");
206 assert!(data.messages.is_empty());
207 assert!(data.summary.is_none());
208 }
209
210 #[test]
211 fn test_memory_data_with_messages() {
212 let messages = vec![
213 lc_schema::Message::human("Hello"),
214 lc_schema::Message::ai("Hi!"),
215 ];
216
217 let data = MemoryData::new("session_123".to_string()).with_messages(messages);
218
219 assert_eq!(data.messages.len(), 2);
220 }
221}