Skip to main content

Mnemo

Struct Mnemo 

Source
pub struct Mnemo { /* private fields */ }
Expand description

An encrypted, single-file agent memory database.

Implementations§

Source§

impl Mnemo

Source

pub fn create( path: impl Into<PathBuf>, passphrase: &str, config: MnemoConfig, ) -> Result<Mnemo>

Create a brand-new encrypted database at path.

Source

pub fn open(path: impl Into<PathBuf>, passphrase: &str) -> Result<Mnemo>

Open an existing database. A wrong passphrase fails cleanly with MnemoError::WrongPassphrase.

Source

pub fn set_max_snapshots(&mut self, max: usize)

Override the manifest snapshot cap on this open handle. 0 disables the cap; any positive value keeps the most-recent max snapshots and drops the rest on the next flush. See MnemoConfig::max_snapshots.

Source

pub fn dimensions(&self) -> usize

Embedding dimensionality this database expects.

Source

pub fn len(&self) -> usize

Number of live (non-deleted) memories.

Source

pub fn is_empty(&self) -> bool

True if the database holds no live memories.

Source

pub fn remember(&mut self, memory: Memory) -> Result<Ulid>

Store a memory. Returns its ULID. If the memory’s ID is nil a fresh one is assigned; an existing ID overwrites in place.

Source

pub fn get(&mut self, id: &Ulid) -> Result<Memory>

Fetch a memory by ID.

Source

pub fn delete(&mut self, id: &Ulid) -> Result<()>

Soft-delete a memory (tombstoned; space reclaimed by compact).

Source

pub fn memories(&mut self) -> Result<Vec<Memory>>

Return every live memory (used by tooling and compaction).

Source

pub fn about(&mut self) -> Result<Vec<Memory>>

Return the database’s self-describing onboarding memories — the ones tagged metadata.area = "onboarding". This is the engine-level surface for the single-file philosophy: an agent who receives a .mnemo file (and its passphrase) can call this to learn what the file is, which embedder it expects, the recommended agent id, and any other conventions the file’s author chose to record — all without needing any external documentation.

Ordering: the canonical manifest (tag metadata.topic = "manifest") always comes first; everything else follows in importance descending, then created_at ascending for deterministic results.

Source

pub fn search( &mut self, query: &[f32], top_k: usize, metric: Metric, ) -> Result<Vec<(Memory, f32)>>

Phase-1 brute-force search: rank live memories by raw similarity only. Read-only — does not update access statistics.

Source

pub fn recall(&mut self, req: &RecallRequest) -> Result<Vec<RecallResult>>

Phase-5 multi-signal recall: rank by α·similarity + β·recency + γ·importance + δ·ln(freq), with type and agent filtering. Updates accessed_at / access_count on the returned memories (persisted on the next flush).

When an ANN index has been built (Mnemo::build_index), recall runs the tiered IVF→PQ→rerank pipeline: it scores only the similarity-nearest n_rerank candidates rather than every memory. Without an index it scores every live memory exactly.

Source

pub fn build_index(&mut self) -> Result<IndexInfo>

Build an IVF+PQ approximate-nearest-neighbour index over every live memory, using default tuning. After this, Mnemo::recall runs the tiered pipeline instead of an exact scan. Persisted on the next flush. Returns a snapshot of the index shape.

Source

pub fn build_index_with(&mut self, cfg: IndexConfig) -> Result<IndexInfo>

Build the ANN index with explicit tuning.

Source

pub fn rebuild_index(&mut self) -> Result<IndexInfo>

Rebuild the ANN index from scratch — re-clusters centroids and retrains the PQ codebook, undoing the cluster drift that accumulates as memories are inserted against fixed centroids.

Source

pub fn drop_index(&mut self)

Drop the ANN index; recall reverts to exact scans. Persisted on flush.

Source

pub fn has_index(&self) -> bool

Whether an ANN index is currently loaded.

Source

