Skip to main content

Vein

Struct Vein 

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

“The Vein” — local RAG memory engine backed by SQLite FTS5 + semantic embeddings.

Two retrieval modes, used together:

BM25 (always available) Full-text search via SQLite FTS5 with Porter-stemming. Fast, zero extra GPU cost, works as the fallback when the embedding model isn’t loaded.

Semantic (when LM Studio has an embedding model loaded) Calls /v1/embeddings (nomic-embed-text-v1.5 or similar) to produce 768-dim float vectors for each chunk. At search time the query is embedded and cosine similarity selects the most conceptually relevant chunks — even when no keywords match.

Hybrid search runs BM25 and semantic in parallel, deduplicates by path, and returns the top-k results ranked by combined score. Semantic results score higher when the embedding model is available; BM25 fills the gap when it isn’t.

Indexing is incremental: files are re-indexed only when their mtime changes. Embedding vectors are stored in a separate chunks_vec SQLite table so they survive re-runs without hitting the embedding API again.

Implementations§

Source§

impl Vein

Source

pub fn new<P: AsRef<Path>>( db_path: P, base_url: String, ) -> Result<Self, Box<dyn Error>>

Source

pub fn index_document( &mut self, path: &str, last_modified: i64, full_text: &str, ) -> Result<Vec<String>, Box<dyn Error>>

Index a single file for BM25 search. Skip if mtime hasn’t changed. Returns the chunks that were written (empty if file was unchanged).

Source

pub fn embed_and_store_chunks(&self, path: &str, chunks: &[String])

Embed a set of chunks for one file and store the vectors. Called after index_document returns new chunks. Silently skips if the embedding model is unavailable.

Source

pub fn search_bm25( &self, query: &str, limit: usize, ) -> Result<Vec<SearchResult>, Box<dyn Error>>

BM25-ranked full-text search via FTS5 MATCH.

Source

pub fn search_semantic(&self, query: &str, limit: usize) -> Vec<SearchResult>

Semantic search: embed the query, cosine-similarity against all stored vectors. Returns empty if the embedding model isn’t loaded.

Source

pub fn search_context( &self, query: &str, limit: usize, ) -> Result<Vec<SearchResult>, Box<dyn Error>>

Hybrid search: BM25 + semantic, deduplicated and re-ranked.

Semantic results are preferred (they score higher) when the embedding model is available. BM25 fills in or takes over when it isn’t. Results from the active room (hottest subsystem by edit count) get a small boost so the model gravitates toward what’s currently being worked on.

Source

pub fn index_project(&mut self) -> usize

Walk the entire project and index all source files (BM25 + embeddings).

Skips: target/, .git/, node_modules/, .hematite/, files > 512 KB. Also indexes .hematite/docs/ — the designated reference document drop folder. Returns the number of files processed (unchanged files are fast-pathed).

Source

pub fn index_workspace_artifacts(&mut self, workspace_root: &Path) -> usize

Index workspace-local supporting context that should be available even outside a real project workspace: .hematite/docs/, recent session reports stored in .hematite/reports/, and imported chat exports in .hematite/imports/.

Source

pub fn index_recent_session_reports(&mut self, workspace_root: &Path) -> usize

Index the most recent local session reports by exchange pair so prior decisions remain searchable across launches without flooding the vein.

Source

pub fn index_imported_session_exports(&mut self, workspace_root: &Path) -> usize

Index imported chat exports from .hematite/imports/. Supported inputs include already-normalized > transcripts, Claude Code JSONL, Codex CLI JSONL, simple role/content JSON exports, ChatGPT mapping exports, and Hematite session-report JSON.

Source

pub fn file_count(&self) -> usize

Total number of unique files currently indexed. Session exchange chunks are excluded so status counts stay source/doc centric.

Source

pub fn embedded_chunk_count(&self) -> usize

Number of source/doc chunks that have semantic embedding vectors stored. Session exchange chunks are excluded so status counts stay source/doc centric.

Source

pub fn has_any_embeddings(&self) -> bool

True when any chunk type currently has embeddings available.

Source

pub fn reset(&self)

Wipe all indexed data. The DB file stays on disk; next index_project() call rebuilds from scratch (re-reads all files, re-embeds all chunks).

Source

pub fn inspect_snapshot(&self, hot_limit: usize) -> VeinInspectionSnapshot

Return a compact operator-facing snapshot of what The Vein currently knows. Intended for trust/debug surfaces like /vein-inspect.

Source

pub fn bump_heat(&self, path: &str)

Record an edit to a file. Increments its heat score in file_heat. Called from the tool dispatch after a successful edit_file / write_file / patch_hunk / multi_search_replace so the L1 context stays current.

Source

pub fn hot_file_paths(&self, n: usize) -> Vec<String>

Return the paths of the top hot files (most edited). Used by RepoMapGenerator to bias PageRank toward active files.

Source

pub fn hot_files_weighted(&self, n: usize) -> Vec<(String, f64)>

Return hot files with normalized heat weights in [0.0, 1.0]. The hottest file gets weight 1.0; others are scaled proportionally. Used by RepoMapGenerator to apply heat-weighted PageRank personalization.

Source

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

Build the L1 context block — a compact “hot files” summary injected into the system prompt at session start. Capped at ~150 tokens. Files are grouped by room so the model sees subsystem structure at a glance. Returns None when there are no heat records yet (fresh project).

Trait Implementations§

Auto Trait Implementations§

§

impl Freeze for Vein

§

impl RefUnwindSafe for Vein

§

impl Unpin for Vein

§

impl UnsafeUnpin for Vein

§

impl UnwindSafe for Vein

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<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

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<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: 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: 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> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

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
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,