Skip to main content

MenteDb

Struct MenteDb 

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

The unified database facade for MenteDB.

MenteDb coordinates storage, indexing, graph relationships, query parsing, context assembly, and cognitive subsystems into a single coherent API.

All internal state is protected by fine-grained locks, so every public method takes &self. This allows Arc<MenteDb> to be shared across threads without an external RwLock.

Implementations§

Source§

impl MenteDb

Source

pub fn process_turn( &self, input: &ProcessTurnInput, delta_tracker: &mut DeltaTracker, ) -> MenteResult<ProcessTurnResult>

Process a single conversation turn through the full cognitive pipeline.

This is the unified entry point that replaces the duplicated orchestration in MCP and platform. It handles:

  • Context retrieval (speculative cache → hybrid search)
  • Pain signal checking
  • Episodic memory storage (with automatic write inference)
  • Action detection, proactive recall, corrections, sentiment
  • Phantom detection + stream contradiction checking
  • Trajectory tracking + ghost memory creation
  • Speculative cache pre-assembly
  • Fact extraction + edge linking
  • Auto-maintenance (decay / archival / consolidation)

LLM-powered features (entity resolution, topic canonicalization, Bedrock extraction, etc.) should be layered on top by the caller.

Source§

impl MenteDb

Source

pub fn recall_for_injection( &self, query: &InjectionQuery<'_>, ) -> MenteResult<Vec<InjectionCandidate>>

Injection-ready context selection. See the module docs for the policy; this is the API client hooks should prefer over raw recall.

Source

pub fn record_injection_outcome( &self, shown: &[MemoryId], reply_embedding: Option<&[f32]>, ) -> MenteResult<(usize, usize)>

Record the outcome of an injection: every shown memory’s exposure count rises, and memories the reply actually drew on (embedding similarity against the reply) are counted as used and reinforced. Returns (shown_updated, used_count).

Source§

impl MenteDb

Source

pub fn open(path: &Path) -> MenteResult<Self>

Opens (or creates) a MenteDB instance at the given path.

Source

pub fn open_with_config( path: &Path, cognitive_config: CognitiveConfig, ) -> MenteResult<Self>

Opens a MenteDB instance with custom cognitive configuration.

Source

pub fn open_with_embedder( path: &Path, embedder: Box<dyn EmbeddingProvider>, ) -> MenteResult<Self>

Opens a MenteDB instance with a configured embedding provider.

Source

pub fn open_with_embedder_and_config( path: &Path, embedder: Box<dyn EmbeddingProvider>, cognitive_config: CognitiveConfig, ) -> MenteResult<Self>

Opens a MenteDB instance with both embedder and cognitive config.

Source

pub fn set_embedder(&mut self, embedder: Box<dyn EmbeddingProvider>)

Set the embedding provider after construction.

Source

pub fn embed_text(&self, text: &str) -> MenteResult<Option<Vec<f32>>>

Generate an embedding for the given text using the configured provider. Returns None if no provider is configured.

Source

pub fn store(&self, node: MemoryNode) -> MenteResult<()>

Stores a memory node into the database.

The node is persisted to storage, added to all indexes, and registered in the graph for relationship traversal.

When cognitive features are enabled (the default), write inference automatically runs to:

  • Detect contradictions with existing memories
  • Create relationship edges (Related, Supersedes, Contradicts)
  • Invalidate superseded memories
  • Propagate confidence changes through the graph
Source

pub fn store_batch(&self, nodes: Vec<MemoryNode>) -> MenteResult<Vec<MemoryId>>

Store multiple memories in a single batch transaction.

Uses a single WAL lock for all writes, avoiding per-write overhead of flock acquisition, header reload, and LSN scan. Significantly faster for bulk inserts.

Source

pub fn recall(&self, query: &str) -> MenteResult<ContextWindow>

Recalls memories using an MQL query string.

Parses the query, builds an execution plan, runs it against the appropriate indexes/graph, and assembles the results into a token-budget-aware context window.

Source

pub fn recall_similar( &self, embedding: &[f32], k: usize, ) -> MenteResult<Vec<(MemoryId, f32)>>

Shortcut for vector similarity search.

Returns the top-k most similar memory IDs with their scores. Memories that have been superseded, contradicted, or temporally invalidated are automatically excluded from results.

Source

pub fn recall_similar_filtered( &self, embedding: &[f32], k: usize, tags: Option<&[&str]>, time_range: Option<(Timestamp, Timestamp)>, ) -> MenteResult<Vec<(MemoryId, f32)>>

Vector similarity search with optional tag and time range filters.

Source

pub fn recall_similar_at( &self, embedding: &[f32], k: usize, at: Timestamp, ) -> MenteResult<Vec<(MemoryId, f32)>>

Vector similarity search at a specific point in time.

Only returns memories that were temporally valid at the given timestamp. Superseded/contradicted memories are excluded unless the edge itself was not yet valid at that time.

Source

pub fn recall_similar_filtered_at( &self, embedding: &[f32], k: usize, at: Timestamp, tags: Option<&[&str]>, time_range: Option<(Timestamp, Timestamp)>, ) -> MenteResult<Vec<(MemoryId, f32)>>

Vector similarity search at a specific point in time with optional filters.

Only returns memories that were temporally valid at the given timestamp. Superseded/contradicted memories are excluded unless the edge itself was not yet valid at that time. Optionally filters by tags and time range.

Source

pub fn recall_hybrid_at( &self, embedding: &[f32], query_text: Option<&str>, k: usize, at: Timestamp, tags: Option<&[&str]>, time_range: Option<(Timestamp, Timestamp)>, ) -> MenteResult<Vec<(MemoryId, f32)>>

Hybrid search combining vector similarity and BM25 keyword matching.

When query_text is provided, BM25 results are fused with vector results via Reciprocal Rank Fusion (RRF) for better recall on exact entity names, dates, and specific terms.

Source

pub fn recall_hybrid_at_mode( &self, embedding: &[f32], query_text: Option<&str>, k: usize, at: Timestamp, tags: Option<&[&str]>, tags_or: bool, time_range: Option<(Timestamp, Timestamp)>, ) -> MenteResult<Vec<(MemoryId, f32)>>

Hybrid recall with configurable tag mode (AND vs OR).

Source

pub fn recall_hybrid_scoped_at_mode( &self, embedding: &[f32], query_text: Option<&str>, k: usize, at: Timestamp, tags: Option<&[&str]>, tags_or: bool, time_range: Option<(Timestamp, Timestamp)>, agent: Option<AgentId>, ) -> MenteResult<Vec<(MemoryId, f32)>>

Hybrid recall visible to one agent: nodes owned by agent or owned by no agent (nil, shared knowledge) pass; other agents’ memories are invisible. agent: None recalls globally, preserving single agent behavior.

Source

pub fn recall_similar_multi( &self, embeddings: &[Vec<f32>], k: usize, tags: Option<&[&str]>, time_range: Option<(Timestamp, Timestamp)>, ) -> MenteResult<Vec<(MemoryId, f32)>>

Multi-query search with Reciprocal Rank Fusion (RRF).

Runs multiple vector searches (one per embedding) and merges results using RRF: score = Σ 1/(k + rank_i). This improves recall by matching on different semantic aspects of a query. When query_texts is provided, each search also runs BM25 matching.

Source

pub fn recall_hybrid_multi( &self, embeddings: &[Vec<f32>], query_texts: Option<&[String]>, k: usize, tags: Option<&[&str]>, time_range: Option<(Timestamp, Timestamp)>, ) -> MenteResult<Vec<(MemoryId, f32)>>

Multi-query hybrid search with BM25 + vector fusion.

Each query text is searched via both BM25 and vector, then all results are merged via RRF.

Source

pub fn recall_hybrid_multi_mode( &self, embeddings: &[Vec<f32>], query_texts: Option<&[String]>, k: usize, tags: Option<&[&str]>, tags_or: bool, time_range: Option<(Timestamp, Timestamp)>, ) -> MenteResult<Vec<(MemoryId, f32)>>

Multi-query hybrid search with configurable tag mode.

Source

pub fn invalidate_memory(&self, id: MemoryId, at: Timestamp) -> MenteResult<()>

Invalidate a memory by setting its valid_until timestamp.

The memory remains in storage for historical queries but is excluded from current recall results.

Source

pub fn relate(&self, edge: MemoryEdge) -> MenteResult<()>

Adds a typed, weighted edge between two memories in the graph.

Source

pub fn get_memory(&self, id: MemoryId) -> MenteResult<MemoryNode>

Retrieves a single memory by its ID.

Source

pub fn memory_ids(&self) -> Vec<MemoryId>

Returns all memory IDs currently stored in the database.

Source

pub fn memory_count(&self) -> usize

Returns the number of memories currently stored.

Source

pub fn forget(&self, id: MemoryId) -> MenteResult<()>

Removes a memory from storage, indexes, and the graph.

Source

pub fn graph(&self) -> &GraphManager

Returns a reference to the underlying graph manager.

Source

pub fn graph_mut(&mut self) -> &mut GraphManager

👎Deprecated:

GraphManager now uses interior mutability; use graph() instead

Returns a mutable reference to the underlying graph manager.

Source

pub fn cognitive_config(&self) -> &CognitiveConfig

Returns a reference to the cognitive configuration.

Source

pub fn apply_decay(&self, memories: &mut [MemoryNode])

Apply salience decay to a batch of memories in-place.

Call this during retrieval to ensure scores reflect temporal relevance, or periodically to maintain salience accuracy across the database.

Source

pub fn compute_decayed_salience(&self, memory: &MemoryNode) -> f32

Compute the decayed salience for a single memory at the current time.

Source

pub fn apply_decay_global(&self) -> MenteResult<usize>

Apply decay globally: recompute salience for all memories and persist.

This is an expensive operation intended for periodic maintenance. For real-time use, prefer apply_decay on retrieved memories.

Source

pub fn find_consolidation_candidates( &self, min_cluster_size: usize, similarity_threshold: f32, ) -> MenteResult<Vec<ConsolidationCandidate>>

Find groups of similar memories that are candidates for consolidation.

Returns clusters of memories that share high semantic similarity and could be merged into unified knowledge.

Source

pub fn consolidate_cluster( &self, memory_ids: &[MemoryId], ) -> MenteResult<MemoryId>

Consolidate a cluster of memories into a single merged memory.

The source memories are invalidated (not deleted) and a new consolidated semantic memory is stored with Derived edges back to the sources.

Source

pub fn close(&self) -> MenteResult<()>

Flushes all data and closes the database.

Source

pub fn close_quick(&self) -> MenteResult<()>

Close with durability only: checkpoint the WAL and release the process lock without rewriting snapshots. Reopen reconciles stale snapshots, so this trades a slower next open for a shutdown fast enough to release every user’s lock inside a deploy drain window.

Source

pub fn rebuild_indexes(&self) -> MenteResult<usize>

Rebuild all indexes by scanning every memory in storage.

Use this after index corruption or when index files were overwritten. Returns the number of memories re-indexed.

Source

pub fn flush(&self) -> MenteResult<()>

Flush indexes, graph, and storage to disk without closing.

Call this periodically to ensure cross-session persistence. Unlike close(), the database remains usable after flushing.

Source

pub fn flush_full(&self) -> MenteResult<()>

Flush everything including index, graph, and cognitive snapshots. Used by close and by maintenance, where reopen speed matters more than write latency.

Source

pub fn record_pain(&self, signal: PainSignal)

Record a pain signal — a recurring failure or frustration pattern.

Pain signals are tracked by keywords and surfaced as warnings when similar contexts arise in future queries.

Source

pub fn get_pain_warnings(&self, context_keywords: &[String]) -> Vec<PainSignal>

Get pain warnings relevant to the given context keywords.

Returns formatted warning text if any pain signals match the keywords. Use this before answering to warn about past failures.

Source

pub fn format_pain_warnings(&self, signals: &[&PainSignal]) -> String

Format pain warnings as a human-readable string.

Source

pub fn decay_pain(&self)

Decay all pain signals to reduce intensity over time.

Source

pub fn all_pain_signals(&self) -> Vec<PainSignal>

Get all recorded pain signals.

Source

pub fn record_trajectory_turn(&self, turn: TrajectoryNode)

Record a conversation turn in the trajectory tracker.

Tracks the evolution of topics, decisions, and open questions across a conversation. Used for resume context and topic prediction.

Source

pub fn get_resume_context(&self) -> Option<String>

Get a resume context string summarizing the conversation so far.

Returns None if no trajectory has been recorded.

Source

pub fn predict_next_topics(&self) -> Vec<String>

Predict the next likely topics based on conversation trajectory.

Returns up to 3 predicted topic strings based on transition patterns.

Source

pub fn get_trajectory(&self) -> Vec<TrajectoryNode>

Get the full trajectory of recorded turns.

Source

pub fn reinforce_transition(&self, hit_topic: &str)

Reinforce a transition that led to a speculative cache hit.

Source

pub fn feed_stream_token(&self, token: &str)

Feed a token to the cognition stream for real-time monitoring.

Tokens are buffered and analyzed for contradictions with known facts when check_stream_alerts() is called.

Source

pub fn check_stream_alerts( &self, known_facts: &[(MemoryId, String)], ) -> Vec<StreamAlert>

Check for stream alerts against known facts.

Compares the buffered token stream against the provided known facts to detect contradictions, corrections, and reinforcements.

Source

pub fn drain_stream_buffer(&self) -> String

Drain the token buffer, returning accumulated text.

Source

pub fn detect_phantoms( &self, content: &str, known_entities: &[String], turn_id: u64, ) -> Vec<PhantomMemory>

Detect phantom memories — entities referenced in content but not stored.

Scans content for entity mentions that don’t exist in the known entities list, flagging them as knowledge gaps that should be filled.

Source

pub fn resolve_phantom(&self, phantom_id: MemoryId)

Resolve a phantom memory (mark it as no longer a gap).

Source

pub fn get_active_phantoms(&self) -> Vec<PhantomMemory>

Get all active (unresolved) phantom memories, sorted by priority.

Source

pub fn format_phantom_warnings(&self) -> String

Format phantom warnings as a human-readable string.

Source

pub fn register_entity(&self, entity: &str)

Register an entity so the phantom tracker knows it exists.

Source

pub fn register_entities(&self, entities: &[&str])

Register multiple entities at once.

Source

pub fn try_speculative_hit( &self, query: &str, query_embedding: Option<&[f32]>, ) -> Option<CacheEntry>

Try to hit the speculative cache for a query.

If a previous prediction matches the current query (by keyword overlap or embedding similarity), returns the pre-assembled context.

Source

pub fn pre_assemble_speculative<F>(&self, predictions: Vec<String>, builder: F)
where F: Fn(&str) -> Option<(String, Vec<MemoryId>, Option<Vec<f32>>)>,

Pre-assemble speculative cache entries for predicted topics.

The builder function should return (context_text, memory_ids, optional_embedding) for each topic prediction.

Source

pub fn evict_stale_speculative(&self, max_age_us: u64)

Evict stale entries from the speculative cache.

Source

pub fn speculative_cache_stats(&self) -> CacheStats

Get speculative cache statistics.

Source

pub fn detect_interference( &self, memories: &[MemoryNode], ) -> Vec<InterferencePair>

Detect interference between a set of memories.

Returns pairs of memories that are similar enough to cause confusion, along with disambiguation hints. Use this during context assembly to add disambiguation notes or separate confusable memories.

Source

pub fn generate_disambiguation(&self, a: &MemoryNode, b: &MemoryNode) -> String

Generate a disambiguation hint for two confusable memories.

Source

pub fn arrange_with_separation( memories: Vec<MemoryId>, pairs: &[InterferencePair], ) -> Vec<MemoryId>

Arrange memory IDs to maximize separation between interfering pairs.

Source

pub fn resolve_entity(&self, name: &str) -> ResolvedEntity

Resolve an entity name to its canonical form.

Uses cached aliases and rule-based matching (no LLM).

Source

pub fn add_entity_alias(&self, alias: &str, canonical: &str, confidence: f32)

Add an alias mapping for entity resolution.

Source

pub fn get_canonical_entity(&self, name: &str) -> Option<String>

Get the canonical name for an entity, if known.

Source

pub fn known_entities(&self) -> Vec<String>

List all known entities in the resolver.

Source

pub fn compress_memory(&self, memory: &MemoryNode) -> CompressedMemory

Compress a memory’s content, extracting key facts and removing filler.

Returns a compressed representation with the original ID, compressed text, compression ratio, and extracted key facts.

Source

pub fn compress_memories( &self, memories: &[MemoryNode], ) -> Vec<CompressedMemory>

Compress a batch of memories.

Source

pub fn estimate_tokens(text: &str) -> usize

Estimate token count for a text string.

Source

pub fn evaluate_archival(&self, memory: &MemoryNode) -> ArchivalDecision

Evaluate whether a memory should be kept, archived, or deleted.

Uses age, salience, and access patterns to make lifecycle decisions.

Source

pub fn evaluate_archival_batch( &self, memories: &[MemoryNode], ) -> Vec<(MemoryId, ArchivalDecision)>

Evaluate archival decisions for a batch of memories.

Source

pub fn evaluate_archival_global( &self, ) -> MenteResult<Vec<(MemoryId, ArchivalDecision)>>

Run archival evaluation on all memories in the database.

Returns decisions for each memory. Does NOT apply them — call invalidate_memory or forget to act on the decisions.

Source

pub fn needs_enrichment(&self) -> bool

Check whether enrichment is pending (triggered by turn count or manual).

Source

pub fn last_enrichment_turn(&self) -> u64

Get the turn ID when enrichment last completed.

Source

pub fn request_enrichment(&self)

Manually trigger enrichment on the next check.

Source

pub fn enrichment_candidates(&self) -> Vec<MemoryNode>

Get episodic memories that haven’t been enriched yet.

Returns all Episodic memories created after the last enrichment turn, sorted by creation time. These are the candidates for LLM extraction.

Source

pub fn store_enrichment_memories( &self, memories: Vec<MemoryNode>, source_ids: &[MemoryId], ) -> MenteResult<(usize, usize)>

Store enrichment results: extracted memories with provenance tracking.

Each stored memory gets:

  • source:enrichment tag for identification
  • Confidence capped at max_enrichment_confidence
  • Derived edges back to source episodic memories

Returns (memories_stored, edges_created).

Source

pub fn mark_enrichment_complete(&self, turn_id: u64)

Mark enrichment as complete for the given turn.

Source

pub fn enrichment_config(&self) -> &EnrichmentConfig

Get the enrichment configuration.

Source

pub fn all_entity_names(&self) -> Vec<String>

Get all unique entity names from stored entity memories.

Returns deduplicated, normalized entity names extracted from entity:{name} tags across all stored memories.

Source

pub fn unresolved_entity_names(&self) -> Vec<String>

Get entity names that the EntityResolver hasn’t resolved yet.

These are the entities that need LLM resolution. The EntityResolver cache handles known entities for free.

Source

pub fn entity_names_with_context(&self) -> Vec<(String, Option<String>)>

Get entity names with their memory content for LLM context.

Returns (name, content) pairs for entities that need resolution. The content helps the LLM disambiguate (e.g., “Python” near “web framework” vs “Python” near “Monty Python”).

Apply LLM entity resolution results: create graph edges and update cache.

Takes merge groups from the LLM (via CognitiveLlmService.resolve_entities()) and confirmed-different pairs. Creates entity_link: edges between entity memories that belong to the same group, learns aliases in the EntityResolver, and negative-caches confirmed-different pairs.

Link entities using only the sync EntityResolver (cache + rules, no LLM).

This is the fast path — links entities that are already known to be the same from previous LLM resolutions. For full LLM-powered resolution, use unresolved_entity_names() + apply_entity_link_resolutions().

Source

pub fn entity_memories(&self) -> Vec<MemoryNode>

Get all entity memory nodes (memories tagged with entity:{name}).

Source

pub fn entity_communities(&self) -> HashMap<String, Vec<(String, String)>>

Get entity categories with their member entities for community detection.

Returns a map of category → list of (entity_name, context_snippet). Categories come from entity_type: tags on entity memories.

Source

pub fn store_community_summary( &self, category: &str, summary: &str, member_names: &[String], ) -> MenteResult<MemoryId>

Store a community summary memory with edges to member entities.

Creates a community_summary tagged memory and Derived edges from the summary to each member entity in the category.

Source

pub fn community_summaries(&self) -> Vec<MemoryNode>

Get existing community summaries.

Source

pub fn profile_facts(&self) -> Vec<String>

Collect all semantic/procedural facts for user profile generation.

Returns high-confidence memories suitable for profile building.

Source

pub fn store_user_profile(&self, profile: &str) -> MenteResult<MemoryId>

Store or update the user profile as an always-scoped memory.

There is exactly one user profile memory (tagged user_profile). If one already exists, it’s replaced entirely.

Source

pub fn user_profile(&self) -> Option<MemoryNode>

Get the current user profile, if one exists.

Auto Trait Implementations§

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> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
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

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more