autoagents_core/agent/memory/
mod.rs

1use async_trait::async_trait;
2use autoagents_llm::{chat::ChatMessage, error::LLMError};
3use regex::Regex;
4use serde::{Deserialize, Serialize};
5use std::sync::Arc;
6#[cfg(not(target_arch = "wasm32"))]
7use tokio::sync::broadcast;
8
9mod sliding_window;
10pub use sliding_window::SlidingWindowMemory;
11
12#[cfg(test)]
13mod tests {
14    use super::*;
15    use autoagents_llm::chat::{ChatMessage, ChatRole, MessageType};
16    use autoagents_llm::error::LLMError;
17    use std::sync::Arc;
18
19    // Mock memory provider for testing
20    struct MockMemoryProvider {
21        messages: Vec<ChatMessage>,
22        should_fail: bool,
23    }
24
25    impl MockMemoryProvider {
26        fn new() -> Self {
27            Self {
28                messages: Vec::new(),
29                should_fail: false,
30            }
31        }
32
33        fn with_failure() -> Self {
34            Self {
35                messages: Vec::new(),
36                should_fail: true,
37            }
38        }
39
40        fn with_messages(messages: Vec<ChatMessage>) -> Self {
41            Self {
42                messages,
43                should_fail: false,
44            }
45        }
46    }
47
48    #[async_trait::async_trait]
49    impl MemoryProvider for MockMemoryProvider {
50        async fn remember(&mut self, message: &ChatMessage) -> Result<(), LLMError> {
51            if self.should_fail {
52                return Err(LLMError::ProviderError("Mock memory error".to_string()));
53            }
54            self.messages.push(message.clone());
55            Ok(())
56        }
57
58        async fn recall(
59            &self,
60            _query: &str,
61            limit: Option<usize>,
62        ) -> Result<Vec<ChatMessage>, LLMError> {
63            if self.should_fail {
64                return Err(LLMError::ProviderError("Mock recall error".to_string()));
65            }
66            let limit = limit.unwrap_or(self.messages.len());
67            Ok(self.messages.iter().take(limit).cloned().collect())
68        }
69
70        async fn clear(&mut self) -> Result<(), LLMError> {
71            if self.should_fail {
72                return Err(LLMError::ProviderError("Mock clear error".to_string()));
73            }
74            self.messages.clear();
75            Ok(())
76        }
77
78        fn memory_type(&self) -> MemoryType {
79            MemoryType::SlidingWindow
80        }
81
82        fn size(&self) -> usize {
83            self.messages.len()
84        }
85
86        fn clone_box(&self) -> Box<dyn MemoryProvider> {
87            unimplemented!()
88        }
89    }
90
91    #[test]
92    fn test_memory_type_serialization() {
93        let sliding_window = MemoryType::SlidingWindow;
94        let serialized = serde_json::to_string(&sliding_window).unwrap();
95        assert_eq!(serialized, "\"SlidingWindow\"");
96    }
97
98    #[test]
99    fn test_memory_type_deserialization() {
100        let deserialized: MemoryType = serde_json::from_str("\"SlidingWindow\"").unwrap();
101        assert_eq!(deserialized, MemoryType::SlidingWindow);
102    }
103
104    #[test]
105    fn test_memory_type_debug() {
106        let sliding_window = MemoryType::SlidingWindow;
107        let debug_str = format!("{sliding_window:?}");
108        assert!(debug_str.contains("SlidingWindow"));
109    }
110
111    #[test]
112    fn test_memory_type_clone() {
113        let sliding_window = MemoryType::SlidingWindow;
114        let cloned = sliding_window.clone();
115        assert_eq!(sliding_window, cloned);
116    }
117
118    #[test]
119    fn test_memory_type_equality() {
120        let type1 = MemoryType::SlidingWindow;
121        let type2 = MemoryType::SlidingWindow;
122        assert_eq!(type1, type2);
123    }
124
125    #[test]
126    fn test_message_condition_any() {
127        let condition = MessageCondition::Any;
128        let message = ChatMessage {
129            role: ChatRole::User,
130            message_type: MessageType::Text,
131            content: "test message".to_string(),
132        };
133        let event = MessageEvent {
134            role: "user".to_string(),
135            msg: message,
136        };
137        assert!(condition.matches(&event));
138    }
139
140    #[test]
141    fn test_message_condition_eq() {
142        let condition = MessageCondition::Eq("test message".to_string());
143        let message = ChatMessage {
144            role: ChatRole::User,
145            message_type: MessageType::Text,
146            content: "test message".to_string(),
147        };
148        let event = MessageEvent {
149            role: "user".to_string(),
150            msg: message,
151        };
152        assert!(condition.matches(&event));
153
154        let different_message = ChatMessage {
155            role: ChatRole::User,
156            message_type: MessageType::Text,
157            content: "different message".to_string(),
158        };
159        let different_event = MessageEvent {
160            role: "user".to_string(),
161            msg: different_message,
162        };
163        assert!(!condition.matches(&different_event));
164    }
165
166    #[test]
167    fn test_message_condition_contains() {
168        let condition = MessageCondition::Contains("test".to_string());
169        let message = ChatMessage {
170            role: ChatRole::User,
171            message_type: MessageType::Text,
172            content: "this is a test message".to_string(),
173        };
174        let event = MessageEvent {
175            role: "user".to_string(),
176            msg: message,
177        };
178        assert!(condition.matches(&event));
179
180        let non_matching_message = ChatMessage {
181            role: ChatRole::User,
182            message_type: MessageType::Text,
183            content: "this is different".to_string(),
184        };
185        let non_matching_event = MessageEvent {
186            role: "user".to_string(),
187            msg: non_matching_message,
188        };
189        assert!(!condition.matches(&non_matching_event));
190    }
191
192    #[test]
193    fn test_message_condition_not_contains() {
194        let condition = MessageCondition::NotContains("error".to_string());
195        let message = ChatMessage {
196            role: ChatRole::User,
197            message_type: MessageType::Text,
198            content: "this is a test message".to_string(),
199        };
200        let event = MessageEvent {
201            role: "user".to_string(),
202            msg: message,
203        };
204        assert!(condition.matches(&event));
205
206        let error_message = ChatMessage {
207            role: ChatRole::User,
208            message_type: MessageType::Text,
209            content: "this is an error message".to_string(),
210        };
211        let error_event = MessageEvent {
212            role: "user".to_string(),
213            msg: error_message,
214        };
215        assert!(!condition.matches(&error_event));
216    }
217
218    #[test]
219    fn test_message_condition_role_is() {
220        let condition = MessageCondition::RoleIs("user".to_string());
221        let message = ChatMessage {
222            role: ChatRole::User,
223            message_type: MessageType::Text,
224            content: "test message".to_string(),
225        };
226        let event = MessageEvent {
227            role: "user".to_string(),
228            msg: message,
229        };
230        assert!(condition.matches(&event));
231
232        let assistant_event = MessageEvent {
233            role: "assistant".to_string(),
234            msg: ChatMessage {
235                role: ChatRole::Assistant,
236                message_type: MessageType::Text,
237                content: "test message".to_string(),
238            },
239        };
240        assert!(!condition.matches(&assistant_event));
241    }
242
243    #[test]
244    fn test_message_condition_role_not() {
245        let condition = MessageCondition::RoleNot("system".to_string());
246        let message = ChatMessage {
247            role: ChatRole::User,
248            message_type: MessageType::Text,
249            content: "test message".to_string(),
250        };
251        let event = MessageEvent {
252            role: "user".to_string(),
253            msg: message,
254        };
255        assert!(condition.matches(&event));
256
257        let system_event = MessageEvent {
258            role: "system".to_string(),
259            msg: ChatMessage {
260                role: ChatRole::System,
261                message_type: MessageType::Text,
262                content: "test message".to_string(),
263            },
264        };
265        assert!(!condition.matches(&system_event));
266    }
267
268    #[test]
269    fn test_message_condition_len_gt() {
270        let condition = MessageCondition::LenGt(5);
271        let long_message = ChatMessage {
272            role: ChatRole::User,
273            message_type: MessageType::Text,
274            content: "this is a long message".to_string(),
275        };
276        let long_event = MessageEvent {
277            role: "user".to_string(),
278            msg: long_message,
279        };
280        assert!(condition.matches(&long_event));
281
282        let short_message = ChatMessage {
283            role: ChatRole::User,
284            message_type: MessageType::Text,
285            content: "hi".to_string(),
286        };
287        let short_event = MessageEvent {
288            role: "user".to_string(),
289            msg: short_message,
290        };
291        assert!(!condition.matches(&short_event));
292    }
293
294    #[test]
295    fn test_message_condition_custom() {
296        let condition = MessageCondition::Custom(Arc::new(|msg| msg.content.starts_with("hello")));
297        let hello_message = ChatMessage {
298            role: ChatRole::User,
299            message_type: MessageType::Text,
300            content: "hello world".to_string(),
301        };
302        let hello_event = MessageEvent {
303            role: "user".to_string(),
304            msg: hello_message,
305        };
306        assert!(condition.matches(&hello_event));
307
308        let goodbye_message = ChatMessage {
309            role: ChatRole::User,
310            message_type: MessageType::Text,
311            content: "goodbye world".to_string(),
312        };
313        let goodbye_event = MessageEvent {
314            role: "user".to_string(),
315            msg: goodbye_message,
316        };
317        assert!(!condition.matches(&goodbye_event));
318    }
319
320    #[test]
321    fn test_message_condition_empty() {
322        let condition = MessageCondition::Empty;
323        let empty_message = ChatMessage {
324            role: ChatRole::User,
325            message_type: MessageType::Text,
326            content: "".to_string(),
327        };
328        let empty_event = MessageEvent {
329            role: "user".to_string(),
330            msg: empty_message,
331        };
332        assert!(condition.matches(&empty_event));
333
334        let non_empty_message = ChatMessage {
335            role: ChatRole::User,
336            message_type: MessageType::Text,
337            content: "not empty".to_string(),
338        };
339        let non_empty_event = MessageEvent {
340            role: "user".to_string(),
341            msg: non_empty_message,
342        };
343        assert!(!condition.matches(&non_empty_event));
344    }
345
346    #[test]
347    fn test_message_condition_all() {
348        let condition = MessageCondition::All(vec![
349            MessageCondition::Contains("test".to_string()),
350            MessageCondition::LenGt(5),
351            MessageCondition::RoleIs("user".to_string()),
352        ]);
353
354        let matching_message = ChatMessage {
355            role: ChatRole::User,
356            message_type: MessageType::Text,
357            content: "this is a test message".to_string(),
358        };
359        let matching_event = MessageEvent {
360            role: "user".to_string(),
361            msg: matching_message,
362        };
363        assert!(condition.matches(&matching_event));
364
365        let non_matching_message = ChatMessage {
366            role: ChatRole::User,
367            message_type: MessageType::Text,
368            content: "hi".to_string(),
369        };
370        let non_matching_event = MessageEvent {
371            role: "user".to_string(),
372            msg: non_matching_message,
373        };
374        assert!(!condition.matches(&non_matching_event));
375    }
376
377    #[test]
378    fn test_message_condition_any_of() {
379        let condition = MessageCondition::AnyOf(vec![
380            MessageCondition::Contains("hello".to_string()),
381            MessageCondition::Contains("goodbye".to_string()),
382            MessageCondition::Empty,
383        ]);
384
385        let hello_message = ChatMessage {
386            role: ChatRole::User,
387            message_type: MessageType::Text,
388            content: "hello world".to_string(),
389        };
390        let hello_event = MessageEvent {
391            role: "user".to_string(),
392            msg: hello_message,
393        };
394        assert!(condition.matches(&hello_event));
395
396        let goodbye_message = ChatMessage {
397            role: ChatRole::User,
398            message_type: MessageType::Text,
399            content: "goodbye world".to_string(),
400        };
401        let goodbye_event = MessageEvent {
402            role: "user".to_string(),
403            msg: goodbye_message,
404        };
405        assert!(condition.matches(&goodbye_event));
406
407        let empty_message = ChatMessage {
408            role: ChatRole::User,
409            message_type: MessageType::Text,
410            content: "".to_string(),
411        };
412        let empty_event = MessageEvent {
413            role: "user".to_string(),
414            msg: empty_message,
415        };
416        assert!(condition.matches(&empty_event));
417
418        let non_matching_message = ChatMessage {
419            role: ChatRole::User,
420            message_type: MessageType::Text,
421            content: "test message".to_string(),
422        };
423        let non_matching_event = MessageEvent {
424            role: "user".to_string(),
425            msg: non_matching_message,
426        };
427        assert!(!condition.matches(&non_matching_event));
428    }
429
430    #[test]
431    fn test_message_condition_regex() {
432        let condition = MessageCondition::Regex(r"\d+".to_string());
433        let number_message = ChatMessage {
434            role: ChatRole::User,
435            message_type: MessageType::Text,
436            content: "there are 123 items".to_string(),
437        };
438        let number_event = MessageEvent {
439            role: "user".to_string(),
440            msg: number_message,
441        };
442        assert!(condition.matches(&number_event));
443
444        let no_number_message = ChatMessage {
445            role: ChatRole::User,
446            message_type: MessageType::Text,
447            content: "no numbers here".to_string(),
448        };
449        let no_number_event = MessageEvent {
450            role: "user".to_string(),
451            msg: no_number_message,
452        };
453        assert!(!condition.matches(&no_number_event));
454    }
455
456    #[test]
457    fn test_message_condition_regex_invalid() {
458        let condition = MessageCondition::Regex("[invalid regex".to_string());
459        let message = ChatMessage {
460            role: ChatRole::User,
461            message_type: MessageType::Text,
462            content: "test message".to_string(),
463        };
464        let event = MessageEvent {
465            role: "user".to_string(),
466            msg: message,
467        };
468        assert!(!condition.matches(&event));
469    }
470
471    #[test]
472    fn test_message_event_creation() {
473        let message = ChatMessage {
474            role: ChatRole::User,
475            message_type: MessageType::Text,
476            content: "test message".to_string(),
477        };
478        let event = MessageEvent {
479            role: "user".to_string(),
480            msg: message.clone(),
481        };
482        assert_eq!(event.role, "user");
483        assert_eq!(event.msg.content, "test message");
484    }
485
486    #[test]
487    fn test_message_event_clone() {
488        let message = ChatMessage {
489            role: ChatRole::User,
490            message_type: MessageType::Text,
491            content: "test message".to_string(),
492        };
493        let event = MessageEvent {
494            role: "user".to_string(),
495            msg: message,
496        };
497        let cloned = event.clone();
498        assert_eq!(event.role, cloned.role);
499        assert_eq!(event.msg.content, cloned.msg.content);
500    }
501
502    #[test]
503    fn test_message_event_debug() {
504        let message = ChatMessage {
505            role: ChatRole::User,
506            message_type: MessageType::Text,
507            content: "test message".to_string(),
508        };
509        let event = MessageEvent {
510            role: "user".to_string(),
511            msg: message,
512        };
513        let debug_str = format!("{event:?}");
514        assert!(debug_str.contains("MessageEvent"));
515        assert!(debug_str.contains("user"));
516    }
517
518    #[tokio::test]
519    async fn test_mock_memory_provider_remember() {
520        let mut provider = MockMemoryProvider::new();
521        let message = ChatMessage {
522            role: ChatRole::User,
523            message_type: MessageType::Text,
524            content: "test message".to_string(),
525        };
526
527        let result = provider.remember(&message).await;
528        assert!(result.is_ok());
529        assert_eq!(provider.size(), 1);
530    }
531
532    #[tokio::test]
533    async fn test_mock_memory_provider_remember_failure() {
534        let mut provider = MockMemoryProvider::with_failure();
535        let message = ChatMessage {
536            role: ChatRole::User,
537            message_type: MessageType::Text,
538            content: "test message".to_string(),
539        };
540
541        let result = provider.remember(&message).await;
542        assert!(result.is_err());
543        assert!(result
544            .unwrap_err()
545            .to_string()
546            .contains("Mock memory error"));
547    }
548
549    #[tokio::test]
550    async fn test_mock_memory_provider_recall() {
551        let messages = vec![
552            ChatMessage {
553                role: ChatRole::User,
554                message_type: MessageType::Text,
555                content: "first message".to_string(),
556            },
557            ChatMessage {
558                role: ChatRole::Assistant,
559                message_type: MessageType::Text,
560                content: "second message".to_string(),
561            },
562        ];
563        let provider = MockMemoryProvider::with_messages(messages);
564
565        let result = provider.recall("", None).await;
566        assert!(result.is_ok());
567        let recalled = result.unwrap();
568        assert_eq!(recalled.len(), 2);
569        assert_eq!(recalled[0].content, "first message");
570        assert_eq!(recalled[1].content, "second message");
571    }
572
573    #[tokio::test]
574    async fn test_mock_memory_provider_recall_with_limit() {
575        let messages = vec![
576            ChatMessage {
577                role: ChatRole::User,
578                message_type: MessageType::Text,
579                content: "first message".to_string(),
580            },
581            ChatMessage {
582                role: ChatRole::Assistant,
583                message_type: MessageType::Text,
584                content: "second message".to_string(),
585            },
586        ];
587        let provider = MockMemoryProvider::with_messages(messages);
588
589        let result = provider.recall("", Some(1)).await;
590        assert!(result.is_ok());
591        let recalled = result.unwrap();
592        assert_eq!(recalled.len(), 1);
593        assert_eq!(recalled[0].content, "first message");
594    }
595
596    #[tokio::test]
597    async fn test_mock_memory_provider_recall_failure() {
598        let provider = MockMemoryProvider::with_failure();
599
600        let result = provider.recall("", None).await;
601        assert!(result.is_err());
602        assert!(result
603            .unwrap_err()
604            .to_string()
605            .contains("Mock recall error"));
606    }
607
608    #[tokio::test]
609    async fn test_mock_memory_provider_clear() {
610        let messages = vec![ChatMessage {
611            role: ChatRole::User,
612            message_type: MessageType::Text,
613            content: "first message".to_string(),
614        }];
615        let mut provider = MockMemoryProvider::with_messages(messages);
616        assert_eq!(provider.size(), 1);
617
618        let result = provider.clear().await;
619        assert!(result.is_ok());
620        assert_eq!(provider.size(), 0);
621    }
622
623    #[tokio::test]
624    async fn test_mock_memory_provider_clear_failure() {
625        let mut provider = MockMemoryProvider::with_failure();
626
627        let result = provider.clear().await;
628        assert!(result.is_err());
629        assert!(result.unwrap_err().to_string().contains("Mock clear error"));
630    }
631
632    #[test]
633    fn test_mock_memory_provider_memory_type() {
634        let provider = MockMemoryProvider::new();
635        assert_eq!(provider.memory_type(), MemoryType::SlidingWindow);
636    }
637
638    #[test]
639    fn test_mock_memory_provider_size() {
640        let provider = MockMemoryProvider::new();
641        assert_eq!(provider.size(), 0);
642
643        let messages = vec![ChatMessage {
644            role: ChatRole::User,
645            message_type: MessageType::Text,
646            content: "message".to_string(),
647        }];
648        let provider_with_messages = MockMemoryProvider::with_messages(messages);
649        assert_eq!(provider_with_messages.size(), 1);
650    }
651
652    #[test]
653    fn test_mock_memory_provider_is_empty() {
654        let provider = MockMemoryProvider::new();
655        assert!(provider.is_empty());
656
657        let messages = vec![ChatMessage {
658            role: ChatRole::User,
659            message_type: MessageType::Text,
660            content: "message".to_string(),
661        }];
662        let provider_with_messages = MockMemoryProvider::with_messages(messages);
663        assert!(!provider_with_messages.is_empty());
664    }
665
666    #[test]
667    fn test_memory_provider_default_methods() {
668        let provider = MockMemoryProvider::new();
669        assert!(!provider.needs_summary());
670        assert!(provider.get_event_receiver().is_none());
671    }
672
673    #[tokio::test]
674    async fn test_memory_provider_remember_with_role() {
675        let mut provider = MockMemoryProvider::new();
676        let message = ChatMessage {
677            role: ChatRole::User,
678            message_type: MessageType::Text,
679            content: "test message".to_string(),
680        };
681
682        let result = provider
683            .remember_with_role(&message, "custom_role".to_string())
684            .await;
685        assert!(result.is_ok());
686        assert_eq!(provider.size(), 1);
687    }
688
689    #[test]
690    fn test_memory_provider_mark_for_summary() {
691        let mut provider = MockMemoryProvider::new();
692        provider.mark_for_summary(); // Should not panic
693        assert!(!provider.needs_summary()); // Default implementation
694    }
695
696    #[test]
697    fn test_memory_provider_replace_with_summary() {
698        let mut provider = MockMemoryProvider::new();
699        provider.replace_with_summary("Summary text".to_string()); // Should not panic
700        assert_eq!(provider.size(), 0); // Should not change size in default implementation
701    }
702}
703
704/// Event emitted when a message is added to reactive memory
705#[derive(Debug, Clone)]
706pub struct MessageEvent {
707    /// Role of the agent that sent the message
708    pub role: String,
709    /// The chat message content
710    pub msg: ChatMessage,
711}
712
713/// Conditions for triggering reactive message handlers
714#[derive(Clone)]
715pub enum MessageCondition {
716    /// Always trigger
717    Any,
718    /// Trigger if message content equals exact string
719    Eq(String),
720    /// Trigger if message content contains substring
721    Contains(String),
722    /// Trigger if message content does not contain substring
723    NotContains(String),
724    /// Trigger if sender role matches
725    RoleIs(String),
726    /// Trigger if sender role does not match
727    RoleNot(String),
728    /// Trigger if message length is greater than specified
729    LenGt(usize),
730    /// Custom condition function
731    Custom(Arc<dyn Fn(&ChatMessage) -> bool + Send + Sync>),
732    /// Empty
733    Empty,
734    /// Trigger if all conditions are met
735    All(Vec<MessageCondition>),
736    /// Trigger if any condition is met
737    AnyOf(Vec<MessageCondition>),
738    /// Trigger if message content matches regex
739    Regex(String),
740}
741
742impl MessageCondition {
743    /// Check if the condition is met for the given message event
744    pub fn matches(&self, event: &MessageEvent) -> bool {
745        match self {
746            MessageCondition::Any => true,
747            MessageCondition::Eq(text) => event.msg.content == *text,
748            MessageCondition::Contains(text) => event.msg.content.contains(text),
749            MessageCondition::NotContains(text) => !event.msg.content.contains(text),
750            MessageCondition::RoleIs(role) => event.role == *role,
751            MessageCondition::RoleNot(role) => event.role != *role,
752            MessageCondition::LenGt(len) => event.msg.content.len() > *len,
753            MessageCondition::Custom(func) => func(&event.msg),
754            MessageCondition::Empty => event.msg.content.is_empty(),
755            MessageCondition::All(inner) => inner.iter().all(|c| c.matches(event)),
756            MessageCondition::AnyOf(inner) => inner.iter().any(|c| c.matches(event)),
757            MessageCondition::Regex(regex) => Regex::new(regex)
758                .map(|re| re.is_match(&event.msg.content))
759                .unwrap_or(false),
760        }
761    }
762}
763
764/// Types of memory implementations available
765#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
766pub enum MemoryType {
767    /// Simple sliding window that keeps the N most recent messages
768    SlidingWindow,
769}
770
771/// Trait for memory providers that can store and retrieve conversation history.
772///
773/// Memory providers enable LLMs to maintain context across conversations by:
774/// - Storing messages as they are exchanged
775/// - Retrieving relevant past messages based on queries
776/// - Managing memory size and cleanup
777#[async_trait]
778pub trait MemoryProvider: Send + Sync {
779    /// Store a message in memory.
780    ///
781    /// # Arguments
782    ///
783    /// * `message` - The chat message to store
784    ///
785    /// # Returns
786    ///
787    /// * `Ok(())` if the message was stored successfully
788    /// * `Err(LLMError)` if storage failed
789    async fn remember(&mut self, message: &ChatMessage) -> Result<(), LLMError>;
790
791    /// Retrieve relevant messages from memory based on a query.
792    ///
793    /// # Arguments
794    ///
795    /// * `query` - The query string to search for relevant messages
796    /// * `limit` - Optional maximum number of messages to return
797    ///
798    /// # Returns
799    ///
800    /// * `Ok(Vec<ChatMessage>)` containing relevant messages
801    /// * `Err(LLMError)` if retrieval failed
802    async fn recall(&self, query: &str, limit: Option<usize>)
803        -> Result<Vec<ChatMessage>, LLMError>;
804
805    /// Clear all stored messages from memory.
806    ///
807    /// # Returns
808    ///
809    /// * `Ok(())` if memory was cleared successfully
810    /// * `Err(LLMError)` if clearing failed
811    async fn clear(&mut self) -> Result<(), LLMError>;
812
813    /// Get the type of this memory provider.
814    ///
815    /// # Returns
816    ///
817    /// The memory type enum variant
818    fn memory_type(&self) -> MemoryType;
819
820    /// Get the current number of stored messages.
821    ///
822    /// # Returns
823    ///
824    /// The number of messages currently in memory
825    fn size(&self) -> usize;
826
827    /// Check if the memory is empty.
828    ///
829    /// # Returns
830    ///
831    /// `true` if no messages are stored, `false` otherwise
832    fn is_empty(&self) -> bool {
833        self.size() == 0
834    }
835
836    /// Check if memory needs summarization
837    fn needs_summary(&self) -> bool {
838        false
839    }
840
841    /// Mark memory as needing summarization
842    fn mark_for_summary(&mut self) {}
843
844    /// Replace all messages with a summary
845    fn replace_with_summary(&mut self, _summary: String) {}
846
847    /// Get a receiver for reactive events if this memory supports them
848    #[cfg(not(target_arch = "wasm32"))]
849    fn get_event_receiver(&self) -> Option<broadcast::Receiver<MessageEvent>> {
850        None
851    }
852
853    #[cfg(target_arch = "wasm32")]
854    fn get_event_receiver(&self) -> Option<()> {
855        None
856    }
857
858    /// Remember a message with a specific role for reactive memory
859    async fn remember_with_role(
860        &mut self,
861        message: &ChatMessage,
862        _role: String,
863    ) -> Result<(), LLMError> {
864        self.remember(message).await
865    }
866
867    /// Clone the memory provider into a new Box
868    /// This is needed for persistence across requests
869    fn clone_box(&self) -> Box<dyn MemoryProvider>;
870
871    /// Get a unique identifier for this memory instance
872    /// Used for caching and persistence
873    fn id(&self) -> Option<String> {
874        None
875    }
876
877    /// Preload memory from a cache or storage
878    /// Returns true if memory was successfully preloaded
879    fn preload(&mut self, _data: Vec<ChatMessage>) -> bool {
880        false
881    }
882
883    /// Export memory data for caching or persistence
884    /// Returns the messages that should be persisted
885    fn export(&self) -> Vec<ChatMessage> {
886        Vec::new()
887    }
888}