@wiscale/velesdb-sdk 1.4.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,22 @@
1
1
  # @wiscale/velesdb-sdk
2
2
 
3
- Official TypeScript SDK for VelesDB - Vector Search in Microseconds.
3
+ Official TypeScript SDK for [VelesDB](https://github.com/cyberlife-coder/VelesDB) -- the local-first vector database for AI and RAG. Sub-millisecond semantic search in Browser and Node.js.
4
+
5
+ **v1.6.0** | Node.js >= 18 | Browser (WASM) | MIT License
6
+
7
+ ## What's New in v1.6.0
8
+
9
+ - **Agent Memory API** -- semantic, episodic, and procedural memory for AI agents (REST only)
10
+ - **Graph collections** -- dedicated `createGraphCollection()` for knowledge graphs (REST only)
11
+ - **Metadata-only collections** -- reference tables with no vectors, joinable via VelesQL
12
+ - **Sparse vector support** -- hybrid sparse+dense search on insert and query (REST + WASM)
13
+ - **Stream insert with backpressure** -- `streamInsert()` for high-throughput ingestion (REST only)
14
+ - **Product Quantization training** -- `trainPq()` for further memory compression (REST only)
15
+ - **Collection analytics** -- `analyzeCollection()`, `getCollectionStats()`, `getCollectionConfig()` (REST only)
16
+ - **Property indexes** -- `createIndex()` / `listIndexes()` / `dropIndex()` for O(1) lookups (REST only)
17
+ - **Query introspection** -- `queryExplain()` and `collectionSanity()` diagnostics (REST only)
18
+ - **Batch search** -- `searchBatch()` for parallel multi-query execution
19
+ - **Lightweight search** -- `searchIds()` returns only IDs and scores (REST only)
4
20
 
5
21
  ## Installation
6
22
 
@@ -10,65 +26,73 @@ npm install @wiscale/velesdb-sdk
10
26
 
11
27
  ## Quick Start
12
28
 
13
- ### WASM Backend (Browser/Node.js)
29
+ ### WASM Backend (Browser / Node.js)
30
+
31
+ The WASM backend runs entirely in-process -- no server required. Ideal for browser apps, prototyping, and edge deployments.
14
32
 
15
33
  ```typescript
16
34
  import { VelesDB } from '@wiscale/velesdb-sdk';
17
35
 
18
- // Initialize with WASM backend
36
+ // 1. Create a client with WASM backend
19
37
  const db = new VelesDB({ backend: 'wasm' });
20
38
  await db.init();
21
39
 
22
- // Create a collection
40
+ // 2. Create a collection (768 dimensions for BERT, 1536 for OpenAI, etc.)
23
41
  await db.createCollection('documents', {
24
- dimension: 768, // BERT embedding dimension
42
+ dimension: 768,
25
43
  metric: 'cosine'
26
44
  });
27
45
 
28
- // Insert vectors
46
+ // 3. Insert vectors with metadata
29
47
  await db.insert('documents', {
30
48
  id: 'doc-1',
31
49
  vector: new Float32Array(768).fill(0.1),
32
50
  payload: { title: 'Hello World', category: 'greeting' }
33
51
  });
34
52
 
35
- // Batch insert
53
+ // 4. Batch insert for better throughput
36
54
  await db.insertBatch('documents', [
37
- { id: 'doc-2', vector: [...], payload: { title: 'Second doc' } },
38
- { id: 'doc-3', vector: [...], payload: { title: 'Third doc' } },
55
+ { id: 'doc-2', vector: new Float32Array(768).fill(0.2), payload: { title: 'Second doc' } },
56
+ { id: 'doc-3', vector: new Float32Array(768).fill(0.3), payload: { title: 'Third doc' } },
39
57
  ]);
40
58
 
41
- // Search
59
+ // 5. Search for similar vectors
42
60
  const results = await db.search('documents', queryVector, { k: 5 });
43
61
  console.log(results);
44
- // [{ id: 'doc-1', score: 0.95, payload: { title: '...' } }, ...]
62
+ // [{ id: 'doc-1', score: 0.95, payload: { title: 'Hello World', ... } }, ...]
45
63
 
46
- // Cleanup
64
+ // 6. Cleanup
47
65
  await db.close();
48
66
  ```
49
67
 
50
68
  ### REST Backend (Server)
51
69
 
70
+ The REST backend connects to a running VelesDB server. Use this for production deployments, multi-client access, and persistent storage.
71
+
52
72
  ```typescript
53
73
  import { VelesDB } from '@wiscale/velesdb-sdk';
54
74
 
55
75
  const db = new VelesDB({
56
76
  backend: 'rest',
57
77
  url: 'http://localhost:8080',
58
- apiKey: 'your-api-key' // optional
78
+ apiKey: 'your-api-key' // optional
59
79
  });
60
80
 
61
81
  await db.init();
62
82
 
63
83
  // Same API as WASM backend
64
84
  await db.createCollection('products', { dimension: 1536 });
65
- await db.insert('products', { id: 'p1', vector: [...] });
66
- const results = await db.search('products', query, { k: 10 });
85
+ await db.insert('products', { id: 1, vector: embedding });
86
+ const results = await db.search('products', queryVector, { k: 10 });
67
87
  ```
68
88
 
89
+ > **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.
90
+
69
91
  ## API Reference
70
92
 
71
- ### `new VelesDB(config)`
93
+ ### Client
94
+
95
+ #### `new VelesDB(config)`
72
96
 
73
97
  Create a new VelesDB client.
74
98
 
@@ -77,346 +101,617 @@ Create a new VelesDB client.
77
101
  | `backend` | `'wasm' \| 'rest'` | Yes | Backend type |
78
102
  | `url` | `string` | REST only | Server URL |
79
103
  | `apiKey` | `string` | No | API key for authentication |
80
- | `timeout` | `number` | No | Request timeout (ms, default: 30000) |
104
+ | `timeout` | `number` | No | Request timeout in ms (default: 30000) |
105
+
106
+ #### `db.init()`
107
+
108
+ Initialize the client. **Must be called before any operations.** For the REST backend, this verifies connectivity to the server.
109
+
110
+ #### `db.close()`
111
+
112
+ Close the client and release resources.
81
113
 
82
- ### `db.init()`
114
+ ---
83
115
 
84
- Initialize the client. Must be called before any operations.
116
+ ### Collection Management
85
117
 
86
- ### `db.createCollection(name, config)`
118
+ #### `db.createCollection(name, config)`
87
119
 
88
- Create a new collection.
120
+ Create a vector collection.
89
121
 
90
122
  | Option | Type | Default | Description |
91
123
  |--------|------|---------|-------------|
92
124
  | `dimension` | `number` | Required | Vector dimension |
93
125
  | `metric` | `'cosine' \| 'euclidean' \| 'dot' \| 'hamming' \| 'jaccard'` | `'cosine'` | Distance metric |
94
- | `storageMode` | `'full' \| 'sq8' \| 'binary'` | `'full'` | Memory optimization mode |
126
+ | `storageMode` | `'full' \| 'sq8' \| 'binary'` | `'full'` | Quantization mode |
127
+ | `hnsw` | `{ m?: number, efConstruction?: number }` | - | HNSW index tuning |
128
+ | `description` | `string` | - | Optional description |
95
129
 
96
- #### Storage Modes
130
+ ##### Storage Modes
97
131
 
98
132
  | Mode | Memory (768D) | Compression | Use Case |
99
133
  |------|---------------|-------------|----------|
100
134
  | `full` | 3 KB/vector | 1x | Default, max precision |
101
- | `sq8` | 776 B/vector | **4x** | Scale, RAM-constrained |
102
- | `binary` | 96 B/vector | **32x** | Edge, IoT |
135
+ | `sq8` | 776 B/vector | **4x** | Production scale, RAM-constrained |
136
+ | `binary` | 96 B/vector | **32x** | Edge devices, IoT |
103
137
 
104
138
  ```typescript
105
- // Memory-optimized collection
106
139
  await db.createCollection('embeddings', {
107
140
  dimension: 768,
108
141
  metric: 'cosine',
109
- storageMode: 'sq8' // 4x memory reduction
142
+ storageMode: 'sq8',
143
+ hnsw: { m: 16, efConstruction: 200 }
110
144
  });
111
145
  ```
112
146
 
113
- ### `db.insert(collection, document)`
147
+ #### `db.createGraphCollection(name, config?)`
148
+
149
+ Create a dedicated graph collection for knowledge graph workloads.
150
+
151
+ ```typescript
152
+ await db.createGraphCollection('social', {
153
+ dimension: 384, // optional: embed nodes for vector+graph queries
154
+ metric: 'cosine',
155
+ schemaMode: 'schemaless' // or 'strict'
156
+ });
157
+ ```
158
+
159
+ #### `db.createMetadataCollection(name)`
160
+
161
+ Create a metadata-only collection (no vectors). Useful for reference tables that can be JOINed with vector collections via VelesQL.
162
+
163
+ ```typescript
164
+ await db.createMetadataCollection('products');
165
+ ```
166
+
167
+ #### `db.deleteCollection(name)`
114
168
 
115
- Insert a single vector.
169
+ Delete a collection and all its data.
170
+
171
+ #### `db.getCollection(name)`
172
+
173
+ Get collection info. Returns `null` if not found.
174
+
175
+ #### `db.listCollections()`
176
+
177
+ List all collections. Returns an array of `Collection` objects.
178
+
179
+ ---
180
+
181
+ ### Insert and Retrieve
182
+
183
+ #### `db.insert(collection, document)`
184
+
185
+ Insert a single vector document.
116
186
 
117
187
  ```typescript
118
188
  await db.insert('docs', {
119
189
  id: 'unique-id',
120
- vector: [0.1, 0.2, ...], // or Float32Array
121
- payload: { key: 'value' } // optional metadata
190
+ vector: [0.1, 0.2, 0.3], // number[] or Float32Array
191
+ payload: { key: 'value' }, // optional metadata
192
+ sparseVector: { 42: 0.8, 99: 0.3 } // optional sparse vector for hybrid search
122
193
  });
123
194
  ```
124
195
 
125
- ### `db.insertBatch(collection, documents)`
196
+ #### `db.insertBatch(collection, documents)`
197
+
198
+ Insert multiple vectors in a single call. More efficient than repeated `insert()`.
126
199
 
127
- Insert multiple vectors efficiently.
200
+ ```typescript
201
+ await db.insertBatch('docs', [
202
+ { id: 'a', vector: vecA, payload: { title: 'First' } },
203
+ { id: 'b', vector: vecB, payload: { title: 'Second' } },
204
+ ]);
205
+ ```
128
206
 
129
- ### `db.search(collection, query, options)`
207
+ #### `db.streamInsert(collection, documents)`
130
208
 
131
- Search for similar vectors.
209
+ Insert documents with server backpressure support. Sends documents sequentially, respecting 429 rate limits. Throws `BackpressureError` if the server pushes back.
210
+
211
+ ```typescript
212
+ await db.streamInsert('docs', largeDocumentArray);
213
+ ```
214
+
215
+ #### `db.get(collection, id)`
216
+
217
+ Get a document by ID. Returns `null` if not found.
218
+
219
+ #### `db.delete(collection, id)`
220
+
221
+ Delete a document by ID. Returns `true` if deleted, `false` if not found.
222
+
223
+ ---
224
+
225
+ ### Search
226
+
227
+ #### `db.search(collection, query, options?)`
228
+
229
+ Vector similarity search.
132
230
 
133
231
  | Option | Type | Default | Description |
134
232
  |--------|------|---------|-------------|
135
233
  | `k` | `number` | `10` | Number of results |
136
- | `filter` | `object` | - | Filter expression |
234
+ | `filter` | `object` | - | Payload filter expression |
137
235
  | `includeVectors` | `boolean` | `false` | Include vectors in results |
236
+ | `sparseVector` | `Record<number, number>` | - | Sparse vector for hybrid sparse+dense search |
138
237
 
139
- ### `db.delete(collection, id)`
238
+ ```typescript
239
+ const results = await db.search('docs', queryVector, {
240
+ k: 10,
241
+ filter: { category: 'tech' },
242
+ includeVectors: true
243
+ });
244
+ // Returns: SearchResult[] = [{ id, score, payload?, vector? }, ...]
245
+ ```
140
246
 
141
- Delete a vector by ID. Returns `true` if deleted.
247
+ #### `db.searchBatch(collection, searches)`
142
248
 
143
- ### `db.get(collection, id)`
249
+ Execute multiple search queries in parallel.
144
250
 
145
- Get a vector by ID. Returns `null` if not found.
251
+ ```typescript
252
+ const batchResults = await db.searchBatch('docs', [
253
+ { vector: queryA, k: 5 },
254
+ { vector: queryB, k: 10, filter: { type: 'article' } },
255
+ ]);
256
+ // Returns: SearchResult[][] (one result array per query)
257
+ ```
146
258
 
147
- ### `db.textSearch(collection, query, options)` (v0.8.5+)
259
+ #### `db.searchIds(collection, query, options?)`
148
260
 
149
- Full-text search using BM25 algorithm.
261
+ Lightweight search returning only IDs and scores (no payloads).
150
262
 
151
263
  ```typescript
152
- const results = await db.textSearch('docs', 'machine learning', { k: 10 });
264
+ const hits = await db.searchIds('docs', queryVector, { k: 100 });
265
+ // Returns: Array<{ id: number, score: number }>
153
266
  ```
154
267
 
155
- ### `db.hybridSearch(collection, vector, textQuery, options)` (v0.8.5+)
268
+ #### `db.textSearch(collection, query, options?)`
156
269
 
157
- Combined vector + text search with RRF fusion.
270
+ Full-text search using BM25 scoring.
158
271
 
159
272
  ```typescript
160
- const results = await db.hybridSearch(
161
- 'docs',
162
- queryVector,
163
- 'machine learning',
164
- { k: 10, vectorWeight: 0.7 } // 0.7 = 70% vector, 30% text
165
- );
273
+ const results = await db.textSearch('docs', 'machine learning', { k: 10 });
166
274
  ```
167
275
 
168
- ### `db.query(collection, queryString, params?, options?)` (v0.8.5+)
276
+ #### `db.hybridSearch(collection, vector, textQuery, options?)`
169
277
 
170
- Execute a VelesQL query.
278
+ Combined vector similarity + BM25 text search with RRF fusion.
171
279
 
172
280
  ```typescript
173
- // Simple query
174
- const results = await db.query(
175
- 'documents',
176
- "SELECT * FROM documents WHERE category = 'tech' LIMIT 10"
177
- );
178
-
179
- // With vector parameter
180
- const results = await db.query(
181
- 'documents',
182
- "SELECT * FROM documents WHERE VECTOR NEAR $query LIMIT 5",
183
- { query: [0.1, 0.2, ...] }
184
- );
185
-
186
- // Hybrid query
187
- const results = await db.query(
281
+ const results = await db.hybridSearch(
188
282
  'docs',
189
- "SELECT * FROM docs WHERE VECTOR NEAR $v AND content MATCH 'rust' LIMIT 10",
190
- { v: queryVector }
283
+ queryVector,
284
+ 'machine learning',
285
+ { k: 10, vectorWeight: 0.7 } // 70% vector, 30% text
191
286
  );
192
287
  ```
193
288
 
194
- ### `db.multiQuerySearch(collection, vectors, options)` (v1.1.0+) ⭐ NEW
289
+ #### `db.multiQuerySearch(collection, vectors, options?)`
195
290
 
196
- Multi-query fusion search for RAG pipelines using Multiple Query Generation (MQG).
291
+ Multi-query fusion search for RAG pipelines using Multiple Query Generation (MQG). Combines results from several query vectors into a single ranked list.
197
292
 
198
293
  | Option | Type | Default | Description |
199
294
  |--------|------|---------|-------------|
200
295
  | `k` | `number` | `10` | Number of results |
201
296
  | `fusion` | `'rrf' \| 'average' \| 'maximum' \| 'weighted'` | `'rrf'` | Fusion strategy |
202
297
  | `fusionParams` | `object` | `{ k: 60 }` | Strategy-specific parameters |
203
- | `filter` | `object` | - | Filter expression |
298
+ | `filter` | `object` | - | Payload filter expression |
204
299
 
205
300
  ```typescript
206
- // RRF fusion (default) - best for most RAG use cases
301
+ // RRF fusion (default) -- best for most RAG use cases
207
302
  const results = await db.multiQuerySearch('docs', [emb1, emb2, emb3], {
208
303
  k: 10,
209
304
  fusion: 'rrf',
210
305
  fusionParams: { k: 60 }
211
306
  });
212
307
 
213
- // Weighted fusion - like SearchXP scoring
308
+ // Weighted fusion
214
309
  const results = await db.multiQuerySearch('docs', [emb1, emb2], {
215
310
  k: 10,
216
311
  fusion: 'weighted',
217
312
  fusionParams: { avgWeight: 0.6, maxWeight: 0.3, hitWeight: 0.1 }
218
313
  });
314
+ ```
219
315
 
220
- // Average/Maximum fusion
221
- const results = await db.multiQuerySearch('docs', vectors, {
222
- k: 10,
223
- fusion: 'average' // or 'maximum'
224
- });
316
+ > **Note:** WASM supports `rrf`, `average`, `maximum`. The `weighted` strategy is REST-only.
317
+
318
+ ---
319
+
320
+ ### Collection Utilities
321
+
322
+ #### `db.isEmpty(collection)`
323
+
324
+ Returns `true` if the collection contains no vectors.
325
+
326
+ #### `db.flush(collection)`
327
+
328
+ Flush pending changes to disk. **REST backend only** -- the WASM backend runs in-memory and this is a no-op.
329
+
330
+ #### `db.analyzeCollection(collection)`
331
+
332
+ Compute and return collection statistics.
333
+
334
+ ```typescript
335
+ const stats = await db.analyzeCollection('docs');
336
+ console.log(stats.totalPoints, stats.totalSizeBytes);
225
337
  ```
226
338
 
227
- > **Note:** Multi-query fusion is only available with the REST backend.
339
+ #### `db.getCollectionStats(collection)`
340
+
341
+ Get previously computed statistics. Returns `null` if the collection has not been analyzed yet.
228
342
 
229
- ### `db.isEmpty(collection)` (v0.8.11+)
343
+ #### `db.getCollectionConfig(collection)`
230
344
 
231
- Check if a collection is empty.
345
+ Get detailed collection configuration (dimension, metric, storage mode, point count, schema).
346
+
347
+ ---
348
+
349
+ ### VelesQL Queries
350
+
351
+ #### `db.query(collection, queryString, params?, options?)`
352
+
353
+ Execute a VelesQL query. Supports SELECT, WHERE, vector NEAR, GROUP BY, HAVING, ORDER BY, JOIN, UNION/INTERSECT/EXCEPT, and USING FUSION.
232
354
 
233
355
  ```typescript
234
- const empty = await db.isEmpty('documents');
235
- if (empty) {
236
- console.log('No vectors in collection');
237
- }
356
+ // Vector similarity search
357
+ const result = await db.query(
358
+ 'documents',
359
+ 'SELECT * FROM documents WHERE VECTOR NEAR $query LIMIT 5',
360
+ { query: [0.1, 0.2, 0.3] }
361
+ );
362
+
363
+ // Aggregation
364
+ const agg = await db.query(
365
+ 'products',
366
+ `SELECT category, COUNT(*), AVG(price)
367
+ FROM products
368
+ GROUP BY category
369
+ HAVING COUNT(*) > 5`
370
+ );
371
+
372
+ // Hybrid vector + text
373
+ const hybrid = await db.query(
374
+ 'docs',
375
+ "SELECT * FROM docs WHERE VECTOR NEAR $v AND content MATCH 'rust' LIMIT 10",
376
+ { v: queryVector }
377
+ );
378
+
379
+ // Cross-collection JOIN
380
+ const joined = await db.query(
381
+ 'orders',
382
+ `SELECT * FROM orders
383
+ JOIN customers AS c ON orders.customer_id = c.id
384
+ WHERE status = $status`,
385
+ { status: 'active' }
386
+ );
387
+
388
+ // Set operations
389
+ const combined = await db.query('users',
390
+ 'SELECT * FROM active_users UNION SELECT * FROM archived_users'
391
+ );
392
+
393
+ // Fusion strategy
394
+ const fused = await db.query('docs',
395
+ "SELECT * FROM docs USING FUSION(strategy = 'rrf', k = 60) LIMIT 20"
396
+ );
238
397
  ```
239
398
 
240
- ### `db.flush(collection)` (v0.8.11+)
399
+ Query options:
400
+
401
+ | Option | Type | Default | Description |
402
+ |--------|------|---------|-------------|
403
+ | `timeoutMs` | `number` | `30000` | Query timeout in milliseconds |
404
+ | `stream` | `boolean` | `false` | Enable streaming response |
405
+
406
+ #### `db.queryExplain(queryString, params?)`
241
407
 
242
- Flush pending changes to disk.
408
+ Get the execution plan for a VelesQL query without running it. Returns plan steps, estimated cost, index usage, and detected features.
243
409
 
244
410
  ```typescript
245
- await db.flush('documents');
411
+ const plan = await db.queryExplain(
412
+ 'SELECT * FROM docs WHERE VECTOR NEAR $v LIMIT 10',
413
+ { v: queryVector }
414
+ );
415
+ console.log(plan.plan); // step-by-step execution plan
416
+ console.log(plan.estimatedCost); // { usesIndex, selectivity, complexity }
417
+ console.log(plan.features); // { hasVectorSearch, hasFilter, hasJoin, ... }
246
418
  ```
247
419
 
248
- ### `db.close()`
420
+ #### `db.collectionSanity(collection)`
249
421
 
250
- Close the client and release resources.
422
+ Run diagnostic checks on a collection (dimensions, search readiness, error counts, hints).
423
+
424
+ ```typescript
425
+ const report = await db.collectionSanity('docs');
426
+ console.log(report.checks); // { hasVectors, searchReady, dimensionConfigured }
427
+ console.log(report.diagnostics); // { searchRequestsTotal, dimensionMismatchTotal, ... }
428
+ console.log(report.hints); // actionable suggestions
429
+ ```
430
+
431
+ ---
432
+
433
+ ### VelesQL Query Builder
434
+
435
+ Build type-safe VelesQL queries with a fluent API instead of raw strings.
436
+
437
+ ```typescript
438
+ import { velesql } from '@wiscale/velesdb-sdk';
439
+
440
+ // Vector similarity with filters
441
+ const builder = velesql()
442
+ .match('d', 'Document')
443
+ .nearVector('$queryVector', queryVector)
444
+ .andWhere('d.category = $cat', { cat: 'tech' })
445
+ .orderBy('similarity()', 'DESC')
446
+ .limit(10);
251
447
 
252
- ## Knowledge Graph API (v1.2.0+)
448
+ const queryString = builder.toVelesQL();
449
+ const params = builder.getParams();
450
+ const results = await db.query('documents', queryString, params);
253
451
 
254
- VelesDB supports hybrid vector + graph queries.
452
+ // Graph traversal with relationships
453
+ const graphQuery = velesql()
454
+ .match('p', 'Person')
455
+ .rel('KNOWS')
456
+ .to('f', 'Person')
457
+ .where('p.age > 25')
458
+ .return(['p.name', 'f.name'])
459
+ .toVelesQL();
460
+ // => "MATCH (p:Person)-[:KNOWS]->(f:Person) WHERE p.age > 25 RETURN p.name, f.name"
461
+ ```
462
+
463
+ Builder methods: `match()`, `rel()`, `to()`, `where()`, `andWhere()`, `orWhere()`, `nearVector()`, `limit()`, `offset()`, `orderBy()`, `return()`, `returnAll()`, `fusion()`.
464
+
465
+ ---
255
466
 
256
- ### `db.addEdge(collection, edge)`
467
+ ### Knowledge Graph API
468
+
469
+ #### `db.addEdge(collection, edge)`
470
+
471
+ Add a directed edge between two nodes.
257
472
 
258
473
  ```typescript
259
474
  await db.addEdge('social', {
260
- id: 1, source: 100, target: 200,
475
+ id: 1,
476
+ source: 100,
477
+ target: 200,
261
478
  label: 'FOLLOWS',
262
479
  properties: { since: '2024-01-01' }
263
480
  });
264
481
  ```
265
482
 
266
- ### `db.getEdges(collection, options?)`
483
+ #### `db.getEdges(collection, options?)`
484
+
485
+ Query edges, optionally filtered by label.
267
486
 
268
487
  ```typescript
269
488
  const edges = await db.getEdges('social', { label: 'FOLLOWS' });
270
489
  ```
271
490
 
272
- ### `db.traverseGraph(collection, request)`
491
+ #### `db.traverseGraph(collection, request)`
492
+
493
+ Traverse the graph using BFS or DFS from a source node.
273
494
 
274
495
  ```typescript
275
496
  const result = await db.traverseGraph('social', {
276
- source: 100, strategy: 'bfs', maxDepth: 3
497
+ source: 100,
498
+ strategy: 'bfs',
499
+ maxDepth: 3,
500
+ limit: 100,
501
+ relTypes: ['FOLLOWS', 'KNOWS']
277
502
  });
503
+
504
+ for (const node of result.results) {
505
+ console.log(`Node ${node.targetId} at depth ${node.depth}`);
506
+ }
278
507
  ```
279
508
 
280
- ### `db.getNodeDegree(collection, nodeId)`
509
+ #### `db.getNodeDegree(collection, nodeId)`
510
+
511
+ Get the in-degree and out-degree of a node.
281
512
 
282
513
  ```typescript
283
514
  const degree = await db.getNodeDegree('social', 100);
515
+ console.log(`In: ${degree.inDegree}, Out: ${degree.outDegree}`);
284
516
  ```
285
517
 
286
- ## VelesQL v2.0 Queries (v1.4.0+)
518
+ ---
287
519
 
288
- Execute advanced SQL-like queries with aggregation, joins, and set operations.
520
+ ### Property Indexes
289
521
 
290
- ### Aggregation with GROUP BY / HAVING
522
+ Create secondary indexes for fast lookups on payload fields.
291
523
 
292
- ```typescript
293
- // Group by with aggregates
294
- const result = await db.query('products', `
295
- SELECT category, COUNT(*), AVG(price)
296
- FROM products
297
- GROUP BY category
298
- HAVING COUNT(*) > 5 AND AVG(price) > 50
299
- `);
524
+ #### `db.createIndex(collection, options)`
300
525
 
301
- // Access results
302
- for (const row of result.results) {
303
- console.log(row.payload.category, row.payload.count);
304
- }
526
+ ```typescript
527
+ // Hash index for O(1) equality lookups
528
+ await db.createIndex('users', { label: 'Person', property: 'email' });
529
+
530
+ // Range index for O(log n) range queries
531
+ await db.createIndex('events', {
532
+ label: 'Event',
533
+ property: 'timestamp',
534
+ indexType: 'range'
535
+ });
305
536
  ```
306
537
 
307
- ### ORDER BY with similarity()
538
+ #### `db.listIndexes(collection)`
308
539
 
309
540
  ```typescript
310
- // Order by semantic similarity
311
- const result = await db.query('docs', `
312
- SELECT * FROM docs
313
- ORDER BY similarity(vector, $v) DESC
314
- LIMIT 10
315
- `, { v: queryVector });
541
+ const indexes = await db.listIndexes('users');
542
+ // [{ label, property, indexType, cardinality, memoryBytes }, ...]
316
543
  ```
317
544
 
318
- ### JOIN across collections
545
+ #### `db.hasIndex(collection, label, property)`
546
+
547
+ Returns `true` if the specified index exists.
548
+
549
+ #### `db.dropIndex(collection, label, property)`
550
+
551
+ Drop an index. Returns `true` if the index existed and was removed.
552
+
553
+ ---
554
+
555
+ ### Product Quantization
556
+
557
+ #### `db.trainPq(collection, options?)`
558
+
559
+ 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.
319
560
 
320
561
  ```typescript
321
- // Cross-collection join
322
- const result = await db.query('orders', `
323
- SELECT * FROM orders
324
- JOIN customers AS c ON orders.customer_id = c.id
325
- WHERE status = $status
326
- `, { status: 'active' });
562
+ const result = await db.trainPq('embeddings', {
563
+ m: 8, // number of subquantizers
564
+ k: 256, // centroids per subquantizer
565
+ opq: true // enable Optimized PQ
566
+ });
327
567
  ```
328
568
 
329
- ### Set Operations (UNION / INTERSECT / EXCEPT)
569
+ ---
570
+
571
+ ### Agent Memory API
572
+
573
+ The Agent Memory API provides three memory types for AI agents, built on top of VelesDB's vector and graph storage.
330
574
 
331
575
  ```typescript
332
- // Combine query results
333
- const result = await db.query('users', `
334
- SELECT * FROM active_users
335
- UNION
336
- SELECT * FROM archived_users
337
- `);
576
+ import { VelesDB } from '@wiscale/velesdb-sdk';
338
577
 
339
- // Find common elements
340
- const result = await db.query('users', `
341
- SELECT id FROM premium_users
342
- INTERSECT
343
- SELECT id FROM active_users
344
- `);
578
+ const db = new VelesDB({ backend: 'rest', url: 'http://localhost:8080' });
579
+ await db.init();
580
+
581
+ const memory = db.agentMemory({ dimension: 384 });
345
582
  ```
346
583
 
347
- ### Hybrid Search with USING FUSION
584
+ #### Semantic Memory (facts and knowledge)
348
585
 
349
586
  ```typescript
350
- // RRF fusion (default)
351
- const result = await db.query('docs', `
352
- SELECT * FROM docs
353
- USING FUSION(strategy = 'rrf', k = 60)
354
- LIMIT 20
355
- `);
587
+ // Store a fact
588
+ await memory.storeFact('knowledge', {
589
+ id: 1,
590
+ text: 'VelesDB uses HNSW for vector indexing',
591
+ embedding: factEmbedding,
592
+ metadata: { source: 'docs', confidence: 0.95 }
593
+ });
356
594
 
357
- // Weighted fusion
358
- const result = await db.query('docs', `
359
- SELECT * FROM docs
360
- USING FUSION(strategy = 'weighted', vector_weight = 0.7, graph_weight = 0.3)
361
- LIMIT 20
362
- `);
595
+ // Recall similar facts
596
+ const facts = await memory.searchFacts('knowledge', queryEmbedding, 5);
363
597
  ```
364
598
 
365
- ## VelesQL Query Builder (v1.2.0+)
366
-
367
- Build type-safe VelesQL queries with the fluent builder API.
599
+ #### Episodic Memory (events and experiences)
368
600
 
369
601
  ```typescript
370
- import { velesql } from '@wiscale/velesdb-sdk';
602
+ // Record an event
603
+ await memory.recordEvent('events', {
604
+ eventType: 'user_query',
605
+ data: { query: 'How does HNSW work?', response: '...' },
606
+ embedding: eventEmbedding,
607
+ metadata: { timestamp: Date.now() }
608
+ });
371
609
 
372
- // Graph pattern query
373
- const builder = velesql()
374
- .match('d', 'Document')
375
- .nearVector('$queryVector', queryVector)
376
- .andWhere('d.category = $cat', { cat: 'tech' })
377
- .limit(10);
610
+ // Recall similar events
611
+ const events = await memory.recallEvents('events', queryEmbedding, 5);
612
+ ```
378
613
 
379
- const queryString = builder.toVelesQL();
380
- const params = builder.getParams();
381
- const results = await db.query('documents', queryString, params);
614
+ #### Procedural Memory (learned patterns)
382
615
 
383
- // Graph traversal with relationships
384
- const graphQuery = velesql()
385
- .match('p', 'Person')
386
- .rel('KNOWS')
387
- .to('f', 'Person')
388
- .where('p.age > 25')
389
- .return(['p.name', 'f.name'])
390
- .toVelesQL();
616
+ ```typescript
617
+ // Store a procedure
618
+ await memory.learnProcedure('procedures', {
619
+ name: 'deploy-to-prod',
620
+ steps: ['Run tests', 'Build artifacts', 'Push to registry', 'Deploy'],
621
+ metadata: { lastUsed: Date.now() }
622
+ });
623
+
624
+ // Find matching procedures
625
+ const procs = await memory.recallProcedures('procedures', queryEmbedding, 3);
391
626
  ```
392
627
 
628
+ ---
629
+
393
630
  ## Error Handling
394
631
 
632
+ All error classes extend `VelesDBError` and include a `code` property for programmatic handling.
633
+
395
634
  ```typescript
396
- import { VelesDBError, ValidationError, ConnectionError, NotFoundError } from '@wiscale/velesdb-sdk';
635
+ import {
636
+ VelesDBError,
637
+ ValidationError,
638
+ ConnectionError,
639
+ NotFoundError,
640
+ BackpressureError
641
+ } from '@wiscale/velesdb-sdk';
397
642
 
398
643
  try {
399
- await db.search('nonexistent', query);
644
+ await db.search('nonexistent', queryVector);
400
645
  } catch (error) {
401
646
  if (error instanceof NotFoundError) {
402
647
  console.log('Collection not found');
403
648
  } else if (error instanceof ValidationError) {
404
649
  console.log('Invalid input:', error.message);
405
650
  } else if (error instanceof ConnectionError) {
406
- console.log('Connection failed:', error.message);
651
+ console.log('Server unreachable:', error.message);
652
+ } else if (error instanceof BackpressureError) {
653
+ console.log('Server overloaded, retry later');
407
654
  }
408
655
  }
409
656
  ```
410
657
 
658
+ ## Exports
659
+
660
+ Everything is importable from the package root:
661
+
662
+ ```typescript
663
+ import {
664
+ // Client
665
+ VelesDB,
666
+ AgentMemoryClient,
667
+
668
+ // Backends (advanced: use VelesDB client instead)
669
+ WasmBackend,
670
+ RestBackend,
671
+
672
+ // Query builder
673
+ VelesQLBuilder,
674
+ velesql,
675
+
676
+ // Error classes
677
+ VelesDBError,
678
+ ValidationError,
679
+ ConnectionError,
680
+ NotFoundError,
681
+ BackpressureError,
682
+
683
+ // Types (selected)
684
+ type VelesDBConfig,
685
+ type CollectionConfig,
686
+ type VectorDocument,
687
+ type SearchOptions,
688
+ type SearchResult,
689
+ type SparseVector,
690
+ type MultiQuerySearchOptions,
691
+ type GraphEdge,
692
+ type AddEdgeRequest,
693
+ type TraverseRequest,
694
+ type TraverseResponse,
695
+ type QueryApiResponse,
696
+ type AgentMemoryConfig,
697
+ type SemanticEntry,
698
+ type EpisodicEvent,
699
+ type ProceduralPattern,
700
+ } from '@wiscale/velesdb-sdk';
701
+ ```
702
+
411
703
  ## Performance Tips
412
704
 
413
- 1. **Use batch operations** for multiple inserts
414
- 2. **Reuse Float32Array** for queries when possible
415
- 3. **Use WASM backend** for browser apps (no network latency)
416
- 4. **Pre-initialize** the client at app startup
705
+ 1. **Use `insertBatch()`** instead of repeated `insert()` calls
706
+ 2. **Reuse `Float32Array`** buffers for query vectors when possible
707
+ 3. **Use WASM backend** for browser apps (zero network latency)
708
+ 4. **Use `searchIds()`** when you only need IDs and scores (skips payload transfer)
709
+ 5. **Use `streamInsert()`** for high-throughput ingestion with backpressure handling
710
+ 6. **Pre-initialize** the client at app startup (`await db.init()`)
711
+ 7. **Tune HNSW** with `hnsw: { m: 16, efConstruction: 200 }` for higher recall
417
712
 
418
713
  ## License
419
714
 
420
- MIT License - See [LICENSE](./LICENSE) for details.
715
+ MIT License -- See [LICENSE](./LICENSE) for details.
421
716
 
422
- VelesDB Core is licensed under ELv2 (source available).
717
+ VelesDB Core and Server are licensed under VelesDB Core License 1.0 (source-available).