vectorDb Stable WINMACLNX
A vector similarity search database backed by sqlite-vec. Pairs naturally with ai.embed() for semantic search — store embeddings, then find the nearest neighbors by cosine similarity.
Capability
{
"capabilities": ["db"]
}Import
import { vectorDb } from 'veloxkit'vectorDb.open(path)
Open (or create) a vector store.
const vdb = await vectorDb.open('vectors.db')
// or: vectorDb.open(':memory:') for an ephemeral in-memory storeReturns Promise<VectorDbHandle>
handle.upsert(table, id, vector, meta?)
Insert or replace a vector record.
await vdb.upsert(
'docs', // collection name
'doc-42', // unique record ID
[0.12, -0.34, 0.56, ...], // 384-dim float array (from ai.embed)
{ title: 'Getting started', url: '/intro' } // optional metadata (JSON)
)Parameters
| Param | Type | Description |
|---|---|---|
table | string | Collection / namespace name |
id | string | Unique record identifier |
vector | number[] | Embedding vector |
meta | any | Optional JSON-serialisable metadata |
Returns Promise<void>
handle.search(table, queryVector, limit?)
Find the limit most similar records by cosine similarity.
const results = await vdb.search('docs', queryVec, 5)
// [
// { id: 'doc-7', score: 0.94, metadata: { title: '...' } },
// { id: 'doc-42', score: 0.87, metadata: { title: '...' } },
// ...
// ]Returns Promise<{ id: string, score: number, metadata: any }[]> — sorted by descending score (most similar first).
handle.close()
Release the database connection.
await vdb.close()Semantic search with ai.embed()
The most common use case — pair vectorDb with ai.embed() to build local semantic search:
import { ai, vectorDb } from 'veloxkit'
import { useState, useEffect } from 'react'
// Index documents on startup
async function indexDocuments(docs: { id: string, title: string, body: string }[]) {
const vdb = await vectorDb.open('search.db')
for (const doc of docs) {
const vec = await ai.embed(`${doc.title}\n${doc.body}`)
await vdb.upsert('docs', doc.id, vec, { title: doc.title })
}
await vdb.close()
}
// Search
async function semanticSearch(query: string, limit = 8) {
const vdb = await vectorDb.open('search.db')
const vec = await ai.embed(query)
const results = await vdb.search('docs', vec, limit)
await vdb.close()
return results
}
// Component
function SearchBox() {
const [query, setQuery] = useState('')
const [results, setResults] = useState([])
const handleSearch = async () => {
const hits = await semanticSearch(query)
setResults(hits)
}
return (
<View style={{ gap: 12 }}>
<TextInput value={query} onChangeText={setQuery} placeholder="Search…" width={320} />
<Pressable onPress={handleSearch}
style={{ padding: 10, backgroundColor: '#4a4a7e', borderRadius: 8 }}>
<Text>Search</Text>
</Pressable>
{results.map(r => (
<View key={r.id} style={{ padding: 10, backgroundColor: '#1a1a2e', borderRadius: 6 }}>
<Text style={{ fontWeight: '600' }}>{r.metadata?.title}</Text>
<Text style={{ color: '#9999bb', fontSize: 12 }}>
Score: {(r.score * 100).toFixed(1)}%
</Text>
</View>
))}
</View>
)
}Multiple collections
A single database file can hold many collections — use different table names:
const vdb = await vectorDb.open('app.db')
// Separate collections
await vdb.upsert('notes', noteId, noteVec, { text: note.body })
await vdb.upsert('contacts', contactId, contactVec, { name: contact.name })
await vdb.upsert('emails', emailId, emailVec, { subject: email.subject })
// Search specific collection
const hits = await vdb.search('notes', queryVec, 10)Vector dimensions must be consistent within a collection. If you change the embedding model (and thus the dimension), create a new collection name and re-index.
vectorDb shares the db capability with the regular SQLite API — no additional capability declaration needed.