pub fn flush(&mut self) -> Result<()>

Persist all pending changes as one write-ahead-logged transaction.

Sequence:

  1. Prepare. Serialize the control plane (catalog, ANN index), grow the WAL if needed, and lease counter and page slots — bump header.write_counter and header.next_page by upper bounds on this transaction’s consumption and persist that leased header to disk before any encrypted page is written.
  2. Data pages. [Pager::flush] writes dirty record pages copy-on-write under fresh nonces and fsyncs them. The orphan-page nonce-reuse window (see [Phase 1.1 of the improvement plan]) is closed because the leased header on disk already records a write_counter past anything this step can produce.
  3. Control plane. Seal the new catalog / ANN index / snapshot manifest into fresh home page runs.
  4. Commit. Log all of step 3’s frames plus the final header frame into the WAL and fsync — the durability point.
  5. Checkpoint. Fold the WAL into the home pages.

A crash before step 4 leaves the previous state intact. A crash after step 4 is repaired by Mnemo::open replaying the WAL. Safe to call repeatedly.

Source

pub fn close(&mut self) -> Result<()>

Flush and close. Equivalent to flush(); the file is released on drop.

Source

pub fn set_cache_capacity(&mut self, pages: usize)

Bound the in-memory page cache to pages decrypted pages.

The cache holds decrypted page payloads to speed repeated reads. By default it is capped at 8192 pages (~64 MiB); lower the cap to trade hit rate for a smaller footprint, or raise it for a hotter cache. The cap governs clean pages — pages with un-flushed writes are always retained until Mnemo::flush, regardless of the cap.

Source

pub fn cache_stats(&self) -> (usize, usize)

Page-cache occupancy: (pages_cached, capacity).

Source

pub fn session(&mut self, agent_id: impl Into<String>) -> Session<'_>

Begin a conversation Session for agent_id.

The session borrows the database for its lifetime, records turns as working memory, and consolidates them into episodic memory when closed.

Source

pub fn snapshots(&self) -> Vec<SnapshotInfo>

Every committed transaction, oldest first — the restore points available to Mnemo::restore_to and Mnemo::restore_to_time.

Each flush appends one snapshot. Because the storage engine is append-only, the pages a past flush wrote are still on disk, so any listed snapshot can be reinstated exactly. The history reaches back to the last Mnemo::compact_file, which reclaims space by collapsing it.

Source

pub fn restore_to(&mut self, txn_id: u64) -> Result<SnapshotInfo>

Restore the database to the snapshot produced by transaction txn_id.

The restore is itself a new committed transaction (and a new snapshot), so it is crash-safe and reversible — restoring forward to a later snapshot afterwards works just as well.

Source

pub fn restore_to_time(&mut self, unix_secs: i64) -> Result<SnapshotInfo>

Restore the database to the latest snapshot committed at or before unix_secs. Returns MnemoError::NotFound if no snapshot is that old. Like Mnemo::restore_to, the restore is a new transaction.

Source

pub fn rekey(&mut self, new_passphrase: &str, kdf: KdfParams) -> Result<()>

Change the passphrase. Cheap: re-derives the KEK and re-wraps the DEK; the encrypted pages are never rewritten.

Source

pub fn verify(&mut self) -> Result<usize>

Decrypt and validate every live record. Returns the count verified.

Source

pub fn stats(&mut self) -> Result<Stats>

Summary statistics for the open database.

Source

pub fn compact_file(path: &str, passphrase: &str) -> Result<CompactReport>

Rewrite the file, dropping tombstoned and expired memories and reclaiming stale pages left by updates. Done out-of-place via a temp file and an atomic rename.

Auto Trait Implementations§

§

impl Freeze for Mnemo

§

impl RefUnwindSafe for Mnemo

§

impl Send for Mnemo

§

impl Sync for Mnemo

§

impl Unpin for Mnemo

§

impl UnsafeUnpin for Mnemo

§

impl UnwindSafe for Mnemo

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V