@wiscale/velesdb-sdk 1.5.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: 1, 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,356 +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?)`
114
148
 
115
- Insert a single vector.
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)`
168
+
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
  });
194
+ ```
195
+
196
+ #### `db.insertBatch(collection, documents)`
197
+
198
+ Insert multiple vectors in a single call. More efficient than repeated `insert()`.
123
199
 
124
- // REST backend note:
125
- // IDs must be numeric and within JS safe integer range (0..Number.MAX_SAFE_INTEGER).
126
- // Non-numeric strings are rejected.
200
+ ```typescript
201
+ await db.insertBatch('docs', [
202
+ { id: 'a', vector: vecA, payload: { title: 'First' } },
203
+ { id: 'b', vector: vecB, payload: { title: 'Second' } },
204
+ ]);
127
205
  ```
128
206
 
129
- ### `db.insertBatch(collection, documents)`
207
+ #### `db.streamInsert(collection, documents)`
130
208
 
131
- Insert multiple vectors efficiently.
209
+ Insert documents with server backpressure support. Sends documents sequentially, respecting 429 rate limits. Throws `BackpressureError` if the server pushes back.
132
210
 
133
- ### `db.search(collection, query, options)`
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
+ ---
134
224
 
135
- Search for similar vectors.
225
+ ### Search
226
+
227
+ #### `db.search(collection, query, options?)`
228
+
229
+ Vector similarity search.
136
230
 
137
231
  | Option | Type | Default | Description |
138
232
  |--------|------|---------|-------------|
139
233
  | `k` | `number` | `10` | Number of results |
140
- | `filter` | `object` | - | Filter expression |
234
+ | `filter` | `object` | - | Payload filter expression |
141
235
  | `includeVectors` | `boolean` | `false` | Include vectors in results |
236
+ | `sparseVector` | `Record<number, number>` | - | Sparse vector for hybrid sparse+dense search |
142
237
 
143
- ### `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
+ ```
144
246
 
145
- Delete a vector by ID. Returns `true` if deleted.
247
+ #### `db.searchBatch(collection, searches)`
146
248
 
147
- ### `db.get(collection, id)`
249
+ Execute multiple search queries in parallel.
148
250
 
149
- 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
+ ```
150
258
 
151
- ### `db.textSearch(collection, query, options)` (v0.8.5+)
259
+ #### `db.searchIds(collection, query, options?)`
152
260
 
153
- Full-text search using BM25 algorithm.
261
+ Lightweight search returning only IDs and scores (no payloads).
154
262
 
155
263
  ```typescript
156
- 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 }>
157
266
  ```
158
267
 
159
- ### `db.hybridSearch(collection, vector, textQuery, options)` (v0.8.5+)
268
+ #### `db.textSearch(collection, query, options?)`
160
269
 
161
- Combined vector + text search with RRF fusion.
270
+ Full-text search using BM25 scoring.
162
271
 
163
272
  ```typescript
164
- const results = await db.hybridSearch(
165
- 'docs',
166
- queryVector,
167
- 'machine learning',
168
- { k: 10, vectorWeight: 0.7 } // 0.7 = 70% vector, 30% text
169
- );
273
+ const results = await db.textSearch('docs', 'machine learning', { k: 10 });
170
274
  ```
171
275
 
172
- ### `db.query(collection, queryString, params?, options?)` (v0.8.5+)
276
+ #### `db.hybridSearch(collection, vector, textQuery, options?)`
173
277
 
174
- Execute a VelesQL query.
278
+ Combined vector similarity + BM25 text search with RRF fusion.
175
279
 
