use crate::{
cosmic::CosmicScaleMemory, individual::IndividualMemory, species::SpeciesMemory, Memory,
MemoryError, MemoryTier, QueryBuilder,
};
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct MemoryConsolidator {
individual: Arc<RwLock<IndividualMemory>>,
species: Arc<RwLock<SpeciesMemory>>,
cosmic_scale: Arc<RwLock<CosmicScaleMemory>>,
}
impl MemoryConsolidator {
pub fn new(
individual: Arc<RwLock<IndividualMemory>>,
species: Arc<RwLock<SpeciesMemory>>,
cosmic_scale: Arc<RwLock<CosmicScaleMemory>>,
) -> Self {
Self {
individual,
species,
cosmic_scale,
}
}
pub async fn consolidate(
&self,
from_tier: MemoryTier,
to_tier: MemoryTier,
) -> Result<(), MemoryError> {
if from_tier >= to_tier {
return Err(MemoryError::Consolidation(
"Can only consolidate to higher tiers".to_string(),
));
}
let query = QueryBuilder::new()
.tier(from_tier)
.min_importance(to_tier.importance_threshold())
.build();
let memories = match from_tier.scale() {
crate::tiers::MemoryScale::Individual => {
self.individual
.read()
.await
.recall(&query, &[from_tier])
.await?
}
crate::tiers::MemoryScale::Species => {
self.species
.read()
.await
.recall(&query, &[from_tier])
.await?
}
crate::tiers::MemoryScale::Cosmic => {
self.cosmic_scale
.read()
.await
.recall(&query, &[from_tier])
.await?
}
};
for memory in memories {
let consolidated = self.consolidate_memory(memory, to_tier)?;
match to_tier.scale() {
crate::tiers::MemoryScale::Individual => {
self.individual.write().await.store(consolidated).await?;
}
crate::tiers::MemoryScale::Species => {
self.species.write().await.store(consolidated).await?;
}
crate::tiers::MemoryScale::Cosmic => {
self.cosmic_scale.write().await.store(consolidated).await?;
}
}
}
Ok(())
}
pub async fn auto_consolidate(&self) -> Result<(), MemoryError> {
self.consolidate_by_importance(MemoryTier::Instant, MemoryTier::Session)
.await?;
self.consolidate_by_importance(MemoryTier::Session, MemoryTier::Episodic)
.await?;
self.consolidate_by_importance(MemoryTier::Episodic, MemoryTier::Semantic)
.await?;
self.consolidate_by_importance(MemoryTier::Semantic, MemoryTier::Collective)
.await?;
Ok(())
}
async fn consolidate_by_importance(
&self,
from_tier: MemoryTier,
to_tier: MemoryTier,
) -> Result<(), MemoryError> {
let query = QueryBuilder::new()
.tier(from_tier)
.min_importance(to_tier.importance_threshold())
.build();
let memories = match from_tier.scale() {
crate::tiers::MemoryScale::Individual => {
self.individual
.read()
.await
.recall(&query, &[from_tier])
.await?
}
crate::tiers::MemoryScale::Species => {
self.species
.read()
.await
.recall(&query, &[from_tier])
.await?
}
crate::tiers::MemoryScale::Cosmic => {
self.cosmic_scale
.read()
.await
.recall(&query, &[from_tier])
.await?
}
};
for memory in memories {
if memory.importance >= to_tier.importance_threshold() {
let consolidated = self.consolidate_memory(memory, to_tier)?;
match to_tier.scale() {
crate::tiers::MemoryScale::Individual => {
self.individual.write().await.store(consolidated).await?;
}
crate::tiers::MemoryScale::Species => {
self.species.write().await.store(consolidated).await?;
}
crate::tiers::MemoryScale::Cosmic => {
self.cosmic_scale.write().await.store(consolidated).await?;
}
}
}
}
Ok(())
}
fn consolidate_memory(&self, mut memory: Memory, to_tier: MemoryTier) -> Result<Memory, MemoryError> {
memory.tier = to_tier;
memory.importance = (memory.importance * 1.1).min(1.0);
memory.id = uuid::Uuid::new_v4().to_string();
if let serde_json::Value::Object(ref mut map) = memory.metadata {
map.insert(
"consolidated_at".to_string(),
serde_json::Value::String(chrono::Utc::now().to_rfc3339()),
);
map.insert(
"consolidation_tier".to_string(),
serde_json::Value::Number(serde_json::Number::from(to_tier as u8)),
);
}
Ok(memory)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::MemoryContent;
#[tokio::test]
async fn test_consolidation() {
let individual = Arc::new(RwLock::new(IndividualMemory::new().await.unwrap()));
let species = Arc::new(RwLock::new(SpeciesMemory::new().await.unwrap()));
let cosmic = Arc::new(RwLock::new(CosmicScaleMemory::new().await.unwrap()));
let consolidator = MemoryConsolidator::new(individual.clone(), species, cosmic);
let memory = Memory::new(
MemoryTier::Instant,
MemoryContent::Text("important".to_string()),
vec![0.5, 0.5, 0.5],
0.9,
);
individual.write().await.store(memory).await.unwrap();
consolidator
.consolidate(MemoryTier::Instant, MemoryTier::Session)
.await
.unwrap();
}
}