@wiscale/velesdb-sdk
v1.15.0
Published
VelesDB TypeScript SDK: The Local Vector Database for AI & RAG. Microsecond semantic search in Browser & Node.js.
Downloads
2,208
Maintainers
Readme
@wiscale/velesdb-sdk
Official TypeScript SDK for VelesDB -- the local-first vector database for AI and RAG. Sub-millisecond semantic search in Browser and Node.js.
v1.15.0 | Node.js >= 18 | Browser (WASM) | MIT License
What's New in v1.14.2
- No SDK source change. v1.14.2 is a workspace patch focused on the Python Haystack
DocumentStore(DuplicatePolicy.SKIPcontract fix) and seven version-drift gaps in the release tooling. The TS SDK ships in lock-step with the workspace and is functionally identical to v1.14.1; the version bump only ensuresnpm install @wiscale/velesdb-sdkresolves to the same release line aspip install velesdbandcargo add [email protected].
Previous (v1.14.1)
- Pipeline fix only. v1.14.0 added Haystack 2.x DocumentStore source code on the Python side but the release workflow forgot to publish
haystack-velesdbto PyPI. v1.14.1 closes that gap. No TS SDK source change.
Previous (v1.14.0)
- MSRV Rust 1.89 -- workspace and CI now align with the actual SIMD path (
avx512vpopcntdqtarget feature). No source change for the SDK; bumps in lock-step with the workspace. - Dockerfile auto-sync -- release tooling now keeps
LABEL version=in lock-step across all Dockerfiles. Indirectly improves anyone runningdocker buildagainst a checkout.
Previous (v1.13.7)
- Node.js WASM init fix --
new VelesDB({ backend: 'wasm' }).init()now readsvelesdb_wasm_bg.wasmbytes from disk viafs.readFileso Node 20+ no longer crashes on the brokenfetch('file://')path. Browsers are unchanged. - Lifecycle hardening -- memoised in-flight init promise + generation token make
close()race-free. - Dual ESM + CJS bundles -- TS SDK build emits both formats with
import.meta.url/__filenamepolyfilled correctly.
Previous (v1.13.0)
- WASM VelesQL executor -- full browser-side VelesQL execution: SELECT/INSERT/UPDATE/DELETE/DDL + aggregations (COUNT/SUM/AVG/MIN/MAX) + GROUP BY/HAVING/UNION/INTERSECT/EXCEPT/JOIN/FUSION/MATCH 1-2 hops + NOT De Morgan distribution
- TS SDK coverage raised to 94% -- 423 tests, per-file thresholds codified in
vitest.config.ts - SIFT1M standardized ANN benchmark -- fvecs/ivecs loader + Criterion ef sweep on the INRIA TEXMEX dataset, feature-gated behind
--features bench-sift1m - Security hardening --
validateCollectionName()helper on TS SDK prevents VelesQL injection intrainPq - API consistency --
streamInsertnow serializespayload: nullexplicitly (matchesstreamUpsertPoints)
Previous (v1.12.0)
- Cross-collection MATCH queries --
@collectionannotation on MATCH node patterns enables cross-collection graph queries - MATCH via
/queryendpoint -- MATCH queries can now be executed viaDatabase::execute_query - BFS dedup -- CSR and EdgeStore BFS no longer produce duplicate results for diamond graphs
rrf_kpropagation -- now properly propagated tohybrid_search_with_filterComponentScoresoptimization -- changed to&'static strfor zero-allocation score tagging
Previous (v1.11.1)
- Graph API parity -- 7 new REST endpoints for complete graph operations (delete edge, edge count, list nodes, node edges, node payload, parallel BFS, graph search)
- Bitmap pre-filter -- adaptive strategy selection for filtered search
- CSR graph traversal v2 -- lock-free adjacency with edge IDs and labels
- Bulk insert v2 -- DirectVectorWriter + AsyncIndexBuilder pipeline
Previous (v1.11.0)
- 15 new VelesQL statements -- SHOW COLLECTIONS, DESCRIBE, EXPLAIN, CREATE/DROP INDEX, ANALYZE, TRUNCATE, ALTER COLLECTION, FLUSH, multi-row INSERT, UPSERT, SELECT EDGES, INSERT NODE
- 203 BDD E2E tests -- comprehensive end-to-end test coverage for all VelesQL features
- TRUNCATE on graph collections -- clears nodes + edges in a single statement
- Python
execute_query()-- full VelesQL execution from Python bindings - Cyclomatic complexity ≤ 8 -- refactored 6 hotspots for Codacy compliance
Previous (v1.10.0)
- SearchQuality type --
SearchQualitytype andqualityfield inSearchOptions - StorageMode in HnswParams --
storageModefield in HNSW configuration - Relative score fusion --
'relative_score'fusion strategy - DistanceMetric "ip" alias --
"ip"accepted as alias for"dot" - StorageMode aliases --
"f32","int8","bit"accepted
Previous (v1.9.1)
- Agent Memory API -- semantic, episodic, and procedural memory for AI agents (REST only)
- Graph collections -- dedicated
createGraphCollection()for knowledge graphs (REST only) - Metadata-only collections -- reference tables with no vectors, joinable via VelesQL
- Sparse vector support -- hybrid sparse+dense search on insert and query (REST + WASM)
- Stream insert with backpressure --
streamInsert()for high-throughput ingestion (REST only) - Product Quantization training --
trainPq()for further memory compression (REST only) - Collection analytics --
analyzeCollection(),getCollectionStats(),getCollectionConfig()(REST only) - Property indexes --
createIndex()/listIndexes()/dropIndex()for O(1) lookups (REST only) - Query introspection --
queryExplain()andcollectionSanity()diagnostics (REST only) - Batch search --
searchBatch()for parallel multi-query execution - Lightweight search --
searchIds()returns only IDs and scores (REST only)
Installation
npm install @wiscale/velesdb-sdkSupported Node.js versions
| Node.js | TS SDK | Browser (WASM) | Notes | |---------|--------|----------------|-------| | 18 LTS | ✅ | ✅ | minimum supported | | 20 LTS | ✅ (CI) | ✅ | tested matrix on every PR | | 22 LTS | ✅ | ✅ | latest LTS |
The Node.js WASM init() path was fixed in v1.13.7 to read velesdb_wasm_bg.wasm bytes from disk via fs.readFile instead of the broken fetch('file://') URL — Node ≥ 18 now works out-of-the-box. Browsers were never affected.
Quick Start
WASM Backend (Browser / Node.js)
The WASM backend runs entirely in-process -- no server required. Ideal for browser apps, prototyping, and edge deployments.
import { VelesDB } from '@wiscale/velesdb-sdk';
// 1. Create a client with WASM backend
const db = new VelesDB({ backend: 'wasm' });
await db.init();
// 2. Create a collection (768 dimensions for BERT, 1536 for OpenAI, etc.)
await db.createCollection('documents', {
dimension: 768,
metric: 'cosine'
});
// 3. Upsert vectors with metadata
await db.upsert('documents', {
id: 'doc-1',
vector: new Float32Array(768).fill(0.1),
payload: { title: 'Hello World', category: 'greeting' }
});
// 4. Batch upsert for better throughput
await db.upsertBatch('documents', [
{ id: 'doc-2', vector: new Float32Array(768).fill(0.2), payload: { title: 'Second doc' } },
{ id: 'doc-3', vector: new Float32Array(768).fill(0.3), payload: { title: 'Third doc' } },
]);
// 5. Search for similar vectors
const results = await db.search('documents', queryVector, { k: 5 });
console.log(results);
// [{ id: 'doc-1', score: 0.95, payload: { title: 'Hello World', ... } }, ...]
// 6. Cleanup
await db.close();REST Backend (Server)
The REST backend connects to a running VelesDB server. Use this for production deployments, multi-client access, and persistent storage.
import { VelesDB } from '@wiscale/velesdb-sdk';
const db = new VelesDB({
backend: 'rest',
url: 'http://localhost:8080',
apiKey: 'your-api-key' // optional
});
await db.init();
// Same API as WASM backend
await db.createCollection('products', { dimension: 1536 });
await db.upsert('products', { id: 1, vector: embedding });
const results = await db.search('products', queryVector, { k: 10 });REST backend note: Document IDs must be numeric integers in the range
0..Number.MAX_SAFE_INTEGER. String IDs are only supported with the WASM backend.
Versioned routes: The REST backend uses
/v1/as the canonical route prefix (e.g.POST /v1/collections/{name}/search). Legacy routes without the prefix are accepted for backward compatibility but are deprecated and will be removed in a future major version. Always target/v1/in custom HTTP clients.
API Reference
Client
new VelesDB(config)
Create a new VelesDB client.
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| backend | 'wasm' \| 'rest' | Yes | Backend type |
| url | string | REST only | Server URL |
| apiKey | string | No | API key for authentication |
| timeout | number | No | Request timeout in ms (default: 30000) |
db.init()
Initialize the client. Must be called before any operations. For the REST backend, this verifies connectivity to the server.
db.close()
Close the client and release resources.
Collection Management
db.createCollection(name, config)
Create a vector collection.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| dimension | number | Required | Vector dimension |
| metric | 'cosine' \| 'euclidean' \| 'dot' \| 'hamming' \| 'jaccard' | 'cosine' | Distance metric (aliases: 'ip'/'inner'/'dotproduct' for dot) |
| storageMode | 'full' \| 'sq8' \| 'binary' | 'full' | Quantization mode (aliases: 'f32' for full, 'int8' for sq8, 'bit' for binary) |
| hnsw | { m?: number, efConstruction?: number } | - | HNSW index tuning |
| description | string | - | Optional description |
Storage Modes
| Mode | Memory (768D) | Compression | Use Case |
|------|---------------|-------------|----------|
| full | 3 KB/vector | 1x | Default, max precision |
| sq8 | 776 B/vector | 4x | Production scale, RAM-constrained |
| binary | 96 B/vector | 32x | Edge devices, IoT |
await db.createCollection('embeddings', {
dimension: 768,
metric: 'cosine',
storageMode: 'sq8',
hnsw: { m: 16, efConstruction: 200 }
});db.createGraphCollection(name, config?)
Create a dedicated graph collection for knowledge graph workloads.
await db.createGraphCollection('social', {
dimension: 384, // optional: embed nodes for vector+graph queries
metric: 'cosine',
schemaMode: 'schemaless' // or 'strict'
});db.createMetadataCollection(name)
Create a metadata-only collection (no vectors). Useful for reference tables that can be JOINed with vector collections via VelesQL.
await db.createMetadataCollection('products');db.deleteCollection(name)
Delete a collection and all its data.
db.getCollection(name)
Get collection info. Returns null if not found.
db.listCollections()
List all collections. Returns an array of Collection objects.
Upsert and Retrieve
db.upsert(collection, document)
Upsert (insert or replace) a single vector document.
await db.upsert('docs', {
id: 'unique-id',
vector: [0.1, 0.2, 0.3], // number[] or Float32Array
payload: { key: 'value' }, // optional metadata
sparseVector: { 42: 0.8, 99: 0.3 } // optional sparse vector for hybrid search
});db.upsertBatch(collection, documents)
Upsert multiple vectors in a single call. More efficient than repeated upsert().
await db.upsertBatch('docs', [
{ id: 'a', vector: vecA, payload: { title: 'First' } },
{ id: 'b', vector: vecB, payload: { title: 'Second' } },
]);db.streamInsert(collection, documents)
Insert documents with server backpressure support. Sends documents sequentially, respecting 429 rate limits. Throws BackpressureError if the server pushes back.
await db.streamInsert('docs', largeDocumentArray);db.get(collection, id)
Get a document by ID. Returns null if not found.
db.delete(collection, id)
Delete a document by ID. Returns true if deleted, false if not found.
Search
db.search(collection, query, options?)
Vector similarity search.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| k | number | 10 | Number of results |
| filter | object | - | Payload filter expression |
| includeVectors | boolean | false | Include vectors in results |
| sparseVector | Record<number, number> | - | Sparse vector for hybrid sparse+dense search |
| quality | SearchQuality | - | Search quality mode (e.g., 'fast', 'balanced', 'custom:256', 'adaptive:32:512') |
const results = await db.search('docs', queryVector, {
k: 10,
filter: { category: 'tech' },
includeVectors: true
});
// Returns: SearchResult[] = [{ id, score, payload?, vector? }, ...]db.searchBatch(collection, searches)
Execute multiple search queries in parallel.
const batchResults = await db.searchBatch('docs', [
{ vector: queryA, k: 5 },
{ vector: queryB, k: 10, filter: { type: 'article' } },
]);
// Returns: SearchResult[][] (one result array per query)db.searchIds(collection, query, options?)
Lightweight search returning only IDs and scores (no payloads).
const hits = await db.searchIds('docs', queryVector, { k: 100 });
// Returns: Array<{ id: number, score: number }>db.scroll(collection, request)
Iterate over all points in a collection in stable, paginated batches without a
query vector. Useful for export pipelines, re-embedding, and full-collection
inspection. Pagination is cursor-based — pass the nextCursor from each
ScrollResponse until it is null.
import { ScrollRequest, ScrollResponse } from '@wiscale/velesdb-sdk';
let cursor: string | number | null = null;
let hasMore = true;
while (hasMore) {
const req: ScrollRequest = { batchSize: 100 };
if (cursor !== null) {
req.cursor = cursor;
}
const page: ScrollResponse = await db.scroll('docs', req);
for (const point of page.points) {
console.log(point.id, point.payload);
}
cursor = page.nextCursor;
hasMore = cursor !== null;
}| Field (ScrollRequest) | Type | Default | Description |
|-------------------------|------|---------|-------------|
| cursor | string \| number | - | Cursor from previous ScrollResponse.nextCursor |
| batchSize | number | 100 | Points per page |
| filter | object | - | Optional payload filter expression |
db.textSearch(collection, query, options?)
Full-text search using BM25 scoring.
const results = await db.textSearch('docs', 'machine learning', { k: 10 });db.hybridSearch(collection, vector, textQuery, options?)
Combined vector similarity + BM25 text search with RRF fusion.
const results = await db.hybridSearch(
'docs',
queryVector,
'machine learning',
{ k: 10, vectorWeight: 0.7 } // 70% vector, 30% text
);db.multiQuerySearch(collection, vectors, options?)
Multi-query fusion search for RAG pipelines using Multiple Query Generation (MQG). Combines results from several query vectors into a single ranked list.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| k | number | 10 | Number of results |
| fusion | 'rrf' \| 'average' \| 'maximum' \| 'weighted' \| 'relative_score' | 'rrf' | Fusion strategy |
| fusionParams | object | { k: 60 } | Strategy-specific parameters |
| filter | object | - | Payload filter expression |
// RRF fusion (default) -- best for most RAG use cases
const results = await db.multiQuerySearch('docs', [emb1, emb2, emb3], {
k: 10,
fusion: 'rrf',
fusionParams: { k: 60 }
});
// Weighted fusion
const results = await db.multiQuerySearch('docs', [emb1, emb2], {
k: 10,
fusion: 'weighted',
fusionParams: { avgWeight: 0.6, maxWeight: 0.3, hitWeight: 0.1 }
});
// Relative Score Fusion — linear blend of dense and sparse scores
const results = await db.multiQuerySearch('docs', [emb1, emb2], {
k: 10,
fusion: 'relative_score',
fusionParams: { denseWeight: 0.7, sparseWeight: 0.3 }
});Note: WASM supports
rrf,average,maximum. Theweightedandrelative_scorestrategies are REST-only.
Named sparse indexes — sparseIndexName vs sparseSearchNamed()
A collection can carry multiple sparse indexes (e.g. splade_v2, bm25_titles). The TypeScript SDK exposes two distinct APIs depending on whether you want a dense + sparse hybrid query or a pure sparse query against a named index.
| API | Shape | Use when |
|---|---|---|
| db.search(coll, denseVec, { sparseVector, sparseIndexName }) | dense + sparse hybrid against the named sparse index | You already have a dense embedding and want to combine it with a specific named sparse index in a single search call. The dense vector drives the primary candidate set; the named sparse index re-ranks. |
| db.sparseSearchNamed(coll, sparseVec, indexName, options?) | pure sparse against a named index | You have only a sparse vector (e.g. SPLADE expansion, lexical query) and want to query a specific named sparse index directly. No dense component. |
// Hybrid: dense + sparse via the splade_v2 named index
const hybrid = await db.search('docs', denseEmbedding, {
k: 10,
sparseVector: { 42: 0.8, 99: 0.3 },
sparseIndexName: 'splade_v2',
});
// Pure sparse against the same named index
const sparseOnly = await db.sparseSearchNamed(
'docs',
{ 42: 0.8, 99: 0.3 },
'splade_v2',
{ k: 10 },
);When the collection has only one (default) sparse index, omit sparseIndexName on db.search(); the server picks the default. For named indexes, both APIs require the explicit name.
Note: Both APIs are REST-only when a named index is required. The WASM backend has no concept of named sparse indexes —
sparseIndexNameis silently ignored ondb.search()(the collection's single sparse index is used), anddb.sparseSearchNamed()throwswasmNotSupported. Tracked as a follow-up to either surface awasmNotSupportedthrow onsparseIndexNameor implement named-sparse support in WASM.
Collection Utilities
db.isEmpty(collection)
Returns true if the collection contains no vectors.
db.flush(collection)
Flush pending changes to disk. REST backend only -- the WASM backend runs in-memory and this is a no-op.
db.analyzeCollection(collection)
Compute and return collection statistics.
const stats = await db.analyzeCollection('docs');
console.log(stats.totalPoints, stats.totalSizeBytes);db.getCollectionStats(collection)
Get previously computed statistics. Returns null if the collection has not been analyzed yet.
db.getCollectionConfig(collection)
Get detailed collection configuration (dimension, metric, storage mode, point count, schema).
VelesQL Queries
db.query(collection, queryString, params?, options?)
Execute a VelesQL query. Supports SELECT, WHERE, vector NEAR, GROUP BY, HAVING, ORDER BY, JOIN, UNION/INTERSECT/EXCEPT, and USING FUSION.
// Vector similarity search
const result = await db.query(
'documents',
'SELECT * FROM documents WHERE VECTOR NEAR $query LIMIT 5',
{ query: [0.1, 0.2, 0.3] }
);
// Aggregation
const agg = await db.query(
'products',
`SELECT category, COUNT(*), AVG(price)
FROM products
GROUP BY category
HAVING COUNT(*) > 5`
);
// Hybrid vector + text
const hybrid = await db.query(
'docs',
"SELECT * FROM docs WHERE VECTOR NEAR $v AND content MATCH 'rust' LIMIT 10",
{ v: queryVector }
);
// Cross-collection JOIN
const joined = await db.query(
'orders',
`SELECT * FROM orders
JOIN customers AS c ON orders.customer_id = c.id
WHERE status = $status`,
{ status: 'active' }
);
// Set operations
const combined = await db.query('users',
'SELECT * FROM active_users UNION SELECT * FROM archived_users'
);
// Fusion strategy
const fused = await db.query('docs',
"SELECT * FROM docs USING FUSION(strategy = 'rrf', k = 60) LIMIT 20"
);Query options:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| timeoutMs | number | 30000 | Query timeout in milliseconds |
| stream | boolean | false | Enable streaming response |
db.queryExplain(queryString, params?)
Get the execution plan for a VelesQL query without running it. Returns plan steps, estimated cost, index usage, and detected features.
const plan = await db.queryExplain(
'SELECT * FROM docs WHERE VECTOR NEAR $v LIMIT 10',
{ v: queryVector }
);
console.log(plan.plan); // step-by-step execution plan
console.log(plan.estimatedCost); // { usesIndex, selectivity, complexity }
console.log(plan.features); // { hasVectorSearch, hasFilter, hasJoin, ... }db.collectionSanity(collection)
Run diagnostic checks on a collection (dimensions, search readiness, error counts, hints).
const report = await db.collectionSanity('docs');
console.log(report.checks); // { hasVectors, searchReady, dimensionConfigured }
console.log(report.diagnostics); // { searchRequestsTotal, dimensionMismatchTotal, ... }
console.log(report.hints); // actionable suggestionsVelesQL Query Builder
Build type-safe VelesQL queries with a fluent API instead of raw strings.
import { velesql } from '@wiscale/velesdb-sdk';
// Vector similarity with filters
const builder = velesql()
.match('d', 'Document')
.nearVector('$queryVector', queryVector)
.andWhere('d.category = $cat', { cat: 'tech' })
.orderBy('similarity()', 'DESC')
.limit(10);
const queryString = builder.toVelesQL();
const params = builder.getParams();
const results = await db.query('documents', queryString, params);
// Graph traversal with relationships
const graphQuery = velesql()
.match('p', 'Person')
.rel('KNOWS')
.to('f', 'Person')
.where('p.age > 25')
.return(['p.name', 'f.name'])
.toVelesQL();
// => "MATCH (p:Person)-[:KNOWS]->(f:Person) WHERE p.age > 25 RETURN p.name, f.name"Builder methods: match(), rel(), to(), where(), andWhere(), orWhere(), nearVector(), limit(), offset(), orderBy(), return(), returnAll(), fusion().
Knowledge Graph API
db.addEdge(collection, edge)
Add a directed edge between two nodes.
await db.addEdge('social', {
id: 1,
source: 100,
target: 200,
label: 'FOLLOWS',
properties: { since: '2024-01-01' }
});db.getEdges(collection, options?)
Query edges, optionally filtered by label.
const edges = await db.getEdges('social', { label: 'FOLLOWS' });db.traverseGraph(collection, request)
Traverse the graph using BFS or DFS from a source node.
const result = await db.traverseGraph('social', {
source: 100,
strategy: 'bfs',
maxDepth: 3,
limit: 100,
relTypes: ['FOLLOWS', 'KNOWS']
});
for (const node of result.results) {
console.log(`Node ${node.targetId} at depth ${node.depth}`);
}db.getNodeDegree(collection, nodeId)
Get the in-degree and out-degree of a node.
const degree = await db.getNodeDegree('social', 100);
console.log(`In: ${degree.inDegree}, Out: ${degree.outDegree}`);db.traverseParallel(collection, request)
Multi-source parallel BFS traversal with deduplication. Starts BFS from multiple source nodes simultaneously.
const result = await db.traverseParallel('social', {
sources: [100, 200, 300],
maxDepth: 3,
limit: 50,
relTypes: ['FOLLOWS']
});
for (const node of result.results) {
console.log(`Node ${node.targetId} at depth ${node.depth}`);
}Property Indexes
Create secondary indexes for fast lookups on payload fields.
db.createIndex(collection, options)
// Hash index for O(1) equality lookups
await db.createIndex('users', { label: 'Person', property: 'email' });
// Range index for O(log n) range queries
await db.createIndex('events', {
label: 'Event',
property: 'timestamp',
indexType: 'range'
});db.listIndexes(collection)
const indexes = await db.listIndexes('users');
// [{ label, property, indexType, cardinality, memoryBytes }, ...]db.hasIndex(collection, label, property)
Returns true if the specified index exists.
db.dropIndex(collection, label, property)
Drop an index. Returns true if the index existed and was removed.
Product Quantization
db.trainPq(collection, options?)
Train Product Quantization on a collection for further memory compression beyond SQ8. REST backend only -- delegates to velesdb-server; not available in the WASM backend.
const result = await db.trainPq('embeddings', {
m: 8, // number of subquantizers
k: 256, // centroids per subquantizer
opq: true // enable Optimized PQ
});Agent Memory API
The Agent Memory API provides three memory types for AI agents, built on top of VelesDB's vector and graph storage.
import { VelesDB } from '@wiscale/velesdb-sdk';
const db = new VelesDB({ backend: 'rest', url: 'http://localhost:8080' });
await db.init();
const memory = db.agentMemory({ dimension: 384 });Semantic Memory (facts and knowledge)
// Store a fact
await memory.storeFact('knowledge', {
id: 1,
text: 'VelesDB uses HNSW for vector indexing',
embedding: factEmbedding,
metadata: { source: 'docs', confidence: 0.95 }
});
// Recall similar facts
const facts = await memory.searchFacts('knowledge', queryEmbedding, 5);Episodic Memory (events and experiences)
// Record an event
await memory.recordEvent('events', {
eventType: 'user_query',
data: { query: 'How does HNSW work?', response: '...' },
embedding: eventEmbedding,
metadata: { timestamp: Date.now() }
});
// Recall similar events
const events = await memory.recallEvents('events', queryEmbedding, 5);Procedural Memory (learned patterns)
// Store a procedure
await memory.learnProcedure('procedures', {
name: 'deploy-to-prod',
steps: ['Run tests', 'Build artifacts', 'Push to registry', 'Deploy'],
metadata: { lastUsed: Date.now() }
});
// Find matching procedures
const procs = await memory.recallProcedures('procedures', queryEmbedding, 3);Error Handling
All error classes extend VelesDBError and include a code property for programmatic handling.
import {
VelesDBError,
ValidationError,
ConnectionError,
NotFoundError,
BackpressureError
} from '@wiscale/velesdb-sdk';
try {
await db.search('nonexistent', queryVector);
} catch (error) {
if (error instanceof NotFoundError) {
console.log('Collection not found');
} else if (error instanceof ValidationError) {
console.log('Invalid input:', error.message);
} else if (error instanceof ConnectionError) {
console.log('Server unreachable:', error.message);
} else if (error instanceof BackpressureError) {
console.log('Server overloaded, retry later');
}
}Exports
Everything is importable from the package root:
import {
// Client
VelesDB,
AgentMemoryClient,
// Backends (advanced: use VelesDB client instead)
WasmBackend,
RestBackend,
// Query builder
VelesQLBuilder,
velesql,
type RelDirection,
type RelOptions,
type NearVectorOptions,
type FusionOptions,
// Error classes
VelesDBError,
ValidationError,
ConnectionError,
NotFoundError,
BackpressureError,
// Types (selected)
type VelesDBConfig,
type CollectionConfig,
type VectorDocument,
type SearchOptions,
type SearchQuality,
type SearchResult,
type SparseVector,
type MultiQuerySearchOptions,
type GraphEdge,
type AddEdgeRequest,
type TraverseRequest,
type TraverseResponse,
type QueryApiResponse,
type AgentMemoryConfig,
type SemanticEntry,
type EpisodicEvent,
type ProceduralPattern,
} from '@wiscale/velesdb-sdk';Performance Tips
- Use
upsertBatch()instead of repeatedupsert()calls - Reuse
Float32Arraybuffers for query vectors when possible - Use WASM backend for browser apps (zero network latency)
- Use
searchIds()when you only need IDs and scores (skips payload transfer) - Use
streamInsert()for high-throughput ingestion with backpressure handling - Pre-initialize the client at app startup (
await db.init()) - Tune HNSW with
hnsw: { m: 16, efConstruction: 200 }for higher recall
License
MIT License -- See LICENSE for details.
VelesDB Core and Server are licensed under VelesDB Core License 1.0 (source-available).
