velesdb_memory/lib.rs
1#![deny(unsafe_code)]
2//! # VelesDB-memory
3//!
4//! Local-first **memory** layer for AI agents, exposed through a single MCP
5//! server. This crate is the domain core: it maps nine memory operations onto
6//! `VelesDB`'s in-core Agent Memory SDK.
7//!
8//! | Operation | Meaning |
9//! |--------------------|-----------------------------------------------------|
10//! | `remember` | store a fact (+ optional links to other memories) |
11//! | `recall` | semantic retrieval of similar facts |
12//! | `recall_where` | semantic retrieval filtered by metadata |
13//! | `recall_fused` | vector + graph fused retrieval |
14//! | `relate` | create a typed edge between two memories |
15//! | `forget` | delete a memory |
16//! | `why` | recall + multi-hop graph traversal |
17//! | `feedback` | reinforce or penalize a memory after use |
18//! | `remember_extracted`| extract facts from raw text and auto-wire the graph|
19//!
20//! ## License boundary (non-negotiable)
21//!
22//! This crate exposes **memory semantics only** (results), never raw database
23//! capabilities (`query(velesql)`, `create_collection`, `upsert(vectors)`,
24//! `traverse(graph)`). Exposing the raw engine would constitute a "Substantial
25//! Set" of the Software's features and breach the `VelesDB` Core License 1.0
26//! (§1, No Hosted or Managed Service). See `VISION.md` §5 and `PLAN.md` Phase 4A.
27
28/// Wall-clock "today" as a `YYYYMMDD` integer, read only by `remember`'s
29/// auto-date stamping (see [`storage::AUTO_DATE_FIELD`]) — never by the
30/// context compiler, which stays clock-free and deterministic. Internal:
31/// nothing outside the crate needs to read the clock directly.
32mod clock;
33/// The ONE `ColumnFilter` conformance table both `MemoryStore` backends run,
34/// so the native (`VelesQL`-translating) and WASM (payload-testing) paths
35/// cannot drift apart again (#1759). Deliberately NOT target-gated: the WASM
36/// backend is one of the two that must run it.
37pub mod column_filter_conformance;
38/// The optional TOML configuration file: one place to set every knob, with
39/// `command line > environment > file > default` precedence. Native-only —
40/// it reads the filesystem.
41#[cfg(not(target_arch = "wasm32"))]
42pub mod config;
43/// The deterministic context compiler (EPIC-P-070): classify, dedup, and pack
44/// caller-supplied context fragments under a token budget — no LLM, no cloud,
45/// every decision auditable. Gated behind the default `context` feature.
46#[cfg(feature = "context")]
47pub mod context;
48/// Format recalled facts as a chronological, date-prefixed timeline with a
49/// "now" anchor — the dated-context representation measured to lift temporal
50/// question answering, shipped as product behavior rather than a harness prompt.
51pub mod dated_context;
52pub mod embedder;
53/// Which embedding model filled a store, and whether the configured one can
54/// still read it. Gated on `persistence` because an unrecorded store is a
55/// directory on disk — see the module docs for why the *backend* is
56/// deliberately not part of the record.
57#[cfg(feature = "persistence")]
58pub mod embedding_provenance;
59pub mod error;
60#[cfg(feature = "persistence")]
61pub mod export;
62pub mod extract;
63/// Vector+graph score fusion — the ranking layer behind
64/// [`service::MemoryService::recall_fused`]. Internal: callers reach it only
65/// through that method.
66mod fusion;
67/// The streamable-HTTP transport (multi-client mode): lets several MCP
68/// clients share ONE `velesdb-memory` process instead of each spawning its
69/// own stdio process and fighting over the store's single-writer `flock`.
70/// Gated behind the (non-default) `http` feature — see the module docs and
71/// the crate README's "HTTP transport (multi-client)" section.
72#[cfg(feature = "http")]
73pub mod http;
74/// Synchronous retry + actionable failure reporting shared by the two blocking
75/// Ollama call sites ([`embedder`] and [`extract`]). Internal: it exists to make
76/// those two backends resilient, not to be a general-purpose retry API.
77#[cfg(any(feature = "ollama", feature = "extract"))]
78mod http_retry;
79/// Content-addressed memory ids — internal; ids surface through the service API.
80pub(crate) mod id;
81/// Resource caps (DoS limits) shared by every adapter — the single source of
82/// truth for fact size, recall limit, and `why` hop depth.
83pub mod limits;
84/// Per-request observability, gated by `VELESDB_MEMORY_LOG` (#1780): silent
85/// by default, stderr only, never a payload. Rides the `mcp` feature with
86/// the server it observes.
87#[cfg(feature = "mcp")]
88pub mod logging;
89/// The MCP server transport. Gated behind the default `mcp` feature so library
90/// consumers (e.g. the language bindings) can depend on the memory core without
91/// pulling the `rmcp`/`tokio` server stack.
92#[cfg(feature = "mcp")]
93pub mod mcp;
94/// Read-only diagnosis of a store an embedding-model change made unopenable,
95/// and the feasibility proof the rebuild depends on (#1762). Never writes to
96/// the store it inspects.
97#[cfg(feature = "persistence")]
98pub mod migration;
99/// The domain data model — the value types the memory layer exchanges
100/// (`Link`, `Recollection`, `ColumnFilter`, `Explanation`, …), separate from the
101/// service that computes them.
102pub mod model;
103
104/// Authenticated JSON over HTTP: the transport under every remote inference
105/// backend, with no knowledge of role or vendor.
106#[cfg(any(feature = "ollama", feature = "extract"))]
107pub mod http_client;
108
109/// The OpenAI-compatible protocol — paths, bodies, responses — over
110/// [`http_client`].
111#[cfg(any(feature = "ollama", feature = "extract"))]
112mod openai;
113/// Is a configured remote inference backend actually reachable? (#1751 D2)
114///
115/// Gated exactly like [`openai`], which it builds its URL with, and like the
116/// `ureq` agent it probes through: without either role's feature there is no
117/// remote backend to be unreachable, and no transport to ask with. Declaring
118/// it unconditionally compiled here and nowhere else — the default build has
119/// neither dependency.
120#[cfg(any(feature = "ollama", feature = "extract"))]
121pub mod reachability;
122/// Where a remote embedding/extraction backend's URL, model and credential
123/// come from, resolved from the environment once so the daemon and the
124/// language bindings read the same variables the same way (#1886).
125#[cfg(any(feature = "ollama", feature = "extract"))]
126pub mod remote_endpoint;
127/// Optional second-stage re-scoring of a fused recall pool (bring your own
128/// cross-encoder/LLM). Never wired in by default — see [`rerank::Reranker`].
129pub mod rerank;
130/// Shared JSON Schema post-processing (strips `schemars`' non-standard integer
131/// `format` keywords so strict MCP clients don't warn on every id field).
132mod schema;
133pub mod service;
134/// The storage backend abstraction — [`storage::MemoryStore`] and the
135/// default, file-backed [`storage::NativeStore`]. Implement `MemoryStore` to
136/// run the wedge over a different backend (e.g. an in-memory one for WASM).
137pub mod storage;
138/// Locally-generated TLS material (a cached self-signed CA + short-lived
139/// leaf certs) for the streamable-HTTP transport's HTTPS-by-default
140/// listener — see the module docs for the full design rationale. Gated
141/// behind `http` since it exists only to serve that transport.
142#[cfg(feature = "http")]
143pub mod tls;
144
145/// Default embedding dimension — the single source of truth, taken from the
146/// SDK's own default so the server, library, and tests never restate the
147/// value. `velesdb_core::agent` (where the canonical constant lives) is
148/// itself `persistence`-gated, so a `persistence`-free build (e.g.
149/// `velesdb-wasm`) falls back to `FALLBACK_DIMENSION`.
150#[cfg(feature = "persistence")]
151pub const DEFAULT_DIMENSION: usize = velesdb_core::agent::DEFAULT_DIMENSION;
152#[cfg(not(feature = "persistence"))]
153pub const DEFAULT_DIMENSION: usize = FALLBACK_DIMENSION;
154
155/// The hand-written value the `persistence`-free arm of
156/// [`DEFAULT_DIMENSION`] falls back to (the canonical constant's module is
157/// feature-gated away there). The `persistence` build — CI's default —
158/// statically asserts it still equals the canonical value, so drift fails
159/// to compile instead of silently splitting the wasm default dimension
160/// from the native one.
161const FALLBACK_DIMENSION: usize = 384;
162#[cfg(feature = "persistence")]
163const _: () = assert!(
164 FALLBACK_DIMENSION == velesdb_core::agent::DEFAULT_DIMENSION,
165 "update FALLBACK_DIMENSION to match velesdb_core::agent::DEFAULT_DIMENSION"
166);
167
168#[cfg(feature = "context")]
169pub use context::ContextCompiler;
170pub use dated_context::{format_dated_context, DatedContext};
171pub use embedder::{
172 select_embedder, DynEmbedder, EmbedError, Embedder, EmbedderSelection, HashEmbedder,
173};
174#[cfg(feature = "ollama")]
175pub use embedder::{OllamaEmbedder, OpenAiEmbedder, DEFAULT_OLLAMA_MODEL, DEFAULT_OLLAMA_URL};
176pub use error::{ErrorCategory, MemoryError};
177pub use extract::{
178 select_extractor, DynExtractor, ExtractError, ExtractedAttribute, ExtractedFact,
179 ExtractedRelation, Extraction, Extractor, ExtractorSelection, OutlineExtractor,
180};
181#[cfg(feature = "extract")]
182pub use extract::{OllamaExtractor, OpenAiExtractor};
183#[cfg(any(feature = "ollama", feature = "extract"))]
184pub use http_client::{Auth, HttpJsonClient};
185#[cfg(feature = "mcp")]
186pub use mcp::McpServer;
187pub use model::{
188 column_value_matches, BoundedMemoryEdges, ColumnFilter, ColumnOp, EntityProfile,
189 EntityRelation, Explanation, FusionOptions, Link, MemoryEdge, MemoryNode, Recollection,
190 RememberedExtraction, UnrelateOutcome,
191};
192#[cfg(feature = "ollama")]
193pub use remote_endpoint::embedder_env_endpoint;
194#[cfg(any(feature = "ollama", feature = "extract"))]
195pub use remote_endpoint::{role_auth, RemoteEndpoint};
196pub use rerank::{DynReranker, RerankError, Reranker};
197pub use service::{AutographWorkerHandle, MemoryService, Metadata};
198#[cfg(feature = "persistence")]
199pub use storage::NativeStore;
200pub use storage::{MemoryStore, AUTO_DATE_FIELD};