Skip to main content

MemoryService

Struct MemoryService 

Source
pub struct MemoryService<E: Embedder, S: MemoryStore = NativeStore> { /* private fields */ }
Expand description

Local-first agent memory backed by a single VelesDB instance.

Generic over the Embedder so production can use an on-device model while tests use a deterministic, network-free one, and over the MemoryStore backend S so the same orchestration runs over the native, file-backed engine (the default — nothing changes for existing callers) or any other backend that implements the trait (e.g. an in-memory one for WASM).

Two definitions, persistence-gated: the default type parameter itself references NativeStore, which doesn’t exist as a type at all without the feature, so a persistence-free build (e.g. velesdb-wasm) drops the default and every caller names its own MemoryStore backend explicitly.

Implementations§

Source§

impl<E: Embedder, S: MemoryStore> MemoryService<E, S>

Source

pub fn recall_fused( &self, query: &str, k: usize, filter: Option<&Metadata>, opts: FusionOptions, ) -> Result<Vec<Recollection>, MemoryError>

Fused recall: like Self::recall, but also walks the graph from the query’s top vector hit and folds any fact it reaches (hop ≥ 1) into the ranking, scored by opts.graph_boost · graph_weight on top of its normalised vector similarity. A fact the graph reaches never displaces a strong vector hit unless the boosted score genuinely outranks it; a fact the vector pool ranked low (or missed) can still surface if the graph connects it. This is the tri-engine ranking measured on HotpotQA/TimeQA/LoCoMo (examples/multihop, examples/timeqa, examples/locomo) — Self::recall stays pure-vector and unchanged, so existing callers see no behavior shift.

The graph reach requires a wired graph to find anything: it walks edges from Self::relate or the entity hubs Self::remember_extracted auto-wires. Entity hubs themselves are never returned, exactly like Self::recall.

§Errors

Returns MemoryError if embedding, vector search, or graph traversal fails.

Source

pub fn recall_fused_reranked<R: Reranker>( &self, query: &str, k: usize, filter: Option<&Metadata>, opts: FusionOptions, reranker: &R, ) -> Result<Vec<Recollection>, MemoryError>

Like Self::recall_fused, but hands the FULL fused-ranked candidate pool (before the final k cutoff) to reranker for a second-stage re-score, then truncates to k. Closes the ranking-miss gap the LoCoMo ceiling diagnostic found: a relevant fact can be IN the pool (recall@64 ≈ 89% on multi-hop) yet outranked out of a tight k (recall@8 ≈ 50%) — a reranker recovers it without widening k itself.

No built-in reranker ships: bring your own (cross-encoder, LLM judge, …) via Reranker. Never call this as a default — a reranker can also hurt out-of-distribution conversational queries (measured on LoCoMo), so it is opt-in, one call at a time.

§Errors

Returns MemoryError if embedding, vector search, graph traversal, or reranker itself fails.

Source§

impl<E: Embedder> MemoryService<E, NativeStore>

Source

pub fn open<P: AsRef<Path>>(path: P, embedder: E) -> Result<Self, MemoryError>

Open (or create) a native, file-backed memory store at path, using embedder for text vectorization. The store never leaves this directory.

§Errors

Returns MemoryError if the store cannot be opened or the agent memory cannot be initialized for the embedder’s dimension.

Source§

impl<E: Embedder, S: MemoryStore> MemoryService<E, S>

Source

pub fn with_store(store: S, embedder: E) -> Self

Build a service directly over a store backend, bypassing Self::open’s filesystem-specific setup — the constructor a non-native backend (e.g. velesdb-wasm’s in-memory store) uses.

Source

pub fn remember( &self, fact: &str, links: &[Link], metadata: Option<&Metadata>, ) -> Result<u64, MemoryError>

Remember a fact, optionally tagging it with structured metadata (ColumnStore facet) and linking it to existing memories (graph facet). Returns the stable id of the fact (idempotent on identical content).

Every link is validated — target existence AND relation label — before the fact is stored, so bad link input never leaves the fact half-written. If an edge write itself fails afterwards (e.g. a target expiring concurrently), a freshly-created fact is rolled back; a re-remembered fact keeps its updated payload (re-remembering updates metadata by design, and deleting it would destroy prior state). Concurrent remembers of identical content are last-writer-wins, not transactional.

