use crate::models::*; use crate::search::MemoryIndex; use crate::store::Store; use std::collections::HashMap; use std::path::PathBuf; use std::sync::RwLock; pub struct MemoryState { pub base_dir: PathBuf, pub graph: Store, pub search_index: RwLock, pub ledger: Store>, pub sticky: Store>, pub tasks: Store>, pub snippets: Store>, pub adrs: Store>, pub prefs: Store>, pub error_fixes: Store>, pub pinned_files: Store>, pub session_summaries: Store>, pub handoff_memos: Store>, pub env_fingerprints: Store>, pub env_requirements: Store>, pub milestones: Store>, pub environments: Store>, pub pr_checklists: Store>, pub tech_debts: Store>, pub gates: Store>, pub context_workspaces: Store>, pub activity_tx: tokio::sync::broadcast::Sender, } impl MemoryState { pub fn unique_items(input: Vec) -> Vec { let mut keys = std::collections::HashSet::new(); input .into_iter() .filter(|entry| keys.insert(entry.clone())) .collect() } pub fn broadcast_activity(&self, message: &str) { let payload = serde_json::json!({ "type": "activity", "data": message }) .to_string(); let _ = self.activity_tx.send(payload); } pub fn get_full_graph(&self) -> KnowledgeGraph { self.graph.read() } pub fn write_to_local_delta(&self, update_fn: F) { self.graph.modify(update_fn); } pub fn apply_sync_write(&self, update_fn: F) { self.graph.modify(update_fn); } pub fn rebuild_index(&self) { if let Ok(new_idx) = MemoryIndex::new(&self.base_dir) { let graph = self.graph.read(); for e in graph.entities.values() { let _ = new_idx.index_entity(e); } let tasks = self.tasks.read(); for t in tasks { let _ = new_idx.index_task(&t); } let snippets = self.snippets.read(); for s in snippets { let _ = new_idx.index_snippet(&s); } let adrs = self.adrs.read(); for a in adrs { let _ = new_idx.index_adr(&a); } let _ = new_idx.commit(); if let Ok(mut w) = self.search_index.write() { *w = new_idx; } } } }