Skip to main content

agent_diva_core/memory/
storage.rs

1//! Memory data structures
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6/// Long-term memory storage
7#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8pub struct Memory {
9    /// Memory content in Markdown format
10    pub content: String,
11    /// Last updated timestamp
12    pub updated_at: DateTime<Utc>,
13    /// Version for conflict detection
14    pub version: u64,
15}
16
17impl Memory {
18    /// Create new empty memory
19    pub fn new() -> Self {
20        Self {
21            content: String::new(),
22            updated_at: Utc::now(),
23            version: 1,
24        }
25    }
26
27    /// Create memory with initial content
28    pub fn with_content(content: impl Into<String>) -> Self {
29        Self {
30            content: content.into(),
31            updated_at: Utc::now(),
32            version: 1,
33        }
34    }
35
36    /// Update the memory content
37    pub fn update(&mut self, content: impl Into<String>) {
38        self.content = content.into();
39        self.updated_at = Utc::now();
40        self.version += 1;
41    }
42
43    /// Append content to memory
44    pub fn append(&mut self, content: impl AsRef<str>) {
45        if !self.content.is_empty() {
46            self.content.push('\n');
47        }
48        self.content.push_str(content.as_ref());
49        self.updated_at = Utc::now();
50        self.version += 1;
51    }
52}
53
54/// Daily note entry
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct DailyNote {
57    /// Date string (YYYY-MM-DD)
58    pub date: String,
59    /// Note content in Markdown format
60    pub content: String,
61    /// Creation timestamp
62    pub created_at: DateTime<Utc>,
63    /// Last updated timestamp
64    pub updated_at: DateTime<Utc>,
65}
66
67impl DailyNote {
68    /// Create a new daily note for today
69    pub fn today() -> Self {
70        let now = Utc::now();
71        Self {
72            date: now.format("%Y-%m-%d").to_string(),
73            content: String::new(),
74            created_at: now,
75            updated_at: now,
76        }
77    }
78
79    /// Create a daily note for a specific date
80    pub fn for_date(date: impl Into<String>) -> Self {
81        let now = Utc::now();
82        Self {
83            date: date.into(),
84            content: String::new(),
85            created_at: now,
86            updated_at: now,
87        }
88    }
89
90    /// Update the note content
91    pub fn update(&mut self, content: impl Into<String>) {
92        self.content = content.into();
93        self.updated_at = Utc::now();
94    }
95
96    /// Append content to the note
97    pub fn append(&mut self, content: impl AsRef<str>) {
98        if !self.content.is_empty() {
99            self.content.push('\n');
100        }
101        self.content.push_str(content.as_ref());
102        self.updated_at = Utc::now();
103    }
104
105    /// Get the filename for this note
106    pub fn filename(&self) -> String {
107        format!("{}.md", self.date)
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114
115    #[test]
116    fn test_memory_creation() {
117        let memory = Memory::new();
118        assert!(memory.content.is_empty());
119        assert_eq!(memory.version, 1);
120    }
121
122    #[test]
123    fn test_memory_with_content() {
124        let memory = Memory::with_content("Test content");
125        assert_eq!(memory.content, "Test content");
126    }
127
128    #[test]
129    fn test_memory_update() {
130        let mut memory = Memory::new();
131        memory.update("New content");
132        assert_eq!(memory.content, "New content");
133        assert_eq!(memory.version, 2);
134    }
135
136    #[test]
137    fn test_memory_append() {
138        let mut memory = Memory::with_content("Line 1");
139        memory.append("Line 2");
140        assert_eq!(memory.content, "Line 1\nLine 2");
141        assert_eq!(memory.version, 2);
142    }
143
144    #[test]
145    fn test_daily_note_today() {
146        let note = DailyNote::today();
147        assert!(!note.date.is_empty());
148        assert!(note.content.is_empty());
149    }
150
151    #[test]
152    fn test_daily_note_filename() {
153        let note = DailyNote::for_date("2024-01-15");
154        assert_eq!(note.filename(), "2024-01-15.md");
155    }
156}