176
280
  ```typescript
177
- // Simple query
178
- const results = await db.query(
179
- 'documents',
180
- "SELECT * FROM documents WHERE category = 'tech' LIMIT 10"
181
- );
182
-
183
- // With vector parameter
184
- const results = await db.query(
185
- 'documents',
186
- "SELECT * FROM documents WHERE VECTOR NEAR $query LIMIT 5",
187
- { query: [0.1, 0.2, ...] }
188
- );
189
-
190
- // Hybrid query
191
- const results = await db.query(
281
+ const results = await db.hybridSearch(
192
282
  'docs',
193
- "SELECT * FROM docs WHERE VECTOR NEAR $v AND content MATCH 'rust' LIMIT 10",
194
- { v: queryVector }
195
- );
196
-
197
- // Aggregation query (returns { result, stats })
198
- const agg = await db.query(
199
- 'documents',
200
- "SELECT COUNT(*) AS total FROM documents"
283
+ queryVector,
284
+ 'machine learning',
285
+ { k: 10, vectorWeight: 0.7 } // 70% vector, 30% text
201
286
  );
202
287
  ```
203
288
 
204
- ### `db.multiQuerySearch(collection, vectors, options)` (v1.1.0+) ⭐ NEW
289
+ #### `db.multiQuerySearch(collection, vectors, options?)`
205
290
 
206
- 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.
207
292
 
208
293
  | Option | Type | Default | Description |
209
294
  |--------|------|---------|-------------|
210
295
  | `k` | `number` | `10` | Number of results |
211
296
  | `fusion` | `'rrf' \| 'average' \| 'maximum' \| 'weighted'` | `'rrf'` | Fusion strategy |
212
297
  | `fusionParams` | `object` | `{ k: 60 }` | Strategy-specific parameters |
213
- | `filter` | `object` | - | Filter expression |
298
+ | `filter` | `object` | - | Payload filter expression |
214
299
 
215
300
  ```typescript
216
- // RRF fusion (default) - best for most RAG use cases
301
+ // RRF fusion (default) -- best for most RAG use cases
217
302
  const results = await db.multiQuerySearch('docs', [emb1, emb2, emb3], {
218
303
  k: 10,
219
304
  fusion: 'rrf',
220
305
  fusionParams: { k: 60 }
221
306
  });
222
307
 
223
- // Weighted fusion - like SearchXP scoring
308
+ // Weighted fusion
224
309
  const results = await db.multiQuerySearch('docs', [emb1, emb2], {
225
310
  k: 10,
226
311
  fusion: 'weighted',
227
312
  fusionParams: { avgWeight: 0.6, maxWeight: 0.3, hitWeight: 0.1 }
228
313
  });
314
+ ```
229
315
 
230
- // Average/Maximum fusion
231
- const results = await db.multiQuerySearch('docs', vectors, {
232
- k: 10,
233
- fusion: 'average' // or 'maximum'
234
- });
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);
235
337
  ```
236
338
 
237
- > **Note:** WASM supports `rrf`, `average`, `maximum`. `weighted` is REST-only.
339
+ #### `db.getCollectionStats(collection)`
238
340
 
239
- ### `db.isEmpty(collection)` (v0.8.11+)
341
+ Get previously computed statistics. Returns `null` if the collection has not been analyzed yet.
240
342
 
241
- Check if a collection is empty.
343
+ #### `db.getCollectionConfig(collection)`
344
+
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.
242
354
 
243
355
  ```typescript
244
- const empty = await db.isEmpty('documents');
245
- if (empty) {
246
- console.log('No vectors in collection');
247
- }
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
+ );
248
397
  ```
249
398
 
250
- ### `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?)`
251
407
 
252
- 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.
253
409
 
254
410
  ```typescript
255
- 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, ... }
256
418
  ```
257
419
 
258
- ### `db.close()`
420
+ #### `db.collectionSanity(collection)`
259
421
 
260
- 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
+ ```
261
430
 
262
- ## Knowledge Graph API (v1.2.0+)
431
+ ---
263
432
 
264
- VelesDB supports hybrid vector + graph queries.
433
+ ### VelesQL Query Builder
265
434
 
