mod cluster;
mod creative;
mod decay;
mod forget;
mod summarize;
pub mod union_find;
pub use union_find::UnionFind;
use crate::CodememEngine;
use codemem_core::{CodememError, VectorBackend};
pub struct ConsolidationResult {
pub cycle: String,
pub affected: usize,
pub details: serde_json::Value,
}
pub struct ConsolidationStatusEntry {
pub cycle_type: String,
pub last_run: String,
pub affected_count: usize,
}
impl CodememEngine {
pub fn consolidation_status(&self) -> Result<Vec<ConsolidationStatusEntry>, CodememError> {
let runs = self.storage.last_consolidation_runs()?;
let mut entries = Vec::new();
for entry in &runs {
let dt = chrono::DateTime::from_timestamp(entry.run_at, 0)
.map(|t| t.format("%Y-%m-%d %H:%M:%S UTC").to_string())
.unwrap_or_else(|| "unknown".to_string());
entries.push(ConsolidationStatusEntry {
cycle_type: entry.cycle_type.clone(),
last_run: dt,
affected_count: entry.affected_count,
});
}
Ok(entries)
}
pub fn find_forgettable_by_tags(
&self,
importance_threshold: f64,
target_tags: &[String],
max_access_count: u32,
) -> Result<Vec<String>, CodememError> {
let all_memories = self.storage.list_memories_filtered(None, None)?;
let mut forgettable = Vec::new();
for memory in &all_memories {
if memory.importance >= importance_threshold {
continue;
}
if memory.access_count > max_access_count {
continue;
}
if memory.tags.iter().any(|t| target_tags.contains(t)) {
forgettable.push(memory.id.clone());
}
}
Ok(forgettable)
}
pub fn rebuild_vector_index_internal(&self, vector: &mut dyn VectorBackend) {
let embeddings = match self.storage.list_all_embeddings() {
Ok(e) => e,
Err(e) => {
tracing::warn!("Failed to rebuild vector index: {e}");
return;
}
};
let _ = vector.rebuild_from_entries(&embeddings);
}
}