std.db
An in-process vector store, for semantic search and retrieval.
import std.db
db.add("doc1", "The moon is made of rock.")
db.add("doc2", "Cheese is a dairy product.")
hits = db.search("what is the moon made of?", limit: 3)
# [{ id: "doc1", text: "...", score: 0.83 }, ...]
db.save("knowledge.json")
db.load("knowledge.json")
db.remove("doc2")
db.count()
db.clear()
net to embed, fs to persist.
How it works
add embeds the text and keeps the vector. search embeds the query and scores by cosine similarity over a full scan.
A full scan is the honest choice at this scale: for the document counts a RAG pipeline actually holds - hundreds to tens of thousands - it is fast, exact, and has no index to build, tune or invalidate. It is not a distributed vector database and does not pretend to be.
Process-global
There is one store per process. save and load persist it as JSON.
That means it is not durable and not shared. Two processes have two stores; a restart loses everything not saved. For a persistent shared index, use a real database, or save and load around your process lifecycle.
Offline
Embeddings come from the configured provider (ECKO_AI_EMBED_MODEL). Without a key, deterministic mock embeddings keep similarity search working - so the retrieval path is testable in CI with no network.
Mock vectors are stable but not semantically meaningful: offline, "moon" and "cheese" have an arbitrary similarity. Structure is testable; retrieval quality needs a real model. See Embeddings & RAG.
Higher level
std.rag wraps chunking, indexing, retrieval and grounded answering into a pipeline. Reach for db when you want to manage the store yourself, and rag when you want the usual arrangement.