266
- ### `db.addEdge(collection, edge)`
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);
447
+
448
+ const queryString = builder.toVelesQL();
449
+ const params = builder.getParams();
450
+ const results = await db.query('documents', queryString, params);
451
+
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
+ ---
466
+
467
+ ### Knowledge Graph API
468
+
469
+ #### `db.addEdge(collection, edge)`
470
+
471
+ Add a directed edge between two nodes.
267
472
 
268
473
  ```typescript
269
474
  await db.addEdge('social', {
270
- id: 1, source: 100, target: 200,
475
+ id: 1,
476
+ source: 100,
477
+ target: 200,
271
478
  label: 'FOLLOWS',
272
479
  properties: { since: '2024-01-01' }
273
480
  });
274
481
  ```
275
482
 
276
- ### `db.getEdges(collection, options?)`
483
+ #### `db.getEdges(collection, options?)`
484
+
485
+ Query edges, optionally filtered by label.
277
486
 
278
487
  ```typescript
279
488
  const edges = await db.getEdges('social', { label: 'FOLLOWS' });
280
489
  ```
281
490
 
282
- ### `db.traverseGraph(collection, request)`
491
+ #### `db.traverseGraph(collection, request)`
492
+
493
+ Traverse the graph using BFS or DFS from a source node.
283
494
 
284
495
  ```typescript
285
496
  const result = await db.traverseGraph('social', {
286
- source: 100, strategy: 'bfs', maxDepth: 3
497
+ source: 100,
498
+ strategy: 'bfs',
499
+ maxDepth: 3,
500
+ limit: 100,
501
+ relTypes: ['FOLLOWS', 'KNOWS']
287
502
  });
503
+
504
+ for (const node of result.results) {
505
+ console.log(`Node ${node.targetId} at depth ${node.depth}`);
506
+ }
288
507
  ```
289
508
 
290
- ### `db.getNodeDegree(collection, nodeId)`
509
+ #### `db.getNodeDegree(collection, nodeId)`
510
+
511
+ Get the in-degree and out-degree of a node.
291
512
 
292
513
  ```typescript
293
514
  const degree = await db.getNodeDegree('social', 100);
515
+ console.log(`In: ${degree.inDegree}, Out: ${degree.outDegree}`);
294
516
  ```
295
517
 
296
- ## VelesQL v2.0 Queries (v1.4.0+)
518
+ ---
297
519
 
298
- Execute advanced SQL-like queries with aggregation, joins, and set operations.
520
+ ### Property Indexes
299
521
 
300
- ### Aggregation with GROUP BY / HAVING
522
+ Create secondary indexes for fast lookups on payload fields.
301
523
 
302
- ```typescript
303
- // Group by with aggregates
304
- const result = await db.query('products', `
305
- SELECT category, COUNT(*), AVG(price)
306
- FROM products
307
- GROUP BY category
308
- HAVING COUNT(*) > 5 AND AVG(price) > 50
309
- `);
524
+ #### `db.createIndex(collection, options)`
310
525
 
311
- // Access results
312
- for (const row of result.results) {
313
- console.log(row.payload.category, row.payload.count);
314
- }
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
+ });
315
536
  ```
316
537
 
317
- ### ORDER BY with similarity()
538
+ #### `db.listIndexes(collection)`
318
539
 
319
540
  ```typescript
320
- // Order by semantic similarity
321
- const result = await db.query('docs', `
322
- SELECT * FROM docs
323
- ORDER BY similarity(vector, $v) DESC
324
- LIMIT 10
325
- `, { v: queryVector });
541
+ const indexes = await db.listIndexes('users');
542
+ // [{ label, property, indexType, cardinality, memoryBytes }, ...]
326
543
  ```
327
544
 
328
- ### 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.
329
560
 
330
561
  ```typescript
331
- // Cross-collection join
332
- const result = await db.query('orders', `
333
- SELECT * FROM orders
334
- JOIN customers AS c ON orders.customer_id = c.id
335
- WHERE status = $status
336
- `, { 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
+ });
337
567
  ```
338
568
 
339
- ### 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.
340
574
 