§Errors

Returns MemoryError::EmptyFact for empty/whitespace facts, MemoryError::ReservedKey if metadata names a reserved key (content or any _veles_-prefixed system key), MemoryError::UnknownMemory if a link points at a missing memory, MemoryError::InvalidRelation for a bad relation label, MemoryError::RollbackFailed if an edge write failed and the compensating delete also failed (the fact remains stored), or a storage error if persistence fails.

Source

pub fn remember_with_ttl( &self, fact: &str, links: &[Link], metadata: Option<&Metadata>, ttl_seconds: Option<u64>, ) -> Result<u64, MemoryError>

Like Self::remember, but the fact expires after ttl_seconds.

The expiry is a durable TTL — persisted with the fact (reserved _veles_expires_at payload field), so it survives a process restart, and expired facts stop being recalled. None (or Some(0)) stores the fact permanently, exactly like Self::remember. Metadata and a TTL combine: the metadata is written and the expiry preserved.

§Errors

Same as Self::remember.

Source

pub fn remember_extracted<X: Extractor>( &self, text: &str, extractor: &X, metadata: Option<&Metadata>, ) -> Result<Vec<u64>, MemoryError>

Remember a passage of raw text by running it through an Extractor and storing every fact it yields, auto-wiring the fact↔entity graph.

This is the commodity on top of Self::remember’s bring-your-own-links core: each extracted fact is stored (tagged with metadata), each salient topic becomes a deduplicated hub memory, and every fact is linked to its topics with a bidirectional about/mentions edge. Two facts sharing a topic therefore become reachable from one another, so Self::why has a real graph to traverse with no manual relate().

Entity hubs are content-addressed, so the same topic seen across many calls collapses onto one hub. Returns the ids of the stored facts (entity hubs excluded), in extraction order.

§Errors

Returns MemoryError::EmptyFact for empty/whitespace text, MemoryError::Extract if extraction fails, MemoryError::ReservedKey if metadata names a reserved key, or a storage error if persistence fails.

Source

pub fn recall( &self, query: &str, k: usize, filter: Option<&Metadata>, ) -> Result<Vec<Recollection>, MemoryError>

Recall up to k memories semantically similar to query (vector facet), optionally narrowed to an exact-match metadata filter (ColumnStore facet) — e.g. { "project": "veles", "status": "resolved" }.

A highly selective filter may return fewer than k hits even when more matches exist — raise k for fuller coverage with a narrow filter.

Entity hubs created by Self::remember_extracted are never returned: they are internal graph scaffolding, not facts the caller stored.

Each hit carries its caller metadata (Recollection::metadata, None when the fact carries none) — store a date field (e.g. occurred_at) and it round-trips here, so a caller can sort the result into a chronological, date-stamped context without recall_where’s explicit filters. One extra, single batched lookup covers every returned hit.

§Errors

Returns MemoryError if the semantic query or the metadata lookup fails.

Source

pub fn recall_where( &self, query: &str, k: usize, filters: &[ColumnFilter], ) -> Result<Vec<Recollection>, MemoryError>

Fused recall: semantic NEAR search combined with structured ColumnStore predicates over metadata columns — ranges and comparisons, not just the equality of Self::recall. One query spanning the vector and column facets (e.g. “most similar facts with timestamp in this window”), which a vector-only or equality-only recall cannot express.

Filter values are bound as query parameters (never interpolated), so they cannot inject; filter field names are validated to be plain identifiers. Results come back in similarity order.

§Errors

Returns MemoryError::InvalidFilter if a filter field is not a plain identifier, MemoryError::Embed if the query cannot be embedded, or a storage error if the query fails. An empty query or k == 0 yields [].

Source

pub fn relate( &self, from: u64, to: u64, relation: &str, ) -> Result<u64, MemoryError>

Create a typed edge from -> to. Returns the edge id.

Both endpoints are validated to exist first, so the tool reports an unknown id as client input (UnknownMemory) rather than a generic storage fault — and the graph never gains an edge dangling off a memory that was never stored.

