codemem_engine/consolidation/
mod.rs1mod cluster;
9mod creative;
10mod decay;
11mod forget;
12mod summarize;
13pub mod union_find;
14
15pub use union_find::UnionFind;
16
17use crate::CodememEngine;
18use codemem_core::{CodememError, VectorBackend};
19
20pub struct ConsolidationResult {
22 pub cycle: String,
24 pub affected: usize,
26 pub details: serde_json::Value,
28}
29
30pub struct ConsolidationStatusEntry {
32 pub cycle_type: String,
33 pub last_run: String,
34 pub affected_count: usize,
35}
36
37impl CodememEngine {
38 pub fn consolidation_status(&self) -> Result<Vec<ConsolidationStatusEntry>, CodememError> {
40 let runs = self.storage.last_consolidation_runs()?;
41 let mut entries = Vec::new();
42 for entry in &runs {
43 let dt = chrono::DateTime::from_timestamp(entry.run_at, 0)
44 .map(|t| t.format("%Y-%m-%d %H:%M:%S UTC").to_string())
45 .unwrap_or_else(|| "unknown".to_string());
46 entries.push(ConsolidationStatusEntry {
47 cycle_type: entry.cycle_type.clone(),
48 last_run: dt,
49 affected_count: entry.affected_count,
50 });
51 }
52 Ok(entries)
53 }
54
55 pub fn find_forgettable_by_tags(
62 &self,
63 importance_threshold: f64,
64 target_tags: &[String],
65 max_access_count: u32,
66 ) -> Result<Vec<String>, CodememError> {
67 let all_memories = self.storage.list_memories_filtered(None, None)?;
68 let mut forgettable = Vec::new();
69
70 for memory in &all_memories {
71 if memory.importance >= importance_threshold {
72 continue;
73 }
74 if memory.access_count > max_access_count {
75 continue;
76 }
77 if memory.tags.iter().any(|t| target_tags.contains(t)) {
78 forgettable.push(memory.id.clone());
79 }
80 }
81
82 Ok(forgettable)
83 }
84
85 pub fn rebuild_vector_index_internal(&self, vector: &mut codemem_storage::HnswIndex) {
87 let embeddings = match self.storage.list_all_embeddings() {
88 Ok(e) => e,
89 Err(e) => {
90 tracing::warn!("Failed to rebuild vector index: {e}");
91 return;
92 }
93 };
94
95 if let Ok(mut fresh) = codemem_storage::HnswIndex::with_defaults() {
96 for (id, floats) in &embeddings {
97 let _ = fresh.insert(id, floats);
98 }
99 *vector = fresh;
100 }
101 }
102}