341
575
  ```typescript
342
- // Combine query results
343
- const result = await db.query('users', `
344
- SELECT * FROM active_users
345
- UNION
346
- SELECT * FROM archived_users
347
- `);
576
+ import { VelesDB } from '@wiscale/velesdb-sdk';
348
577
 
349
- // Find common elements
350
- const result = await db.query('users', `
351
- SELECT id FROM premium_users
352
- INTERSECT
353
- SELECT id FROM active_users
354
- `);
578
+ const db = new VelesDB({ backend: 'rest', url: 'http://localhost:8080' });
579
+ await db.init();
580
+
581
+ const memory = db.agentMemory({ dimension: 384 });
355
582
  ```
356
583
 
357
- ### Hybrid Search with USING FUSION
584
+ #### Semantic Memory (facts and knowledge)
358
585
 
359
586
  ```typescript
360
- // RRF fusion (default)
361
- const result = await db.query('docs', `
362
- SELECT * FROM docs
363
- USING FUSION(strategy = 'rrf', k = 60)
364
- LIMIT 20
365
- `);
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
+ });
366
594
 
367
- // Weighted fusion
368
- const result = await db.query('docs', `
369
- SELECT * FROM docs
370
- USING FUSION(strategy = 'weighted', vector_weight = 0.7, graph_weight = 0.3)
371
- LIMIT 20
372
- `);
595
+ // Recall similar facts
596
+ const facts = await memory.searchFacts('knowledge', queryEmbedding, 5);
373
597
  ```
374
598
 
375
- ## VelesQL Query Builder (v1.2.0+)
376
-
377
- Build type-safe VelesQL queries with the fluent builder API.
599
+ #### Episodic Memory (events and experiences)
378
600
 
379
601
  ```typescript
380
- 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
+ });
381
609
 
382
- // Graph pattern query
383
- const builder = velesql()
384
- .match('d', 'Document')
385
- .nearVector('$queryVector', queryVector)
386
- .andWhere('d.category = $cat', { cat: 'tech' })
387
- .limit(10);
610
+ // Recall similar events
611
+ const events = await memory.recallEvents('events', queryEmbedding, 5);
612
+ ```
388
613
 
389
- const queryString = builder.toVelesQL();
390
- const params = builder.getParams();
391
- const results = await db.query('documents', queryString, params);
614
+ #### Procedural Memory (learned patterns)
392
615
 
393
- // Graph traversal with relationships
394
- const graphQuery = velesql()
395
- .match('p', 'Person')
396
- .rel('KNOWS')
397
- .to('f', 'Person')
398
- .where('p.age > 25')
399
- .return(['p.name', 'f.name'])
400
- .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);
401
626
  ```
402
627
 
628
+ ---
629
+
403
630
  ## Error Handling
404
631
 
632
+ All error classes extend `VelesDBError` and include a `code` property for programmatic handling.
633
+
405
634
  ```typescript
406
- 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';
407
642
 
408
643
  try {
409
- await db.search('nonexistent', query);
644
+ await db.search('nonexistent', queryVector);
410
645
  } catch (error) {
411
646
  if (error instanceof NotFoundError) {
412
647
  console.log('Collection not found');
413
648
  } else if (error instanceof ValidationError) {
414
649
  console.log('Invalid input:', error.message);
415
650
  } else if (error instanceof ConnectionError) {
416
- 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');
417
654
  }
418
655
  }
419
656
  ```
420
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
+
421
703
  ## Performance Tips
422
704
 
423
- 1. **Use batch operations** for multiple inserts
424
- 2. **Reuse Float32Array** for queries when possible
425
- 3. **Use WASM backend** for browser apps (no network latency)
426
- 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
427
712
 
428
713
  ## License
429
714
 
430
- MIT License - See [LICENSE](./LICENSE) for details.
715
+ MIT License -- See [LICENSE](./LICENSE) for details.
431
716
 
432
- VelesDB Core is licensed under ELv2 (source available).
717
+ VelesDB Core and Server are licensed under VelesDB Core License 1.0 (source-available).