§Errors

Returns MemoryError::UnknownMemory if either endpoint is missing, or a storage error if the edge cannot be created.

Source

pub fn forget(&self, fact_id: u64) -> Result<(), MemoryError>

Forget (delete) the memory with fact_id.

§Errors

Returns MemoryError if the deletion fails.

Source

pub fn why( &self, decision: &str, max_hops: usize, filter: Option<&Metadata>, ) -> Result<Explanation, MemoryError>

Explain a decision: find the best-matching memory (optionally scoped to a metadata filter, e.g. the current project), then walk its typed links up to max_hops away — fusing the vector, ColumnStore, and graph facets.

Returns an empty Explanation when nothing matches the decision.

§Errors

Returns MemoryError if recall or graph traversal fails.

Auto Trait Implementations§

§

impl<E, S> Freeze for MemoryService<E, S>
where S: Freeze, E: Freeze,

§

impl<E, S> RefUnwindSafe for MemoryService<E, S>

§

impl<E, S> Send for MemoryService<E, S>
where S: Send, E: Send,

§

impl<E, S> Sync for MemoryService<E, S>
where S: Sync, E: Sync,

§

impl<E, S> Unpin for MemoryService<E, S>
where S: Unpin, E: Unpin,

§

impl<E, S> UnsafeUnpin for MemoryService<E, S>
where S: UnsafeUnpin, E: UnsafeUnpin,

§

impl<E, S> UnwindSafe for MemoryService<E, S>
where S: UnwindSafe, E: UnwindSafe,

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

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

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

Source§

fn fg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the foreground set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like red() and green(), which have the same functionality but are pithier.

§Example

Set foreground color to white using fg():

use yansi::{Paint, Color};

painted.fg(Color::White);

Set foreground color to white using white().

use yansi::Paint;

painted.white();
Source§

fn primary(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Primary].

§Example
println!("{}", value.primary());
Source§

fn fixed(&self, color: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Fixed].

§Example
println!("{}", value.fixed(color));
Source§

fn rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Rgb].

§Example
println!("{}", value.rgb(r, g, b));
Source§

fn black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Black].

§Example
println!("{}", value.black());
Source§

fn red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Red].

§Example
println!("{}", value.red());
Source§

fn green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Green].

§Example
println!("{}", value.green());
Source§

fn yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Yellow].

§Example
println!("{}", value.yellow());
Source§

fn blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Blue].

§Example
println!("{}", value.blue());
Source§

fn magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Magenta].

§Example
println!("{}", value.magenta());
Source§

fn cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Cyan].

§Example
println!("{}", value.cyan());
Source§

fn white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: White].

§Example
println!("{}", value.white());
Source§

fn bright_black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlack].

§Example
println!("{}", value.bright_black());
Source§

fn bright_red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightRed].

§Example
println!("{}", value.bright_red());
Source§

fn bright_green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightGreen].

§Example
println!("{}", value.bright_green());
Source§

fn bright_yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightYellow].

§Example
println!("{}", value.bright_yellow());
Source§

fn bright_blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlue].

§Example
println!("{}", value.bright_blue());
Source§

fn bright_magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.bright_magenta());
Source§

fn bright_cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightCyan].

§Example
println!("{}", value.bright_cyan());
Source§

fn bright_white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightWhite].

§Example
println!("{}", value.bright_white());
Source§

fn bg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the background set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like on_red() and on_green(), which have the same functionality but are pithier.

§Example

Set background color to red using fg():

use yansi::{Paint, Color};

painted.bg(Color::Red);

Set background color to red using on_red().

use yansi::Paint;

painted.on_red();
Source§

fn on_primary(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Primary].

§Example
println!("{}", value.on_primary());
Source§

fn on_fixed(&self, color: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Fixed].

§Example
println!("{}", value.on_fixed(color));
Source§

fn on_rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Rgb].

§Example
println!("{}", value.on_rgb(r, g, b));
Source§

fn on_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Black].

§Example
println!("{}", value.on_black());
Source§

fn on_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Red].

§Example
println!("{}", value.on_red());
Source§

fn on_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Green].

§Example
println!("{}", value.on_green());
Source§

