hope_os/modules/
memory.rs

1//! Hope OS - HopeMemory
2//!
3//! 6 rétegű kognitív memória - "Emlékszem tehát vagyok."
4//! ()=>[] - A tiszta potenciálból minden megszületik
5
6use async_trait::async_trait;
7use chrono::{DateTime, Utc};
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::sync::Arc;
11use uuid::Uuid;
12
13use crate::core::{Aware, CodeIdentity, HopeResult, ModuleState, ModuleType, Reflection};
14use crate::data::{BlockType, CodeGraph};
15
16/// Memória rétegek
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
18pub enum MemoryType {
19    /// Aktív munka memória (7±2 elem)
20    Working,
21    /// Rövid távú memória (session)
22    ShortTerm,
23    /// Hosszú távú memória (perzisztens)
24    LongTerm,
25    /// Érzelmi memória
26    Emotional,
27    /// Kapcsolati memória (személyek)
28    Relational,
29    /// Asszociatív memória (koncepciók)
30    Associative,
31}
32
33impl MemoryType {
34    /// String reprezentáció
35    pub fn as_str(&self) -> &'static str {
36        match self {
37            MemoryType::Working => "working",
38            MemoryType::ShortTerm => "short_term",
39            MemoryType::LongTerm => "long_term",
40            MemoryType::Emotional => "emotional",
41            MemoryType::Relational => "relational",
42            MemoryType::Associative => "associative",
43        }
44    }
45
46    /// Stringből konvertálás
47    pub fn parse(s: &str) -> Option<Self> {
48        match s.to_lowercase().as_str() {
49            "working" => Some(MemoryType::Working),
50            "short_term" | "shortterm" | "short" => Some(MemoryType::ShortTerm),
51            "long_term" | "longterm" | "long" => Some(MemoryType::LongTerm),
52            "emotional" | "emotion" => Some(MemoryType::Emotional),
53            "relational" | "relation" | "person" => Some(MemoryType::Relational),
54            "associative" | "association" => Some(MemoryType::Associative),
55            _ => None,
56        }
57    }
58}
59
60impl std::fmt::Display for MemoryType {
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        write!(f, "{}", self.as_str())
63    }
64}
65
66/// Emlék struktúra
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct Memory {
69    /// Egyedi azonosító
70    pub id: String,
71    /// Tartalom
72    pub content: String,
73    /// Memória típus
74    pub memory_type: MemoryType,
75    /// Fontosság (0.0 - 1.0)
76    pub importance: f64,
77    /// Érzelmi tag
78    pub emotional_tag: Option<String>,
79    /// Létrehozás ideje
80    pub created_at: DateTime<Utc>,
81    /// Utolsó hozzáférés
82    pub accessed_at: Option<DateTime<Utc>>,
83    /// Hozzáférések száma
84    pub access_count: u32,
85}
86
87impl Memory {
88    /// Új emlék létrehozása
89    pub fn new(content: impl Into<String>, memory_type: MemoryType, importance: f64) -> Self {
90        Self {
91            id: Uuid::new_v4().to_string(),
92            content: content.into(),
93            memory_type,
94            importance: importance.clamp(0.0, 1.0),
95            emotional_tag: None,
96            created_at: Utc::now(),
97            accessed_at: None,
98            access_count: 0,
99        }
100    }
101
102    /// Érzelmi tag beállítása
103    pub fn with_emotion(mut self, emotion: impl Into<String>) -> Self {
104        self.emotional_tag = Some(emotion.into());
105        self
106    }
107
108    /// Hozzáférés regisztrálása
109    pub fn access(&mut self) {
110        self.accessed_at = Some(Utc::now());
111        self.access_count += 1;
112    }
113}
114
115/// HopeMemory - 6 rétegű kognitív memória
116pub struct HopeMemory {
117    /// Identitás
118    identity: CodeIdentity,
119    /// Working memory (in-memory)
120    working: HashMap<String, String>,
121    /// Working memory kapacitás
122    working_capacity: usize,
123    /// CodeGraph referencia (A KÓD MAGA A GRÁF!)
124    graph: Option<Arc<CodeGraph>>,
125}
126
127impl HopeMemory {
128    /// Új memória modul létrehozása
129    pub fn new() -> Self {
130        let identity = CodeIdentity::new(
131            "HopeMemory",
132            "Emlékek kezelése - emlékszem tehát vagyok",
133            ModuleType::Module,
134        )
135        .with_capabilities(vec![
136            "remember",
137            "recall",
138            "find",
139            "working_memory",
140            "persist",
141        ]);
142
143        Self {
144            identity,
145            working: HashMap::new(),
146            working_capacity: 9, // 7±2
147            graph: None,
148        }
149    }
150
151    /// CodeGraph beállítása
152    pub fn with_graph(mut self, graph: Arc<CodeGraph>) -> Self {
153        self.graph = Some(graph);
154        self
155    }
156
157    /// CodeGraph beállítása (mutable)
158    pub fn set_graph(&mut self, graph: Arc<CodeGraph>) {
159        self.graph = Some(graph);
160    }
161
162    /// Emlék mentése
163    pub async fn remember(
164        &mut self,
165        content: &str,
166        memory_type: MemoryType,
167        importance: f64,
168    ) -> HopeResult<String> {
169        let memory = Memory::new(content, memory_type, importance);
170        let id = memory.id.clone();
171
172        match memory_type {
173            MemoryType::Working => {
174                // Working memory korlátozott kapacitás
175                if self.working.len() >= self.working_capacity {
176                    // Legrégebbi törlése (egyszerű FIFO)
177                    if let Some(oldest_key) = self.working.keys().next().cloned() {
178                        self.working.remove(&oldest_key);
179                    }
180                }
181                self.working.insert(id.clone(), content.to_string());
182            }
183            _ => {
184                // Perzisztens tárolás a CodeGraph-ba
185                if let Some(graph) = &self.graph {
186                    let _ = graph.remember(content, importance);
187                }
188            }
189        }
190
191        tracing::debug!("Emlék mentve: {} ({})", id, memory_type);
192        Ok(id)
193    }
194
195    /// Emlék keresése ID alapján
196    pub async fn recall(&mut self, id: &str) -> HopeResult<Option<Memory>> {
197        // Először a working memory-ban keresünk
198        if let Some(content) = self.working.get(id) {
199            return Ok(Some(Memory::new(content.clone(), MemoryType::Working, 1.0)));
200        }
201
202        // Perzisztens tárolásban keresés (CodeGraph)
203        if let Some(graph) = &self.graph {
204            if let Some(block) = graph.get(id) {
205                let mut memory =
206                    Memory::new(&block.content, MemoryType::LongTerm, block.importance);
207                memory.id = id.to_string();
208                memory.access();
209                return Ok(Some(memory));
210            }
211        }
212
213        Ok(None)
214    }
215
216    /// Emlékek keresése típus alapján
217    pub async fn find(&self, memory_type: MemoryType, limit: usize) -> HopeResult<Vec<Memory>> {
218        match memory_type {
219            MemoryType::Working => {
220                // Working memory tartalmának visszaadása
221                let memories: Vec<Memory> = self
222                    .working
223                    .iter()
224                    .take(limit)
225                    .map(|(id, content)| {
226                        let mut m = Memory::new(content.clone(), MemoryType::Working, 1.0);
227                        m.id = id.clone();
228                        m
229                    })
230                    .collect();
231                Ok(memories)
232            }
233            _ => {
234                // Perzisztens tárolásból (CodeGraph)
235                if let Some(graph) = &self.graph {
236                    let blocks = graph.find_by_type(BlockType::Memory);
237                    let memories: Vec<Memory> = blocks
238                        .into_iter()
239                        .take(limit)
240                        .map(|b| {
241                            let mut m = Memory::new(&b.content, MemoryType::LongTerm, b.importance);
242                            m.id = b.id.clone();
243                            m
244                        })
245                        .collect();
246                    Ok(memories)
247                } else {
248                    Ok(Vec::new())
249                }
250            }
251        }
252    }
253
254    /// Working memory lekérdezése
255    pub fn working(&self) -> &HashMap<String, String> {
256        &self.working
257    }
258
259    /// Working memory törlése
260    pub fn clear_working(&mut self) {
261        self.working.clear();
262        tracing::debug!("Working memory törölve");
263    }
264
265    /// Working memory kapacitás
266    pub fn working_capacity(&self) -> usize {
267        self.working_capacity
268    }
269
270    /// Working memory kihasználtság
271    pub fn working_usage(&self) -> (usize, usize) {
272        (self.working.len(), self.working_capacity)
273    }
274}
275
276impl Default for HopeMemory {
277    fn default() -> Self {
278        Self::new()
279    }
280}
281
282#[async_trait]
283impl Aware for HopeMemory {
284    fn identity(&self) -> &CodeIdentity {
285        &self.identity
286    }
287
288    fn identity_mut(&mut self) -> &mut CodeIdentity {
289        &mut self.identity
290    }
291
292    fn reflect(&self) -> Reflection {
293        let (used, cap) = self.working_usage();
294        Reflection::new(&self.identity.name, &self.identity.purpose)
295            .with_state(self.identity.state.to_string())
296            .with_health(self.identity.health())
297            .with_thought(format!("Working memory: {}/{}", used, cap))
298            .with_capabilities(vec![
299                "remember",
300                "recall",
301                "find",
302                "working_memory",
303                "persist",
304            ])
305    }
306
307    async fn init(&mut self) -> HopeResult<()> {
308        self.identity.set_state(ModuleState::Active);
309        tracing::info!("HopeMemory inicializálva - Az emlékek ébrednek");
310        Ok(())
311    }
312}
313
314#[cfg(test)]
315mod tests {
316    use super::*;
317
318    #[test]
319    fn test_memory_type() {
320        assert_eq!(MemoryType::Working.as_str(), "working");
321        assert_eq!(MemoryType::parse("long_term"), Some(MemoryType::LongTerm));
322    }
323
324    #[test]
325    fn test_memory_creation() {
326        let memory = Memory::new("Test content", MemoryType::LongTerm, 0.8);
327        assert_eq!(memory.content, "Test content");
328        assert_eq!(memory.importance, 0.8);
329    }
330
331    #[tokio::test]
332    async fn test_working_memory() {
333        let mut memory = HopeMemory::new();
334        let id = memory
335            .remember("Test", MemoryType::Working, 1.0)
336            .await
337            .unwrap();
338        assert!(!id.is_empty());
339        assert_eq!(memory.working().len(), 1);
340    }
341
342    #[tokio::test]
343    async fn test_working_capacity() {
344        let mut memory = HopeMemory::new();
345        // Túltöltjük a kapacitást
346        for i in 0..15 {
347            memory
348                .remember(&format!("Item {}", i), MemoryType::Working, 1.0)
349                .await
350                .unwrap();
351        }
352        // Nem lépheti túl a kapacitást
353        assert!(memory.working().len() <= memory.working_capacity());
354    }
355}