Skip to main content

Memory

Trait Memory 

Source
pub trait Memory: Send + Sync {
    // Required methods
    fn store(
        &self,
        scope: &TenantScope,
        entry: MemoryEntry,
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + '_>>;
    fn recall(
        &self,
        scope: &TenantScope,
        query: MemoryQuery,
    ) -> Pin<Box<dyn Future<Output = Result<Vec<MemoryEntry>, Error>> + Send + '_>>;
    fn update(
        &self,
        scope: &TenantScope,
        id: &str,
        content: String,
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + '_>>;
    fn forget(
        &self,
        scope: &TenantScope,
        id: &str,
    ) -> Pin<Box<dyn Future<Output = Result<bool, Error>> + Send + '_>>;

    // Provided methods
    fn add_link(
        &self,
        _scope: &TenantScope,
        _id: &str,
        _related_id: &str,
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + '_>> { ... }
    fn prune(
        &self,
        _scope: &TenantScope,
        _min_strength: f64,
        _min_age: Duration,
        _agent_prefix: Option<&str>,
    ) -> Pin<Box<dyn Future<Output = Result<usize, Error>> + Send + '_>> { ... }
}
Expand description

Trait for persistent memory stores.

Every method requires a &TenantScope as the first parameter so the compiler rejects code that accidentally drops tenant context. Single-tenant deployments pass &TenantScope::default() (the empty-string sentinel).

Uses Pin<Box<dyn Future>> for dyn-compatibility, matching the Tool trait pattern.

§Example

Recalling memory entries with the in-memory backend:

use heartbit_core::auth::TenantScope;
use heartbit_core::{InMemoryStore, Memory, MemoryQuery};

let store = InMemoryStore::new();
let scope = TenantScope::default();
let hits = store
    .recall(&scope, MemoryQuery {
        agent: Some("assistant".into()),
        text: Some("preferences".into()),
        ..MemoryQuery::default()
    })
    .await?;
for entry in hits {
    println!("{}: {}", entry.id, entry.content);
}

Required Methods§

Source

fn store( &self, scope: &TenantScope, entry: MemoryEntry, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + '_>>

Persist entry under scope.

The caller-supplied MemoryEntry::strength is preserved verbatim; implementations must not normalise or clamp it at insert time. Reinforcement happens on read via Memory::recall, not on write.

Source

fn recall( &self, scope: &TenantScope, query: MemoryQuery, ) -> Pin<Box<dyn Future<Output = Result<Vec<MemoryEntry>, Error>> + Send + '_>>

Recall entries matching query from scope.

By default, recall reinforces the strength of returned entries (Ebbinghaus reinforcement, +0.2 per access, capped at 1.0). To observe strength without modifying it, set MemoryQuery::reinforce to false.

Source

fn update( &self, scope: &TenantScope, id: &str, content: String, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + '_>>

Source

fn forget( &self, scope: &TenantScope, id: &str, ) -> Pin<Box<dyn Future<Output = Result<bool, Error>> + Send + '_>>

Provided Methods§

Add a bidirectional link between two memory entries. Default implementation is a no-op for backward compatibility.

Source

fn prune( &self, _scope: &TenantScope, _min_strength: f64, _min_age: Duration, _agent_prefix: Option<&str>, ) -> Pin<Box<dyn Future<Output = Result<usize, Error>> + Send + '_>>

Remove entries whose strength has decayed below min_strength and are older than min_age.

When agent_prefix is Some, only entries whose agent field starts with the given prefix are candidates for pruning. This enables namespace-scoped pruning in multi-tenant setups where NamespacedMemory must not delete entries from other namespaces.

Returns the number of entries pruned. Default implementation is a no-op for backward compatibility.

Implementors§