fn on_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Yellow].

§Example
println!("{}", value.on_yellow());
Source§

fn on_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Blue].

§Example
println!("{}", value.on_blue());
Source§

fn on_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Magenta].

§Example
println!("{}", value.on_magenta());
Source§

fn on_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Cyan].

§Example
println!("{}", value.on_cyan());
Source§

fn on_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: White].

§Example
println!("{}", value.on_white());
Source§

fn on_bright_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlack].

§Example
println!("{}", value.on_bright_black());
Source§

fn on_bright_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightRed].

§Example
println!("{}", value.on_bright_red());
Source§

fn on_bright_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightGreen].

§Example
println!("{}", value.on_bright_green());
Source§

fn on_bright_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightYellow].

§Example
println!("{}", value.on_bright_yellow());
Source§

fn on_bright_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlue].

§Example
println!("{}", value.on_bright_blue());
Source§

fn on_bright_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.on_bright_magenta());
Source§

fn on_bright_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightCyan].

§Example
println!("{}", value.on_bright_cyan());
Source§

fn on_bright_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightWhite].

§Example
println!("{}", value.on_bright_white());
Source§

fn attr(&self, value: Attribute) -> Painted<&T>

Enables the styling Attribute value.

This method should be used rarely. Instead, prefer to use attribute-specific builder methods like bold() and underline(), which have the same functionality but are pithier.

§Example

Make text bold using attr():

use yansi::{Paint, Attribute};

painted.attr(Attribute::Bold);

Make text bold using using bold().

use yansi::Paint;

painted.bold();
Source§

fn bold(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Bold].

§Example
println!("{}", value.bold());
Source§

fn dim(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Dim].

§Example
println!("{}", value.dim());
Source§

fn italic(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Italic].

§Example
println!("{}", value.italic());
Source§

fn underline(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Underline].

§Example
println!("{}", value.underline());

Returns self with the attr() set to [Attribute :: Blink].

§Example
println!("{}", value.blink());

Returns self with the attr() set to [Attribute :: RapidBlink].

§Example
println!("{}", value.rapid_blink());
Source§

fn invert(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Invert].

§Example
println!("{}", value.invert());
Source§

fn conceal(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Conceal].

§Example
println!("{}", value.conceal());
Source§

fn strike(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Strike].

§Example
println!("{}", value.strike());
Source§

fn quirk(&self, value: Quirk) -> Painted<&T>

Enables the yansi Quirk value.

This method should be used rarely. Instead, prefer to use quirk-specific builder methods like mask() and wrap(), which have the same functionality but are pithier.

§Example

Enable wrapping using .quirk():

use yansi::{Paint, Quirk};

painted.quirk(Quirk::Wrap);

Enable wrapping using wrap().

use yansi::Paint;

painted.wrap();
Source§

fn mask(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Mask].

§Example
println!("{}", value.mask());
Source§

fn wrap(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Wrap].

§Example
println!("{}", value.wrap());
Source§

fn linger(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Linger].

§Example
println!("{}", value.linger());
Source§

fn clear(&self) -> Painted<&T>

👎Deprecated since 1.0.1:

renamed to resetting() due to conflicts with Vec::clear(). The clear() method will be removed in a future release.

Returns self with the quirk() set to [Quirk :: Clear].

§Example
println!("{}", value.clear());
Source§

fn resetting(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Resetting].

§Example
println!("{}", value.resetting());
Source§

fn bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Bright].

§Example
println!("{}", value.bright());
Source§

fn on_bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: OnBright].

§Example
println!("{}", value.on_bright());
Source§

fn whenever(&self, value: Condition) -> Painted<&T>

Conditionally enable styling based on whether the Condition value applies. Replaces any previous condition.

See the crate level docs for more details.

§Example

Enable styling painted only when both stdout and stderr are TTYs:

use yansi::{Paint, Condition};

painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);
Source§

fn new(self) -> Painted<Self>
where Self: Sized,

Create a new Painted with a default Style. Read more
Source§

fn paint<S>(&self, style: S) -> Painted<&Self>
where S: Into<Style>,

Apply a style wholesale to self. Any previous style is replaced. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. 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<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