@wiscale/velesdb-sdk 1.11.0 → 1.13.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/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- // src/types.ts
1
+ // src/types/errors.ts
2
2
  var VelesDBError = class extends Error {
3
3
  constructor(message, code, cause) {
4
4
  super(message);
@@ -32,6 +32,610 @@ var BackpressureError = class extends VelesDBError {
32
32
  }
33
33
  };
34
34
 
35
+ // src/capabilities.ts
36
+ var REST_CAPABILITIES = Object.freeze({
37
+ vectorSearch: true,
38
+ textSearch: true,
39
+ hybridSearch: true,
40
+ multiQuerySearch: true,
41
+ sparseSearch: true,
42
+ scroll: true,
43
+ graphTraversal: true,
44
+ secondaryIndexes: true,
45
+ agentMemory: true,
46
+ streamInsert: true,
47
+ pqTraining: true,
48
+ velesqlQuery: true,
49
+ collectionIntrospection: true
50
+ });
51
+ var WASM_CAPABILITIES = Object.freeze({
52
+ vectorSearch: true,
53
+ textSearch: true,
54
+ hybridSearch: true,
55
+ multiQuerySearch: true,
56
+ sparseSearch: false,
57
+ scroll: false,
58
+ graphTraversal: false,
59
+ secondaryIndexes: false,
60
+ agentMemory: false,
61
+ streamInsert: false,
62
+ pqTraining: false,
63
+ velesqlQuery: true,
64
+ collectionIntrospection: false
65
+ });
66
+
67
+ // src/backends/wasm-helpers.ts
68
+ function normalizeIdString(id) {
69
+ const trimmed = id.trim();
70
+ return /^\d+$/.test(trimmed) ? trimmed : null;
71
+ }
72
+ function canonicalPayloadKeyFromResultId(id) {
73
+ if (typeof id === "bigint") {
74
+ return id.toString();
75
+ }
76
+ if (typeof id === "number") {
77
+ return String(Math.trunc(id));
78
+ }
79
+ const normalized = normalizeIdString(id);
80
+ if (normalized !== null) {
81
+ return normalized.replace(/^0+(?=\d)/, "");
82
+ }
83
+ return String(toNumericId(id));
84
+ }
85
+ function canonicalPayloadKey(id) {
86
+ if (typeof id === "number") {
87
+ return String(Math.trunc(id));
88
+ }
89
+ const normalized = normalizeIdString(id);
90
+ if (normalized !== null) {
91
+ return normalized.replace(/^0+(?=\d)/, "");
92
+ }
93
+ return String(toNumericId(id));
94
+ }
95
+ function sparseVectorToArrays(sv) {
96
+ const indices = [];
97
+ const values = [];
98
+ for (const [k, v] of Object.entries(sv)) {
99
+ indices.push(Number(k));
100
+ values.push(v);
101
+ }
102
+ return { indices, values };
103
+ }
104
+ function toNumericId(id) {
105
+ if (typeof id === "number") {
106
+ return id;
107
+ }
108
+ const normalized = normalizeIdString(id);
109
+ if (normalized !== null) {
110
+ const parsed = Number(normalized);
111
+ if (Number.isSafeInteger(parsed)) {
112
+ return parsed;
113
+ }
114
+ }
115
+ let hash = 0;
116
+ for (let i = 0; i < id.length; i++) {
117
+ const char = id.charCodeAt(i);
118
+ hash = (hash << 5) - hash + char;
119
+ hash = hash & hash;
120
+ }
121
+ return Math.abs(hash);
122
+ }
123
+ function buildWasmContext(wasmModule, collections) {
124
+ return {
125
+ wasmModule,
126
+ getCollection: (name) => collections.get(name),
127
+ canonicalPayloadKeyFromResultId: (id) => canonicalPayloadKeyFromResultId(id),
128
+ canonicalPayloadKey: (id) => canonicalPayloadKey(id),
129
+ sparseVectorToArrays: (sv) => sparseVectorToArrays(sv),
130
+ toNumericId: (id) => toNumericId(id)
131
+ };
132
+ }
133
+ function buildCollectionInfo(name, data) {
134
+ return {
135
+ name,
136
+ dimension: data.config.dimension ?? 0,
137
+ metric: data.config.metric ?? "cosine",
138
+ count: data.store.len,
139
+ createdAt: data.createdAt
140
+ };
141
+ }
142
+
143
+ // src/backends/wasm-search.ts
144
+ function searchSparseOnly(ctx, collection, indices, values, k) {
145
+ const sparseResults = collection.store.sparse_search(
146
+ new Uint32Array(indices),
147
+ new Float32Array(values),
148
+ k
149
+ );
150
+ return sparseResults.map((r) => ({
151
+ id: String(r.doc_id),
152
+ score: r.score,
153
+ payload: collection.payloads.get(ctx.canonicalPayloadKeyFromResultId(r.doc_id))
154
+ }));
155
+ }
156
+ function searchHybridFusion(ctx, collection, queryVector, indices, values, k) {
157
+ const denseResults = collection.store.search(queryVector, k);
158
+ const sparseResults = collection.store.sparse_search(
159
+ new Uint32Array(indices),
160
+ new Float32Array(values),
161
+ k
162
+ );
163
+ const denseForFuse = denseResults.map(
164
+ ([id, score]) => [Number(id), score]
165
+ );
166
+ const sparseForFuse = sparseResults.map(
167
+ (r) => [Number(r.doc_id), r.score]
168
+ );
169
+ const fused = ctx.wasmModule.hybrid_search_fuse(
170
+ denseForFuse,
171
+ sparseForFuse,
172
+ 60,
173
+ k
174
+ );
175
+ return fused.slice(0, k).map((r) => ({
176
+ id: String(r.doc_id),
177
+ score: r.score,
178
+ payload: collection.payloads.get(ctx.canonicalPayloadKeyFromResultId(r.doc_id))
179
+ }));
180
+ }
181
+ function searchWithFilter(ctx, collection, queryVector, k, filter) {
182
+ const results = collection.store.search_with_filter(
183
+ queryVector,
184
+ k,
185
+ filter
186
+ );
187
+ return results.map((r) => ({
188
+ id: String(r.id),
189
+ score: r.score,
190
+ payload: r.payload || collection.payloads.get(ctx.canonicalPayloadKeyFromResultId(r.id))
191
+ }));
192
+ }
193
+ function searchDenseOnly(ctx, collection, queryVector, k) {
194
+ const rawResults = collection.store.search(queryVector, k);
195
+ return rawResults.map(([id, score]) => {
196
+ const result = { id: String(id), score };
197
+ const payload = collection.payloads.get(ctx.canonicalPayloadKeyFromResultId(id));
198
+ if (payload) {
199
+ result.payload = payload;
200
+ }
201
+ return result;
202
+ });
203
+ }
204
+ async function wasmSearch(ctx, collectionName, query3, options) {
205
+ const collection = ctx.getCollection(collectionName);
206
+ if (!collection) {
207
+ throw new NotFoundError(`Collection '${collectionName}'`);
208
+ }
209
+ const queryVector = query3 instanceof Float32Array ? query3 : new Float32Array(query3);
210
+ if (queryVector.length !== collection.config.dimension) {
211
+ throw new VelesDBError(
212
+ `Query dimension mismatch: expected ${collection.config.dimension}, got ${queryVector.length}`,
213
+ "DIMENSION_MISMATCH"
214
+ );
215
+ }
216
+ const k = options?.k ?? 10;
217
+ if (options?.sparseVector) {
218
+ const { indices, values } = ctx.sparseVectorToArrays(options.sparseVector);
219
+ const hasDense = queryVector.length > 0 && collection.config.dimension !== void 0 && collection.config.dimension > 0;
220
+ return hasDense ? searchHybridFusion(ctx, collection, queryVector, indices, values, k) : searchSparseOnly(ctx, collection, indices, values, k);
221
+ }
222
+ if (options?.filter) {
223
+ return searchWithFilter(ctx, collection, queryVector, k, options.filter);
224
+ }
225
+ return searchDenseOnly(ctx, collection, queryVector, k);
226
+ }
227
+ async function wasmSearchBatch(ctx, collectionName, searches) {
228
+ const results = [];
229
+ for (const s of searches) {
230
+ results.push(
231
+ await wasmSearch(ctx, collectionName, s.vector, {
232
+ k: s.k,
233
+ filter: s.filter,
234
+ quality: s.quality
235
+ })
236
+ );
237
+ }
238
+ return results;
239
+ }
240
+ function mapWasmResult(ctx, collection, r) {
241
+ if (Array.isArray(r)) {
242
+ const key2 = ctx.canonicalPayloadKeyFromResultId(r[0]);
243
+ return { id: String(r[0]), score: r[1], payload: collection.payloads.get(key2) };
244
+ }
245
+ const key = ctx.canonicalPayloadKeyFromResultId(r.id);
246
+ return { id: String(r.id), score: r.score, payload: r.payload ?? collection.payloads.get(key) };
247
+ }
248
+ async function wasmTextSearch(ctx, collectionName, query3, options) {
249
+ const collection = ctx.getCollection(collectionName);
250
+ if (!collection) {
251
+ throw new NotFoundError(`Collection '${collectionName}'`);
252
+ }
253
+ const k = options?.k ?? 10;
254
+ const raw = collection.store.text_search(query3, k, void 0);
255
+ return raw.map((r) => mapWasmResult(ctx, collection, r));
256
+ }
257
+ async function wasmHybridSearch(ctx, collectionName, vector, textQuery, options) {
258
+ const collection = ctx.getCollection(collectionName);
259
+ if (!collection) {
260
+ throw new NotFoundError(`Collection '${collectionName}'`);
261
+ }
262
+ const queryVector = vector instanceof Float32Array ? vector : new Float32Array(vector);
263
+ const k = options?.k ?? 10;
264
+ const vectorWeight = options?.vectorWeight ?? 0.5;
265
+ const raw = collection.store.hybrid_search(
266
+ queryVector,
267
+ textQuery,
268
+ k,
269
+ vectorWeight
270
+ );
271
+ return raw.map((r) => {
272
+ const key = ctx.canonicalPayloadKeyFromResultId(r.id);
273
+ return { id: String(r.id), score: r.score, payload: r.payload ?? collection.payloads.get(key) };
274
+ });
275
+ }
276
+ async function wasmMultiQuerySearch(ctx, collectionName, vectors, options) {
277
+ const collection = ctx.getCollection(collectionName);
278
+ if (!collection) {
279
+ throw new NotFoundError(`Collection '${collectionName}'`);
280
+ }
281
+ if (vectors.length === 0) {
282
+ return [];
283
+ }
284
+ const numVectors = vectors.length;
285
+ const dimension = collection.config.dimension ?? 0;
286
+ const flat = new Float32Array(numVectors * dimension);
287
+ vectors.forEach((vector, idx) => {
288
+ const src = vector instanceof Float32Array ? vector : new Float32Array(vector);
289
+ flat.set(src, idx * dimension);
290
+ });
291
+ const strategy = options?.fusion ?? "rrf";
292
+ const raw = collection.store.multi_query_search(
293
+ flat,
294
+ numVectors,
295
+ options?.k ?? 10,
296
+ strategy,
297
+ options?.fusionParams?.k ?? 60
298
+ );
299
+ return raw.map((r) => mapWasmResult(ctx, collection, r));
300
+ }
301
+ async function wasmQuery(ctx, collectionName, _queryString, params, _options) {
302
+ const collection = ctx.getCollection(collectionName);
303
+ if (!collection) {
304
+ throw new NotFoundError(`Collection '${collectionName}'`);
305
+ }
306
+ const paramsVector = params?.q;
307
+ if (!Array.isArray(paramsVector) && !(paramsVector instanceof Float32Array)) {
308
+ throw new VelesDBError(
309
+ "WASM query() expects params.q to contain the query embedding vector.",
310
+ "BAD_REQUEST"
311
+ );
312
+ }
313
+ const requestedK = params?.k;
314
+ const k = typeof requestedK === "number" && Number.isInteger(requestedK) && requestedK > 0 ? requestedK : 10;
315
+ const raw = collection.store.query(
316
+ paramsVector instanceof Float32Array ? paramsVector : new Float32Array(paramsVector),
317
+ k
318
+ );
319
+ return {
320
+ results: raw,
321
+ stats: {
322
+ executionTimeMs: 0,
323
+ strategy: "wasm-query",
324
+ scannedNodes: raw.length
325
+ }
326
+ };
327
+ }
328
+
329
+ // src/errors.ts
330
+ var VelesError = class extends VelesDBError {
331
+ constructor(message, code, cause) {
332
+ super(message, code, cause);
333
+ this.name = "VelesError";
334
+ }
335
+ };
336
+ var CollectionExistsError = class extends VelesError {
337
+ constructor(message) {
338
+ super(message, "VELES-001");
339
+ this.name = "CollectionExistsError";
340
+ }
341
+ };
342
+ var CollectionNotFoundError = class extends VelesError {
343
+ constructor(message) {
344
+ super(message, "VELES-002");
345
+ this.name = "CollectionNotFoundError";
346
+ }
347
+ };
348
+ var PointNotFoundError = class extends VelesError {
349
+ constructor(message) {
350
+ super(message, "VELES-003");
351
+ this.name = "PointNotFoundError";
352
+ }
353
+ };
354
+ var DimensionMismatchError = class extends VelesError {
355
+ constructor(message) {
356
+ super(message, "VELES-004");
357
+ this.name = "DimensionMismatchError";
358
+ }
359
+ };
360
+ var InvalidVectorError = class extends VelesError {
361
+ constructor(message) {
362
+ super(message, "VELES-005");
363
+ this.name = "InvalidVectorError";
364
+ }
365
+ };
366
+ var StorageError = class extends VelesError {
367
+ constructor(message) {
368
+ super(message, "VELES-006");
369
+ this.name = "StorageError";
370
+ }
371
+ };
372
+ var IndexError = class extends VelesError {
373
+ constructor(message) {
374
+ super(message, "VELES-007");
375
+ this.name = "IndexError";
376
+ }
377
+ };
378
+ var IndexCorruptedError = class extends VelesError {
379
+ constructor(message) {
380
+ super(message, "VELES-008");
381
+ this.name = "IndexCorruptedError";
382
+ }
383
+ };
384
+ var ConfigError = class extends VelesError {
385
+ constructor(message) {
386
+ super(message, "VELES-009");
387
+ this.name = "ConfigError";
388
+ }
389
+ };
390
+ var QueryError = class extends VelesError {
391
+ constructor(message) {
392
+ super(message, "VELES-010");
393
+ this.name = "QueryError";
394
+ }
395
+ };
396
+ var IoError = class extends VelesError {
397
+ constructor(message) {
398
+ super(message, "VELES-011");
399
+ this.name = "IoError";
400
+ }
401
+ };
402
+ var SerializationError = class extends VelesError {
403
+ constructor(message) {
404
+ super(message, "VELES-012");
405
+ this.name = "SerializationError";
406
+ }
407
+ };
408
+ var InternalError = class extends VelesError {
409
+ constructor(message) {
410
+ super(message, "VELES-013");
411
+ this.name = "InternalError";
412
+ }
413
+ };
414
+ var VectorNotAllowedError = class extends VelesError {
415
+ constructor(message) {
416
+ super(message, "VELES-014");
417
+ this.name = "VectorNotAllowedError";
418
+ }
419
+ };
420
+ var SearchNotSupportedError = class extends VelesError {
421
+ constructor(message) {
422
+ super(message, "VELES-015");
423
+ this.name = "SearchNotSupportedError";
424
+ }
425
+ };
426
+ var VectorRequiredError = class extends VelesError {
427
+ constructor(message) {
428
+ super(message, "VELES-016");
429
+ this.name = "VectorRequiredError";
430
+ }
431
+ };
432
+ var SchemaValidationError = class extends VelesError {
433
+ constructor(message) {
434
+ super(message, "VELES-017");
435
+ this.name = "SchemaValidationError";
436
+ }
437
+ };
438
+ var GraphNotSupportedError = class extends VelesError {
439
+ constructor(message) {
440
+ super(message, "VELES-018");
441
+ this.name = "GraphNotSupportedError";
442
+ }
443
+ };
444
+ var EdgeExistsError = class extends VelesError {
445
+ constructor(message) {
446
+ super(message, "VELES-019");
447
+ this.name = "EdgeExistsError";
448
+ }
449
+ };
450
+ var EdgeNotFoundError = class extends VelesError {
451
+ constructor(message) {
452
+ super(message, "VELES-020");
453
+ this.name = "EdgeNotFoundError";
454
+ }
455
+ };
456
+ var InvalidEdgeLabelError = class extends VelesError {
457
+ constructor(message) {
458
+ super(message, "VELES-021");
459
+ this.name = "InvalidEdgeLabelError";
460
+ }
461
+ };
462
+ var NodeNotFoundError = class extends VelesError {
463
+ constructor(message) {
464
+ super(message, "VELES-022");
465
+ this.name = "NodeNotFoundError";
466
+ }
467
+ };
468
+ var OverflowError = class extends VelesError {
469
+ constructor(message) {
470
+ super(message, "VELES-023");
471
+ this.name = "OverflowError";
472
+ }
473
+ };
474
+ var ColumnStoreError = class extends VelesError {
475
+ constructor(message) {
476
+ super(message, "VELES-024");
477
+ this.name = "ColumnStoreError";
478
+ }
479
+ };
480
+ var GpuError = class extends VelesError {
481
+ constructor(message) {
482
+ super(message, "VELES-025");
483
+ this.name = "GpuError";
484
+ }
485
+ };
486
+ var EpochMismatchError = class extends VelesError {
487
+ constructor(message) {
488
+ super(message, "VELES-026");
489
+ this.name = "EpochMismatchError";
490
+ }
491
+ };
492
+ var GuardRailError = class extends VelesError {
493
+ constructor(message) {
494
+ super(message, "VELES-027");
495
+ this.name = "GuardRailError";
496
+ }
497
+ };
498
+ var InvalidQuantizerConfigError = class extends VelesError {
499
+ constructor(message) {
500
+ super(message, "VELES-028");
501
+ this.name = "InvalidQuantizerConfigError";
502
+ }
503
+ };
504
+ var TrainingFailedError = class extends VelesError {
505
+ constructor(message) {
506
+ super(message, "VELES-029");
507
+ this.name = "TrainingFailedError";
508
+ }
509
+ };
510
+ var SparseIndexError = class extends VelesError {
511
+ constructor(message) {
512
+ super(message, "VELES-030");
513
+ this.name = "SparseIndexError";
514
+ }
515
+ };
516
+ var DatabaseLockedError = class extends VelesError {
517
+ constructor(message) {
518
+ super(message, "VELES-031");
519
+ this.name = "DatabaseLockedError";
520
+ }
521
+ };
522
+ var InvalidDimensionError = class extends VelesError {
523
+ constructor(message) {
524
+ super(message, "VELES-032");
525
+ this.name = "InvalidDimensionError";
526
+ }
527
+ };
528
+ var AllocationFailedError = class extends VelesError {
529
+ constructor(message) {
530
+ super(message, "VELES-033");
531
+ this.name = "AllocationFailedError";
532
+ }
533
+ };
534
+ var InvalidCollectionNameError = class extends VelesError {
535
+ constructor(message) {
536
+ super(message, "VELES-034");
537
+ this.name = "InvalidCollectionNameError";
538
+ }
539
+ };
540
+ var SnapshotBuildFailedError = class extends VelesError {
541
+ constructor(message) {
542
+ super(message, "VELES-035");
543
+ this.name = "SnapshotBuildFailedError";
544
+ }
545
+ };
546
+ var IncompatibleSchemaVersionError = class extends VelesError {
547
+ constructor(message) {
548
+ super(message, "VELES-036");
549
+ this.name = "IncompatibleSchemaVersionError";
550
+ }
551
+ };
552
+ var VELES_ERROR_CODES = [
553
+ "VELES-001",
554
+ "VELES-002",
555
+ "VELES-003",
556
+ "VELES-004",
557
+ "VELES-005",
558
+ "VELES-006",
559
+ "VELES-007",
560
+ "VELES-008",
561
+ "VELES-009",
562
+ "VELES-010",
563
+ "VELES-011",
564
+ "VELES-012",
565
+ "VELES-013",
566
+ "VELES-014",
567
+ "VELES-015",
568
+ "VELES-016",
569
+ "VELES-017",
570
+ "VELES-018",
571
+ "VELES-019",
572
+ "VELES-020",
573
+ "VELES-021",
574
+ "VELES-022",
575
+ "VELES-023",
576
+ "VELES-024",
577
+ "VELES-025",
578
+ "VELES-026",
579
+ "VELES-027",
580
+ "VELES-028",
581
+ "VELES-029",
582
+ "VELES-030",
583
+ "VELES-031",
584
+ "VELES-032",
585
+ "VELES-033",
586
+ "VELES-034",
587
+ "VELES-035",
588
+ "VELES-036"
589
+ ];
590
+ var CODE_TO_CLASS = {
591
+ "VELES-001": CollectionExistsError,
592
+ "VELES-002": CollectionNotFoundError,
593
+ "VELES-003": PointNotFoundError,
594
+ "VELES-004": DimensionMismatchError,
595
+ "VELES-005": InvalidVectorError,
596
+ "VELES-006": StorageError,
597
+ "VELES-007": IndexError,
598
+ "VELES-008": IndexCorruptedError,
599
+ "VELES-009": ConfigError,
600
+ "VELES-010": QueryError,
601
+ "VELES-011": IoError,
602
+ "VELES-012": SerializationError,
603
+ "VELES-013": InternalError,
604
+ "VELES-014": VectorNotAllowedError,
605
+ "VELES-015": SearchNotSupportedError,
606
+ "VELES-016": VectorRequiredError,
607
+ "VELES-017": SchemaValidationError,
608
+ "VELES-018": GraphNotSupportedError,
609
+ "VELES-019": EdgeExistsError,
610
+ "VELES-020": EdgeNotFoundError,
611
+ "VELES-021": InvalidEdgeLabelError,
612
+ "VELES-022": NodeNotFoundError,
613
+ "VELES-023": OverflowError,
614
+ "VELES-024": ColumnStoreError,
615
+ "VELES-025": GpuError,
616
+ "VELES-026": EpochMismatchError,
617
+ "VELES-027": GuardRailError,
618
+ "VELES-028": InvalidQuantizerConfigError,
619
+ "VELES-029": TrainingFailedError,
620
+ "VELES-030": SparseIndexError,
621
+ "VELES-031": DatabaseLockedError,
622
+ "VELES-032": InvalidDimensionError,
623
+ "VELES-033": AllocationFailedError,
624
+ "VELES-034": InvalidCollectionNameError,
625
+ "VELES-035": SnapshotBuildFailedError,
626
+ "VELES-036": IncompatibleSchemaVersionError
627
+ };
628
+ function parseVelesError(code, message) {
629
+ if (code === null || code === void 0) {
630
+ return new VelesError(message, "VELES-UNKNOWN");
631
+ }
632
+ const Cls = CODE_TO_CLASS[code];
633
+ if (Cls !== void 0) {
634
+ return new Cls(message);
635
+ }
636
+ return new VelesError(message, code);
637
+ }
638
+
35
639
  // src/backends/shared.ts
36
640
  function throwOnError(response, resourceLabel) {
37
641
  if (!response.error) {
@@ -40,20 +644,87 @@ function throwOnError(response, resourceLabel) {
40
644
  if (response.error.code === "NOT_FOUND" && resourceLabel !== void 0) {
41
645
  throw new NotFoundError(resourceLabel);
42
646
  }
43
- throw new VelesDBError(response.error.message, response.error.code);
647
+ throw parseVelesError(response.error.code, response.error.message);
44
648
  }
45
649
  function returnNullOnNotFound(response) {
46
650
  if (!response.error) {
47
651
  return void 0;
48
652
  }
49
- if (response.error.code === "NOT_FOUND") {
653
+ if (isNotFoundError(response.error.code)) {
654
+ return true;
655
+ }
656
+ throw parseVelesError(response.error.code, response.error.message);
657
+ }
658
+ function isNotFoundError(code) {
659
+ if (code === void 0) {
660
+ return false;
661
+ }
662
+ if (code === "NOT_FOUND") {
50
663
  return true;
51
664
  }
52
- throw new VelesDBError(response.error.message, response.error.code);
665
+ const err = parseVelesError(code, "");
666
+ return err instanceof CollectionNotFoundError || err instanceof PointNotFoundError || err instanceof EdgeNotFoundError || err instanceof NodeNotFoundError;
53
667
  }
54
668
  function collectionPath(collection) {
55
669
  return `/collections/${encodeURIComponent(collection)}`;
56
670
  }
671
+ var MAX_COLLECTION_NAME_LENGTH = 128;
672
+ var WINDOWS_RESERVED_NAMES = /* @__PURE__ */ new Set([
673
+ "CON",
674
+ "PRN",
675
+ "AUX",
676
+ "NUL",
677
+ "COM1",
678
+ "COM2",
679
+ "COM3",
680
+ "COM4",
681
+ "COM5",
682
+ "COM6",
683
+ "COM7",
684
+ "COM8",
685
+ "COM9",
686
+ "LPT1",
687
+ "LPT2",
688
+ "LPT3",
689
+ "LPT4",
690
+ "LPT5",
691
+ "LPT6",
692
+ "LPT7",
693
+ "LPT8",
694
+ "LPT9"
695
+ ]);
696
+ function validateCollectionName(name) {
697
+ if (typeof name !== "string" || name.length === 0) {
698
+ throw new InvalidCollectionNameError(
699
+ "Collection name must be a non-empty string"
700
+ );
701
+ }
702
+ if (name.length > MAX_COLLECTION_NAME_LENGTH) {
703
+ throw new InvalidCollectionNameError(
704
+ `Collection name '${name}' exceeds maximum length of ${MAX_COLLECTION_NAME_LENGTH} characters`
705
+ );
706
+ }
707
+ if (name === "." || name === "..") {
708
+ throw new InvalidCollectionNameError(
709
+ `Collection name '${name}' is not allowed (path traversal)`
710
+ );
711
+ }
712
+ if (name.startsWith("-")) {
713
+ throw new InvalidCollectionNameError(
714
+ `Collection name '${name}' must not start with a hyphen`
715
+ );
716
+ }
717
+ if (!/^[A-Za-z0-9_-]+$/.test(name)) {
718
+ throw new InvalidCollectionNameError(
719
+ `Collection name '${name}' contains forbidden characters; only ASCII letters, digits, underscores, and hyphens are allowed`
720
+ );
721
+ }
722
+ if (WINDOWS_RESERVED_NAMES.has(name.toUpperCase())) {
723
+ throw new InvalidCollectionNameError(
724
+ `Collection name '${name}' is a Windows reserved device name`
725
+ );
726
+ }
727
+ }
57
728
  function toNumberArray(v) {
58
729
  return v instanceof Float32Array ? Array.from(v) : v;
59
730
  }
@@ -64,6 +735,127 @@ function wasmNotSupported(feature) {
64
735
  );
65
736
  }
66
737
 
738
+ // src/backends/wasm-stubs.ts
739
+ async function wasmCreateIndex(_collection, _options) {
740
+ wasmNotSupported("Index management (createIndex)");
741
+ }
742
+ async function wasmListIndexes(_collection) {
743
+ wasmNotSupported("Index management (listIndexes)");
744
+ }
745
+ async function wasmHasIndex(_collection, _label, _property) {
746
+ wasmNotSupported("Index management (hasIndex)");
747
+ }
748
+ async function wasmDropIndex(_collection, _label, _property) {
749
+ wasmNotSupported("Index management (dropIndex)");
750
+ }
751
+ async function wasmAddEdge(_collection, _edge) {
752
+ wasmNotSupported("Knowledge Graph operations");
753
+ }
754
+ async function wasmGetEdges(_collection, _options) {
755
+ wasmNotSupported("Knowledge Graph operations");
756
+ }
757
+ async function wasmTraverseGraph(_collection, _request) {
758
+ wasmNotSupported("Graph traversal");
759
+ }
760
+ async function wasmTraverseParallel(_collection, _request) {
761
+ wasmNotSupported("Graph parallel traversal");
762
+ }
763
+ async function wasmGetNodeDegree(_collection, _nodeId) {
764
+ wasmNotSupported("Graph degree query");
765
+ }
766
+ async function wasmQueryExplain(_queryString, _params, _options) {
767
+ if (_options?.analyze) {
768
+ wasmNotSupported("EXPLAIN ANALYZE");
769
+ }
770
+ wasmNotSupported("Query explain");
771
+ }
772
+ async function wasmCollectionSanity(_collection) {
773
+ wasmNotSupported("Collection sanity endpoint");
774
+ }
775
+ async function wasmScroll(_collection, _request) {
776
+ wasmNotSupported("scroll");
777
+ }
778
+ async function wasmTrainPq(_collection, _options) {
779
+ wasmNotSupported("PQ training");
780
+ }
781
+ async function wasmStreamInsert(_collection, _docs) {
782
+ wasmNotSupported("Streaming insert");
783
+ }
784
+ async function wasmStreamUpsertPoints(_collection, _docs) {
785
+ wasmNotSupported("Streaming batch upsert");
786
+ }
787
+ async function wasmCreateGraphCollection(_name, _config) {
788
+ wasmNotSupported("Graph collections");
789
+ }
790
+ async function wasmGetCollectionStats(_collection) {
791
+ wasmNotSupported("Collection stats");
792
+ }
793
+ async function wasmAnalyzeCollection(_collection) {
794
+ wasmNotSupported("Collection analyze");
795
+ }
796
+ async function wasmGetCollectionConfig(_collection) {
797
+ wasmNotSupported("Collection config");
798
+ }
799
+ async function wasmSearchIds(_collection, _query, _options) {
800
+ wasmNotSupported("searchIds");
801
+ }
802
+ async function wasmStoreSemanticFact(_collection, _entry) {
803
+ wasmNotSupported("Agent memory");
804
+ }
805
+ async function wasmSearchSemanticMemory(_collection, _embedding, _k) {
806
+ wasmNotSupported("Agent memory");
807
+ }
808
+ async function wasmRecordEpisodicEvent(_collection, _event) {
809
+ wasmNotSupported("Agent memory");
810
+ }
811
+ async function wasmRecallEpisodicEvents(_collection, _embedding, _k) {
812
+ wasmNotSupported("Agent memory");
813
+ }
814
+ async function wasmStoreProceduralPattern(_collection, _pattern) {
815
+ wasmNotSupported("Agent memory");
816
+ }
817
+ async function wasmMatchProceduralPatterns(_collection, _embedding, _k) {
818
+ wasmNotSupported("Agent memory");
819
+ }
820
+
821
+ // src/backends/wasm-wave4-stubs.ts
822
+ function wasmRebuildIndex(_c) {
823
+ return Promise.resolve(wasmNotSupported("Index rebuild"));
824
+ }
825
+ function wasmGetGuardrails() {
826
+ return Promise.resolve(wasmNotSupported("Guardrails"));
827
+ }
828
+ function wasmUpdateGuardrails(_r) {
829
+ return Promise.resolve(wasmNotSupported("Guardrails"));
830
+ }
831
+ function wasmAggregate(_q, _p, _o) {
832
+ return Promise.resolve(wasmNotSupported("Aggregate queries"));
833
+ }
834
+ function wasmMatchQuery(_c, _q, _p, _o) {
835
+ return Promise.resolve(wasmNotSupported("MATCH queries"));
836
+ }
837
+ function wasmRemoveEdge(_c, _id) {
838
+ return Promise.resolve(wasmNotSupported("Graph edge removal"));
839
+ }
840
+ function wasmGetEdgeCount(_c) {
841
+ return Promise.resolve(wasmNotSupported("Graph edge count"));
842
+ }
843
+ function wasmListNodes(_c) {
844
+ return Promise.resolve(wasmNotSupported("Graph list nodes"));
845
+ }
846
+ function wasmGetNodeEdges(_c, _id, _o) {
847
+ return Promise.resolve(wasmNotSupported("Graph node edges"));
848
+ }
849
+ function wasmGetNodePayload(_c, _id) {
850
+ return Promise.resolve(wasmNotSupported("Graph node payload (read)"));
851
+ }
852
+ function wasmUpsertNodePayload(_c, _id, _p) {
853
+ return Promise.resolve(wasmNotSupported("Graph node payload (upsert)"));
854
+ }
855
+ function wasmGraphSearch(_c, _r) {
856
+ return Promise.resolve(wasmNotSupported("Graph search"));
857
+ }
858
+
67
859
  // src/backends/wasm.ts
68
860
  var WasmBackend = class {
69
861
  constructor() {
@@ -71,6 +863,9 @@ var WasmBackend = class {
71
863
  this.collections = /* @__PURE__ */ new Map();
72
864
  this._initialized = false;
73
865
  }
866
+ // ========================================================================
867
+ // Lifecycle
868
+ // ========================================================================
74
869
  async init() {
75
870
  if (this._initialized) {
76
871
  return;
@@ -89,45 +884,32 @@ var WasmBackend = class {
89
884
  isInitialized() {
90
885
  return this._initialized;
91
886
  }
887
+ async close() {
888
+ for (const [, data] of this.collections) {
889
+ data.store.free();
890
+ }
891
+ this.collections.clear();
892
+ this._initialized = false;
893
+ }
894
+ capabilities() {
895
+ return WASM_CAPABILITIES;
896
+ }
92
897
  ensureInitialized() {
93
898
  if (!this._initialized || !this.wasmModule) {
94
899
  throw new ConnectionError("WASM backend not initialized");
95
900
  }
96
901
  }
97
- normalizeIdString(id) {
98
- const trimmed = id.trim();
99
- return /^\d+$/.test(trimmed) ? trimmed : null;
100
- }
101
- canonicalPayloadKeyFromResultId(id) {
102
- if (typeof id === "bigint") {
103
- return id.toString();
104
- }
105
- if (typeof id === "number") {
106
- return String(Math.trunc(id));
107
- }
108
- const normalized = this.normalizeIdString(id);
109
- if (normalized !== null) {
110
- return normalized.replace(/^0+(?=\d)/, "");
111
- }
112
- return String(this.toNumericId(id));
113
- }
114
- canonicalPayloadKey(id) {
115
- if (typeof id === "number") {
116
- return String(Math.trunc(id));
117
- }
118
- const normalized = this.normalizeIdString(id);
119
- if (normalized !== null) {
120
- return normalized.replace(/^0+(?=\d)/, "");
121
- }
122
- return String(this.toNumericId(id));
123
- }
902
+ // ========================================================================
903
+ // Collection management
904
+ // ========================================================================
124
905
  async createCollection(name, config) {
125
906
  this.ensureInitialized();
126
907
  if (this.collections.has(name)) {
127
908
  throw new VelesDBError(`Collection '${name}' already exists`, "COLLECTION_EXISTS");
128
909
  }
910
+ const dimension = config.dimension ?? 0;
129
911
  const metric = config.metric ?? "cosine";
130
- const store = new this.wasmModule.VectorStore(config.dimension, metric);
912
+ const store = new this.wasmModule.VectorStore(dimension, metric);
131
913
  this.collections.set(name, {
132
914
  config: { ...config, metric },
133
915
  store,
@@ -146,39 +928,27 @@ var WasmBackend = class {
146
928
  }
147
929
  async getCollection(name) {
148
930
  this.ensureInitialized();
149
- const collection = this.collections.get(name);
150
- if (!collection) {
151
- return null;
152
- }
153
- return {
154
- name,
155
- dimension: collection.config.dimension ?? 0,
156
- metric: collection.config.metric ?? "cosine",
157
- count: collection.store.len,
158
- createdAt: collection.createdAt
159
- };
931
+ const data = this.collections.get(name);
932
+ return data ? buildCollectionInfo(name, data) : null;
160
933
  }
161
934
  async listCollections() {
162
935
  this.ensureInitialized();
163
936
  const result = [];
164
937
  for (const [name, data] of this.collections) {
165
- result.push({
166
- name,
167
- dimension: data.config.dimension ?? 0,
168
- metric: data.config.metric ?? "cosine",
169
- count: data.store.len,
170
- createdAt: data.createdAt
171
- });
938
+ result.push(buildCollectionInfo(name, data));
172
939
  }
173
940
  return result;
174
941
  }
175
- async insert(collectionName, doc) {
942
+ // ========================================================================
943
+ // Point CRUD
944
+ // ========================================================================
945
+ async upsert(collectionName, doc) {
176
946
  this.ensureInitialized();
177
947
  const collection = this.collections.get(collectionName);
178
948
  if (!collection) {
179
949
  throw new NotFoundError(`Collection '${collectionName}'`);
180
950
  }
181
- const id = this.toNumericId(doc.id);
951
+ const id = toNumericId(doc.id);
182
952
  const vector = doc.vector instanceof Float32Array ? doc.vector : new Float32Array(doc.vector);
183
953
  if (vector.length !== collection.config.dimension) {
184
954
  throw new VelesDBError(
@@ -192,20 +962,19 @@ var WasmBackend = class {
192
962
  collection.store.insert(BigInt(id), vector);
193
963
  }
194
964
  if (doc.payload) {
195
- collection.payloads.set(this.canonicalPayloadKey(doc.id), doc.payload);
965
+ collection.payloads.set(canonicalPayloadKey(doc.id), doc.payload);
196
966
  }
197
967
  }
198
- async insertBatch(collectionName, docs) {
968
+ async upsertBatch(collectionName, docs) {
199
969
  this.ensureInitialized();
200
970
  const collection = this.collections.get(collectionName);
201
971
  if (!collection) {
202
972
  throw new NotFoundError(`Collection '${collectionName}'`);
203
973
  }
204
974
  for (const doc of docs) {
205
- const vectorLen = doc.vector.length;
206
- if (vectorLen !== collection.config.dimension) {
975
+ if (doc.vector.length !== collection.config.dimension) {
207
976
  throw new VelesDBError(
208
- `Vector dimension mismatch for doc ${doc.id}: expected ${collection.config.dimension}, got ${vectorLen}`,
977
+ `Vector dimension mismatch for doc ${doc.id}: expected ${collection.config.dimension}, got ${doc.vector.length}`,
209
978
  "DIMENSION_MISMATCH"
210
979
  );
211
980
  }
@@ -213,7 +982,7 @@ var WasmBackend = class {
213
982
  collection.store.reserve(docs.length);
214
983
  const batch = [];
215
984
  for (const doc of docs) {
216
- const id = BigInt(this.toNumericId(doc.id));
985
+ const id = BigInt(toNumericId(doc.id));
217
986
  const vector = doc.vector instanceof Float32Array ? doc.vector : new Float32Array(doc.vector);
218
987
  if (doc.payload) {
219
988
  collection.store.insert_with_payload(id, vector, doc.payload);
@@ -226,95 +995,20 @@ var WasmBackend = class {
226
995
  }
227
996
  for (const doc of docs) {
228
997
  if (doc.payload) {
229
- collection.payloads.set(this.canonicalPayloadKey(doc.id), doc.payload);
998
+ collection.payloads.set(canonicalPayloadKey(doc.id), doc.payload);
230
999
  }
231
1000
  }
232
1001
  }
233
- async search(collectionName, query2, options) {
234
- this.ensureInitialized();
235
- const collection = this.collections.get(collectionName);
236
- if (!collection) {
237
- throw new NotFoundError(`Collection '${collectionName}'`);
238
- }
239
- const queryVector = query2 instanceof Float32Array ? query2 : new Float32Array(query2);
240
- if (queryVector.length !== collection.config.dimension) {
241
- throw new VelesDBError(
242
- `Query dimension mismatch: expected ${collection.config.dimension}, got ${queryVector.length}`,
243
- "DIMENSION_MISMATCH"
244
- );
245
- }
246
- const k = options?.k ?? 10;
247
- if (options?.sparseVector) {
248
- const { indices, values } = this.sparseVectorToArrays(options.sparseVector);
249
- if (queryVector.length > 0 && collection.config.dimension && collection.config.dimension > 0) {
250
- const denseResults = collection.store.search(queryVector, k);
251
- const sparseResults = collection.store.sparse_search(
252
- new Uint32Array(indices),
253
- new Float32Array(values),
254
- k
255
- );
256
- const sparseArray = sparseResults;
257
- const denseForFuse = denseResults.map(([id, score]) => [Number(id), score]);
258
- const sparseForFuse = sparseArray.map((r) => [Number(r.doc_id), r.score]);
259
- const fused = this.wasmModule.hybrid_search_fuse(denseForFuse, sparseForFuse, 60);
260
- return fused.slice(0, k).map((r) => ({
261
- id: String(r.doc_id),
262
- score: r.score,
263
- payload: collection.payloads.get(this.canonicalPayloadKeyFromResultId(r.doc_id))
264
- }));
265
- } else {
266
- const sparseResults = collection.store.sparse_search(
267
- new Uint32Array(indices),
268
- new Float32Array(values),
269
- k
270
- );
271
- return sparseResults.map((r) => ({
272
- id: String(r.doc_id),
273
- score: r.score,
274
- payload: collection.payloads.get(this.canonicalPayloadKeyFromResultId(r.doc_id))
275
- }));
276
- }
277
- }
278
- if (options?.filter) {
279
- const results = collection.store.search_with_filter(queryVector, k, options.filter);
280
- return results.map((r) => ({
281
- id: String(r.id),
282
- score: r.score,
283
- payload: r.payload || collection.payloads.get(this.canonicalPayloadKeyFromResultId(r.id))
284
- }));
285
- }
286
- const rawResults = collection.store.search(queryVector, k);
287
- return rawResults.map(([id, score]) => {
288
- const stringId = String(id);
289
- const result = {
290
- id: stringId,
291
- score
292
- };
293
- const payload = collection.payloads.get(this.canonicalPayloadKeyFromResultId(id));
294
- if (payload) {
295
- result.payload = payload;
296
- }
297
- return result;
298
- });
299
- }
300
- async searchBatch(collectionName, searches) {
301
- this.ensureInitialized();
302
- const results = [];
303
- for (const s of searches) {
304
- results.push(await this.search(collectionName, s.vector, { k: s.k, filter: s.filter }));
305
- }
306
- return results;
307
- }
308
1002
  async delete(collectionName, id) {
309
1003
  this.ensureInitialized();
310
1004
  const collection = this.collections.get(collectionName);
311
1005
  if (!collection) {
312
1006
  throw new NotFoundError(`Collection '${collectionName}'`);
313
1007
  }
314
- const numericId = this.toNumericId(id);
1008
+ const numericId = toNumericId(id);
315
1009
  const removed = collection.store.remove(BigInt(numericId));
316
1010
  if (removed) {
317
- collection.payloads.delete(this.canonicalPayloadKey(id));
1011
+ collection.payloads.delete(canonicalPayloadKey(id));
318
1012
  }
319
1013
  return removed;
320
1014
  }
@@ -324,287 +1018,691 @@ var WasmBackend = class {
324
1018
  if (!collection) {
325
1019
  throw new NotFoundError(`Collection '${collectionName}'`);
326
1020
  }
327
- const numericId = this.toNumericId(id);
1021
+ const numericId = toNumericId(id);
328
1022
  const point = collection.store.get(BigInt(numericId));
329
1023
  if (!point) {
330
1024
  return null;
331
1025
  }
332
- const payload = point.payload ?? collection.payloads.get(this.canonicalPayloadKey(numericId));
1026
+ const payload = point.payload ?? collection.payloads.get(canonicalPayloadKey(numericId));
333
1027
  return {
334
1028
  id: String(point.id),
335
1029
  vector: Array.isArray(point.vector) ? point.vector : Array.from(point.vector),
336
1030
  payload
337
1031
  };
338
1032
  }
339
- async textSearch(_collection, _query, _options) {
1033
+ // ========================================================================
1034
+ // Collection utilities
1035
+ // ========================================================================
1036
+ async isEmpty(collectionName) {
340
1037
  this.ensureInitialized();
341
- const collection = this.collections.get(_collection);
1038
+ const collection = this.collections.get(collectionName);
342
1039
  if (!collection) {
343
- throw new NotFoundError(`Collection '${_collection}'`);
344
- }
345
- const k = _options?.k ?? 10;
346
- const field = void 0;
347
- const raw = collection.store.text_search(_query, k, field);
348
- return raw.map((r) => {
349
- if (Array.isArray(r)) {
350
- const key2 = this.canonicalPayloadKeyFromResultId(r[0]);
351
- return { id: String(r[0]), score: r[1], payload: collection.payloads.get(key2) };
352
- }
353
- const key = this.canonicalPayloadKeyFromResultId(r.id);
354
- return { id: String(r.id), score: r.score, payload: r.payload ?? collection.payloads.get(key) };
355
- });
1040
+ throw new NotFoundError(`Collection '${collectionName}'`);
1041
+ }
1042
+ return collection.store.is_empty;
356
1043
  }
357
- async hybridSearch(_collection, _vector, _textQuery, _options) {
1044
+ async flush(collectionName) {
358
1045
  this.ensureInitialized();
359
- const collection = this.collections.get(_collection);
1046
+ const collection = this.collections.get(collectionName);
360
1047
  if (!collection) {
361
- throw new NotFoundError(`Collection '${_collection}'`);
362
- }
363
- const queryVector = _vector instanceof Float32Array ? _vector : new Float32Array(_vector);
364
- const k = _options?.k ?? 10;
365
- const vectorWeight = _options?.vectorWeight ?? 0.5;
366
- const raw = collection.store.hybrid_search(queryVector, _textQuery, k, vectorWeight);
367
- return raw.map((r) => {
368
- const key = this.canonicalPayloadKeyFromResultId(r.id);
369
- return {
370
- id: String(r.id),
371
- score: r.score,
372
- payload: r.payload ?? collection.payloads.get(key)
373
- };
374
- });
1048
+ throw new NotFoundError(`Collection '${collectionName}'`);
1049
+ }
375
1050
  }
376
- async query(_collection, _queryString, _params, _options) {
1051
+ // ========================================================================
1052
+ // Search & Query -- delegates to wasm-search.ts
1053
+ // ========================================================================
1054
+ async search(c, q, o) {
377
1055
  this.ensureInitialized();
378
- const collection = this.collections.get(_collection);
379
- if (!collection) {
380
- throw new NotFoundError(`Collection '${_collection}'`);
381
- }
382
- const paramsVector = _params?.q;
383
- if (!Array.isArray(paramsVector) && !(paramsVector instanceof Float32Array)) {
384
- throw new VelesDBError(
385
- "WASM query() expects params.q to contain the query embedding vector.",
386
- "BAD_REQUEST"
387
- );
388
- }
389
- const requestedK = _params?.k;
390
- const k = typeof requestedK === "number" && Number.isInteger(requestedK) && requestedK > 0 ? requestedK : 10;
391
- const raw = collection.store.query(
392
- paramsVector instanceof Float32Array ? paramsVector : new Float32Array(paramsVector),
393
- k
394
- );
395
- return {
396
- results: raw,
397
- stats: {
398
- executionTimeMs: 0,
399
- strategy: "wasm-query",
400
- scannedNodes: raw.length
401
- }
402
- };
1056
+ return wasmSearch(buildWasmContext(this.wasmModule, this.collections), c, q, o);
403
1057
  }
404
- async multiQuerySearch(_collection, _vectors, _options) {
1058
+ async searchBatch(c, s) {
405
1059
  this.ensureInitialized();
406
- const collection = this.collections.get(_collection);
407
- if (!collection) {
408
- throw new NotFoundError(`Collection '${_collection}'`);
409
- }
410
- if (_vectors.length === 0) {
411
- return [];
412
- }
413
- const numVectors = _vectors.length;
414
- const dimension = collection.config.dimension ?? 0;
415
- const flat = new Float32Array(numVectors * dimension);
416
- _vectors.forEach((vector, idx) => {
417
- const src = vector instanceof Float32Array ? vector : new Float32Array(vector);
418
- flat.set(src, idx * dimension);
419
- });
420
- const strategy = _options?.fusion ?? "rrf";
421
- if (strategy === "weighted") {
422
- throw new VelesDBError(
423
- "Fusion strategy 'weighted' is not supported in WASM backend.",
424
- "NOT_SUPPORTED"
425
- );
426
- }
427
- const raw = collection.store.multi_query_search(
428
- flat,
429
- numVectors,
430
- _options?.k ?? 10,
431
- strategy,
432
- _options?.fusionParams?.k ?? 60
433
- );
434
- return raw.map((r) => {
435
- if (Array.isArray(r)) {
436
- const key2 = this.canonicalPayloadKeyFromResultId(r[0]);
437
- return { id: String(r[0]), score: r[1], payload: collection.payloads.get(key2) };
438
- }
439
- const key = this.canonicalPayloadKeyFromResultId(r.id);
440
- return { id: String(r.id), score: r.score, payload: r.payload ?? collection.payloads.get(key) };
441
- });
1060
+ return wasmSearchBatch(buildWasmContext(this.wasmModule, this.collections), c, s);
442
1061
  }
443
- async queryExplain(_queryString, _params) {
1062
+ async textSearch(c, q, o) {
444
1063
  this.ensureInitialized();
445
- wasmNotSupported("Query explain");
1064
+ return wasmTextSearch(buildWasmContext(this.wasmModule, this.collections), c, q, o);
446
1065
  }
447
- async collectionSanity(_collection) {
1066
+ async hybridSearch(c, v, t, o) {
448
1067
  this.ensureInitialized();
449
- wasmNotSupported("Collection sanity endpoint");
1068
+ return wasmHybridSearch(buildWasmContext(this.wasmModule, this.collections), c, v, t, o);
450
1069
  }
451
- async isEmpty(collectionName) {
1070
+ async query(c, q, p, o) {
452
1071
  this.ensureInitialized();
453
- const collection = this.collections.get(collectionName);
454
- if (!collection) {
455
- throw new NotFoundError(`Collection '${collectionName}'`);
456
- }
457
- return collection.store.is_empty();
1072
+ return wasmQuery(buildWasmContext(this.wasmModule, this.collections), c, q, p, o);
458
1073
  }
459
- async flush(collectionName) {
1074
+ async multiQuerySearch(c, v, o) {
460
1075
  this.ensureInitialized();
461
- const collection = this.collections.get(collectionName);
462
- if (!collection) {
463
- throw new NotFoundError(`Collection '${collectionName}'`);
464
- }
1076
+ return wasmMultiQuerySearch(buildWasmContext(this.wasmModule, this.collections), c, v, o);
465
1077
  }
466
- async close() {
467
- for (const [, data] of this.collections) {
468
- data.store.free();
469
- }
470
- this.collections.clear();
471
- this._initialized = false;
1078
+ // ========================================================================
1079
+ // Stubs -- delegates to wasm-stubs.ts & wasm-wave4-stubs.ts
1080
+ // ========================================================================
1081
+ async queryExplain(q, p, o) {
1082
+ this.ensureInitialized();
1083
+ return wasmQueryExplain(q, p, o);
472
1084
  }
473
- sparseVectorToArrays(sv) {
474
- const indices = [];
475
- const values = [];
476
- for (const [k, v] of Object.entries(sv)) {
477
- indices.push(Number(k));
478
- values.push(v);
479
- }
480
- return { indices, values };
1085
+ async collectionSanity(c) {
1086
+ this.ensureInitialized();
1087
+ return wasmCollectionSanity(c);
481
1088
  }
482
- toNumericId(id) {
483
- if (typeof id === "number") {
484
- return id;
485
- }
486
- const normalized = this.normalizeIdString(id);
487
- if (normalized !== null) {
488
- const parsed = Number(normalized);
489
- if (Number.isSafeInteger(parsed)) {
490
- return parsed;
491
- }
492
- }
493
- let hash = 0;
494
- for (let i = 0; i < id.length; i++) {
495
- const char = id.charCodeAt(i);
496
- hash = (hash << 5) - hash + char;
497
- hash = hash & hash;
498
- }
499
- return Math.abs(hash);
1089
+ async scroll(c, r) {
1090
+ this.ensureInitialized();
1091
+ return wasmScroll(c, r);
500
1092
  }
501
- // ========================================================================
502
- // Index Management (EPIC-009) - Stubs for WASM backend
503
- // Note: Full implementation requires velesdb-wasm support
504
- // ========================================================================
505
- async createIndex(_collection, _options) {
1093
+ async createIndex(c, o) {
506
1094
  this.ensureInitialized();
507
- throw new Error(
508
- "WasmBackend: createIndex is not yet supported. Index operations require the REST backend with velesdb-server."
509
- );
1095
+ return wasmCreateIndex(c, o);
510
1096
  }
511
- async listIndexes(_collection) {
1097
+ async listIndexes(c) {
512
1098
  this.ensureInitialized();
513
- return [];
1099
+ return wasmListIndexes(c);
514
1100
  }
515
- async hasIndex(_collection, _label, _property) {
1101
+ async hasIndex(c, l, p) {
516
1102
  this.ensureInitialized();
517
- return false;
1103
+ return wasmHasIndex(c, l, p);
518
1104
  }
519
- async dropIndex(_collection, _label, _property) {
1105
+ async dropIndex(c, l, p) {
520
1106
  this.ensureInitialized();
521
- return false;
1107
+ return wasmDropIndex(c, l, p);
522
1108
  }
523
- // ========================================================================
524
- // Knowledge Graph (EPIC-016 US-041) - Stubs for WASM backend
525
- // Note: Graph operations require server-side EdgeStore
526
- // ========================================================================
527
- async addEdge(_collection, _edge) {
1109
+ async addEdge(c, e) {
528
1110
  this.ensureInitialized();
529
- wasmNotSupported("Knowledge Graph operations");
1111
+ return wasmAddEdge(c, e);
530
1112
  }
531
- async getEdges(_collection, _options) {
1113
+ async getEdges(c, o) {
532
1114
  this.ensureInitialized();
533
- wasmNotSupported("Knowledge Graph operations");
1115
+ return wasmGetEdges(c, o);
534
1116
  }
535
- async traverseGraph(_collection, _request) {
1117
+ async traverseGraph(c, r) {
536
1118
  this.ensureInitialized();
537
- wasmNotSupported("Graph traversal");
1119
+ return wasmTraverseGraph(c, r);
538
1120
  }
539
- async getNodeDegree(_collection, _nodeId) {
1121
+ async traverseParallel(c, r) {
540
1122
  this.ensureInitialized();
541
- wasmNotSupported("Graph degree query");
1123
+ return wasmTraverseParallel(c, r);
542
1124
  }
543
- // ========================================================================
544
- // Sparse / PQ / Streaming (v1.5)
545
- // ========================================================================
546
- async trainPq(_collection, _options) {
1125
+ async getNodeDegree(c, n) {
547
1126
  this.ensureInitialized();
548
- wasmNotSupported("PQ training");
1127
+ return wasmGetNodeDegree(c, n);
549
1128
  }
550
- async streamInsert(_collection, _docs) {
1129
+ async trainPq(c, o) {
551
1130
  this.ensureInitialized();
552
- wasmNotSupported("Streaming insert");
1131
+ return wasmTrainPq(c, o);
553
1132
  }
554
- // ========================================================================
555
- // Graph Collection / Stats / Agent Memory (Phase 8) - WASM stubs
556
- // ========================================================================
557
- async createGraphCollection(_name, _config) {
1133
+ async streamInsert(c, d) {
1134
+ this.ensureInitialized();
1135
+ return wasmStreamInsert(c, d);
1136
+ }
1137
+ async streamUpsertPoints(c, d) {
1138
+ this.ensureInitialized();
1139
+ return wasmStreamUpsertPoints(c, d);
1140
+ }
1141
+ async createGraphCollection(n, c) {
1142
+ this.ensureInitialized();
1143
+ return wasmCreateGraphCollection(n, c);
1144
+ }
1145
+ async getCollectionStats(c) {
1146
+ this.ensureInitialized();
1147
+ return wasmGetCollectionStats(c);
1148
+ }
1149
+ async analyzeCollection(c) {
1150
+ this.ensureInitialized();
1151
+ return wasmAnalyzeCollection(c);
1152
+ }
1153
+ async getCollectionConfig(c) {
1154
+ this.ensureInitialized();
1155
+ return wasmGetCollectionConfig(c);
1156
+ }
1157
+ async searchIds(c, q, o) {
1158
+ this.ensureInitialized();
1159
+ return wasmSearchIds(c, q, o);
1160
+ }
1161
+ async storeSemanticFact(c, e) {
558
1162
  this.ensureInitialized();
559
- wasmNotSupported("Graph collections");
1163
+ return wasmStoreSemanticFact(c, e);
560
1164
  }
561
- async getCollectionStats(_collection) {
1165
+ async searchSemanticMemory(c, e, k) {
562
1166
  this.ensureInitialized();
563
- wasmNotSupported("Collection stats");
1167
+ return wasmSearchSemanticMemory(c, e, k);
564
1168
  }
565
- async analyzeCollection(_collection) {
1169
+ async recordEpisodicEvent(c, e) {
566
1170
  this.ensureInitialized();
567
- wasmNotSupported("Collection analyze");
1171
+ return wasmRecordEpisodicEvent(c, e);
568
1172
  }
569
- async getCollectionConfig(_collection) {
1173
+ async recallEpisodicEvents(c, e, k) {
570
1174
  this.ensureInitialized();
571
- wasmNotSupported("Collection config");
1175
+ return wasmRecallEpisodicEvents(c, e, k);
572
1176
  }
573
- async searchIds(_collection, _query, _options) {
1177
+ async storeProceduralPattern(c, p) {
574
1178
  this.ensureInitialized();
575
- wasmNotSupported("searchIds");
1179
+ return wasmStoreProceduralPattern(c, p);
576
1180
  }
577
- async storeSemanticFact(_collection, _entry) {
1181
+ async matchProceduralPatterns(c, e, k) {
578
1182
  this.ensureInitialized();
579
- wasmNotSupported("Agent memory");
1183
+ return wasmMatchProceduralPatterns(c, e, k);
580
1184
  }
581
- async searchSemanticMemory(_collection, _embedding, _k) {
1185
+ // Wave 4 stubs
1186
+ async rebuildIndex(c) {
582
1187
  this.ensureInitialized();
583
- wasmNotSupported("Agent memory");
1188
+ return wasmRebuildIndex(c);
584
1189
  }
585
- async recordEpisodicEvent(_collection, _event) {
1190
+ async getGuardrails() {
586
1191
  this.ensureInitialized();
587
- wasmNotSupported("Agent memory");
1192
+ return wasmGetGuardrails();
588
1193
  }
589
- async recallEpisodicEvents(_collection, _embedding, _k) {
1194
+ async updateGuardrails(r) {
590
1195
  this.ensureInitialized();
591
- wasmNotSupported("Agent memory");
1196
+ return wasmUpdateGuardrails(r);
592
1197
  }
593
- async storeProceduralPattern(_collection, _pattern) {
1198
+ async aggregate(_q, _p, _o) {
594
1199
  this.ensureInitialized();
595
- wasmNotSupported("Agent memory");
1200
+ return wasmAggregate(_q, _p, _o);
596
1201
  }
597
- async matchProceduralPatterns(_collection, _embedding, _k) {
1202
+ async matchQuery(c, q, p, o) {
598
1203
  this.ensureInitialized();
599
- wasmNotSupported("Agent memory");
1204
+ return wasmMatchQuery(c, q, p, o);
1205
+ }
1206
+ async removeEdge(c, id) {
1207
+ this.ensureInitialized();
1208
+ return wasmRemoveEdge(c, id);
1209
+ }
1210
+ async getEdgeCount(c) {
1211
+ this.ensureInitialized();
1212
+ return wasmGetEdgeCount(c);
1213
+ }
1214
+ async listNodes(c) {
1215
+ this.ensureInitialized();
1216
+ return wasmListNodes(c);
1217
+ }
1218
+ async getNodeEdges(c, id, o) {
1219
+ this.ensureInitialized();
1220
+ return wasmGetNodeEdges(c, id, o);
1221
+ }
1222
+ async getNodePayload(c, id) {
1223
+ this.ensureInitialized();
1224
+ return wasmGetNodePayload(c, id);
1225
+ }
1226
+ async upsertNodePayload(c, id, p) {
1227
+ this.ensureInitialized();
1228
+ return wasmUpsertNodePayload(c, id, p);
1229
+ }
1230
+ async graphSearch(c, r) {
1231
+ this.ensureInitialized();
1232
+ return wasmGraphSearch(c, r);
600
1233
  }
601
1234
  };
602
1235
 
1236
+ // src/backends/crud-backend.ts
1237
+ function parseRestPointId(id) {
1238
+ if (typeof id !== "number" || !Number.isFinite(id) || id < 0 || !Number.isInteger(id) || id > Number.MAX_SAFE_INTEGER) {
1239
+ throw new ValidationError(
1240
+ `REST backend requires numeric u64-compatible IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER}). Received: ${String(id)}`
1241
+ );
1242
+ }
1243
+ return id;
1244
+ }
1245
+ function sparseVectorToRestFormat(sv) {
1246
+ const result = {};
1247
+ for (const [k, v] of Object.entries(sv)) {
1248
+ result[String(k)] = v;
1249
+ }
1250
+ return result;
1251
+ }
1252
+ function toDeferredIndexingWire(opts) {
1253
+ if (!opts) return void 0;
1254
+ const wire = {};
1255
+ if (opts.enabled !== void 0) wire.enabled = opts.enabled;
1256
+ if (opts.mergeThreshold !== void 0) wire.merge_threshold = opts.mergeThreshold;
1257
+ if (opts.maxBufferAgeMs !== void 0) wire.max_buffer_age_ms = opts.maxBufferAgeMs;
1258
+ return wire;
1259
+ }
1260
+ function toAsyncIndexBuilderWire(opts) {
1261
+ if (!opts) return void 0;
1262
+ const wire = {};
1263
+ if (opts.mergeThreshold !== void 0) wire.merge_threshold = opts.mergeThreshold;
1264
+ if (opts.segmentCount !== void 0) wire.segment_count = opts.segmentCount;
1265
+ return wire;
1266
+ }
1267
+ async function createCollection(transport, name, config) {
1268
+ const body = {
1269
+ name,
1270
+ dimension: config.dimension,
1271
+ metric: config.metric ?? "cosine",
1272
+ storage_mode: config.storageMode ?? "full",
1273
+ collection_type: config.collectionType ?? "vector",
1274
+ description: config.description,
1275
+ hnsw_m: config.hnsw?.m,
1276
+ hnsw_ef_construction: config.hnsw?.efConstruction,
1277
+ hnsw_alpha: config.hnsw?.alpha,
1278
+ hnsw_max_elements: config.hnsw?.maxElements
1279
+ };
1280
+ if (config.pqRescoreOversampling !== void 0) {
1281
+ body.pq_rescore_oversampling = config.pqRescoreOversampling;
1282
+ }
1283
+ const deferredWire = toDeferredIndexingWire(config.deferredIndexing);
1284
+ if (deferredWire !== void 0) {
1285
+ body.deferred_indexing = deferredWire;
1286
+ }
1287
+ const asyncWire = toAsyncIndexBuilderWire(config.asyncIndexBuilder);
1288
+ if (asyncWire !== void 0) {
1289
+ body.async_index_builder = asyncWire;
1290
+ }
1291
+ const response = await transport.requestJson("POST", "/collections", body);
1292
+ throwOnError(response);
1293
+ }
1294
+ async function deleteCollection(transport, name) {
1295
+ const response = await transport.requestJson(
1296
+ "DELETE",
1297
+ collectionPath(name)
1298
+ );
1299
+ throwOnError(response, `Collection '${name}'`);
1300
+ }
1301
+ async function getCollection(transport, name) {
1302
+ const response = await transport.requestJson(
1303
+ "GET",
1304
+ collectionPath(name)
1305
+ );
1306
+ if (returnNullOnNotFound(response)) {
1307
+ return null;
1308
+ }
1309
+ return response.data ?? null;
1310
+ }
1311
+ async function listCollections(transport) {
1312
+ const response = await transport.requestJson("GET", "/collections");
1313
+ throwOnError(response);
1314
+ return response.data ?? [];
1315
+ }
1316
+ async function upsert(transport, collection, doc) {
1317
+ const restId = parseRestPointId(doc.id);
1318
+ const vector = toNumberArray(doc.vector);
1319
+ const response = await transport.requestJson(
1320
+ "POST",
1321
+ `${collectionPath(collection)}/points`,
1322
+ { points: [{ id: restId, vector, payload: doc.payload }] }
1323
+ );
1324
+ throwOnError(response, `Collection '${collection}'`);
1325
+ }
1326
+ async function upsertBatch(transport, collection, docs) {
1327
+ const vectors = docs.map((doc) => ({
1328
+ id: parseRestPointId(doc.id),
1329
+ vector: toNumberArray(doc.vector),
1330
+ payload: doc.payload
1331
+ }));
1332
+ const response = await transport.requestJson(
1333
+ "POST",
1334
+ `${collectionPath(collection)}/points`,
1335
+ { points: vectors }
1336
+ );
1337
+ throwOnError(response, `Collection '${collection}'`);
1338
+ }
1339
+ async function deletePoint(transport, collection, id) {
1340
+ const restId = parseRestPointId(id);
1341
+ const response = await transport.requestJson(
1342
+ "DELETE",
1343
+ `${collectionPath(collection)}/points/${encodeURIComponent(String(restId))}`
1344
+ );
1345
+ if (returnNullOnNotFound(response)) {
1346
+ return false;
1347
+ }
1348
+ return response.data?.deleted ?? false;
1349
+ }
1350
+ async function get(transport, collection, id) {
1351
+ const restId = parseRestPointId(id);
1352
+ const response = await transport.requestJson(
1353
+ "GET",
1354
+ `${collectionPath(collection)}/points/${encodeURIComponent(String(restId))}`
1355
+ );
1356
+ if (returnNullOnNotFound(response)) {
1357
+ return null;
1358
+ }
1359
+ return response.data ?? null;
1360
+ }
1361
+ async function isEmpty(transport, collection) {
1362
+ const response = await transport.requestJson(
1363
+ "GET",
1364
+ `${collectionPath(collection)}/empty`
1365
+ );
1366
+ throwOnError(response, `Collection '${collection}'`);
1367
+ return response.data?.is_empty ?? true;
1368
+ }
1369
+ async function flush(transport, collection) {
1370
+ const response = await transport.requestJson(
1371
+ "POST",
1372
+ `${collectionPath(collection)}/flush`
1373
+ );
1374
+ throwOnError(response, `Collection '${collection}'`);
1375
+ }
1376
+
1377
+ // src/backends/rest-http.ts
1378
+ var STATUS_ERROR_CODES = {
1379
+ 400: "BAD_REQUEST",
1380
+ 401: "UNAUTHORIZED",
1381
+ 403: "FORBIDDEN",
1382
+ 404: "NOT_FOUND",
1383
+ 409: "CONFLICT",
1384
+ 429: "RATE_LIMITED",
1385
+ 500: "INTERNAL_ERROR",
1386
+ 503: "SERVICE_UNAVAILABLE"
1387
+ };
1388
+ function mapStatusToErrorCode(status) {
1389
+ return STATUS_ERROR_CODES[status] ?? "UNKNOWN_ERROR";
1390
+ }
1391
+ function stringField(obj, ...keys) {
1392
+ for (const key of keys) {
1393
+ if (typeof obj[key] === "string") return obj[key];
1394
+ }
1395
+ return void 0;
1396
+ }
1397
+ function extractErrorPayload(data) {
1398
+ if (!data || typeof data !== "object") return {};
1399
+ const payload = data;
1400
+ const nested = typeof payload.error === "object" && payload.error ? payload.error : payload;
1401
+ return {
1402
+ code: stringField(nested, "code") ?? stringField(payload, "code"),
1403
+ message: stringField(nested, "message") ?? stringField(payload, "message", "error")
1404
+ };
1405
+ }
1406
+ function parseNodeId(value) {
1407
+ if (value === null || value === void 0) {
1408
+ return 0;
1409
+ }
1410
+ if (typeof value === "bigint") {
1411
+ return value;
1412
+ }
1413
+ if (typeof value === "string") {
1414
+ const num = Number(value);
1415
+ return num > Number.MAX_SAFE_INTEGER ? BigInt(value) : num;
1416
+ }
1417
+ if (typeof value === "number") {
1418
+ return value;
1419
+ }
1420
+ return 0;
1421
+ }
1422
+ function buildHeaders(config) {
1423
+ const headers = { "Content-Type": "application/json" };
1424
+ if (config.apiKey) headers["Authorization"] = `Bearer ${config.apiKey}`;
1425
+ return headers;
1426
+ }
1427
+ function wrapCatchError(error) {
1428
+ if (error instanceof Error && error.name === "AbortError") {
1429
+ throw new ConnectionError("Request timeout");
1430
+ }
1431
+ const message = error instanceof Error ? error.message : "Unknown error";
1432
+ const cause = error instanceof Error ? error : void 0;
1433
+ throw new ConnectionError(`Request failed: ${message}`, cause);
1434
+ }
1435
+ async function request(config, method, path, body) {
1436
+ const controller = new AbortController();
1437
+ const timeoutId = setTimeout(() => controller.abort(), config.timeout);
1438
+ try {
1439
+ const response = await fetch(`${config.baseUrl}${path}`, {
1440
+ method,
1441
+ headers: buildHeaders(config),
1442
+ body: body ? JSON.stringify(body) : void 0,
1443
+ signal: controller.signal
1444
+ });
1445
+ clearTimeout(timeoutId);
1446
+ const data = await response.json().catch(() => ({}));
1447
+ if (!response.ok) {
1448
+ const ep = extractErrorPayload(data);
1449
+ return { error: {
1450
+ code: ep.code ?? mapStatusToErrorCode(response.status),
1451
+ message: ep.message ?? `HTTP ${response.status}`
1452
+ } };
1453
+ }
1454
+ return { data };
1455
+ } catch (error) {
1456
+ clearTimeout(timeoutId);
1457
+ wrapCatchError(error);
1458
+ }
1459
+ }
1460
+ function buildBaseTransport(config) {
1461
+ return {
1462
+ requestJson: (m, p, b) => request(config, m, p, b)
1463
+ };
1464
+ }
1465
+ function buildCrudTransport(config) {
1466
+ return {
1467
+ requestJson: (m, p, b) => request(config, m, p, b)
1468
+ };
1469
+ }
1470
+ function buildSearchTransport(config) {
1471
+ return {
1472
+ requestJson: (m, p, b) => request(config, m, p, b),
1473
+ sparseToRest: (sv) => sparseVectorToRestFormat(sv)
1474
+ };
1475
+ }
1476
+ function buildQueryTransport(config) {
1477
+ return {
1478
+ requestJson: (m, p, b) => request(config, m, p, b),
1479
+ parseNodeId: (v) => parseNodeId(v)
1480
+ };
1481
+ }
1482
+ function buildStreamingTransport(config) {
1483
+ return {
1484
+ requestJson: (m, p, b) => request(config, m, p, b),
1485
+ baseUrl: config.baseUrl,
1486
+ apiKey: config.apiKey,
1487
+ timeout: config.timeout,
1488
+ parseRestPointId,
1489
+ sparseVectorToRestFormat,
1490
+ mapStatusToErrorCode: (s) => mapStatusToErrorCode(s),
1491
+ extractErrorPayload: (d) => extractErrorPayload(d)
1492
+ };
1493
+ }
1494
+ function buildAgentMemoryTransport(config, searchFn) {
1495
+ return {
1496
+ requestJson: (m, p, b) => request(config, m, p, b),
1497
+ searchVectors: (c, e, k, f2) => searchFn(c, e, { k, filter: f2 })
1498
+ };
1499
+ }
1500
+
1501
+ // src/backends/missing-endpoints.ts
1502
+ async function rebuildIndex(transport, collection) {
1503
+ const response = await transport.requestJson(
1504
+ "POST",
1505
+ `${collectionPath(collection)}/index/rebuild`
1506
+ );
1507
+ throwOnError(response, `Collection '${collection}'`);
1508
+ const data = response.data;
1509
+ return {
1510
+ message: data.message,
1511
+ collection: data.collection,
1512
+ compactedEntries: data.compacted_entries
1513
+ };
1514
+ }
1515
+ function mapGuardRailsWire(data) {
1516
+ return {
1517
+ maxDepth: data.max_depth,
1518
+ maxCardinality: data.max_cardinality,
1519
+ memoryLimitBytes: data.memory_limit_bytes,
1520
+ timeoutMs: data.timeout_ms,
1521
+ rateLimitQps: data.rate_limit_qps,
1522
+ circuitFailureThreshold: data.circuit_failure_threshold,
1523
+ circuitRecoverySeconds: data.circuit_recovery_seconds
1524
+ };
1525
+ }
1526
+ function toGuardRailsWireUpdate(req) {
1527
+ const wire = {};
1528
+ if (req.maxDepth !== void 0) wire.max_depth = req.maxDepth;
1529
+ if (req.maxCardinality !== void 0) wire.max_cardinality = req.maxCardinality;
1530
+ if (req.memoryLimitBytes !== void 0) wire.memory_limit_bytes = req.memoryLimitBytes;
1531
+ if (req.timeoutMs !== void 0) wire.timeout_ms = req.timeoutMs;
1532
+ if (req.rateLimitQps !== void 0) wire.rate_limit_qps = req.rateLimitQps;
1533
+ if (req.circuitFailureThreshold !== void 0) {
1534
+ wire.circuit_failure_threshold = req.circuitFailureThreshold;
1535
+ }
1536
+ if (req.circuitRecoverySeconds !== void 0) {
1537
+ wire.circuit_recovery_seconds = req.circuitRecoverySeconds;
1538
+ }
1539
+ return wire;
1540
+ }
1541
+ async function getGuardrails(transport) {
1542
+ const response = await transport.requestJson("GET", "/guardrails");
1543
+ throwOnError(response);
1544
+ return mapGuardRailsWire(response.data);
1545
+ }
1546
+ async function updateGuardrails(transport, req) {
1547
+ const response = await transport.requestJson(
1548
+ "PUT",
1549
+ "/guardrails",
1550
+ toGuardRailsWireUpdate(req)
1551
+ );
1552
+ throwOnError(response);
1553
+ return mapGuardRailsWire(response.data);
1554
+ }
1555
+ async function aggregate(transport, queryString, params, options) {
1556
+ const body = {
1557
+ query: queryString,
1558
+ params: params ?? {}
1559
+ };
1560
+ if (options?.collection !== void 0) {
1561
+ body.collection = options.collection;
1562
+ }
1563
+ const response = await transport.requestJson(
1564
+ "POST",
1565
+ "/aggregate",
1566
+ body
1567
+ );
1568
+ throwOnError(response);
1569
+ const data = response.data;
1570
+ return {
1571
+ result: data.result,
1572
+ timingMs: data.timing_ms,
1573
+ meta: {
1574
+ velesqlContractVersion: data.meta.velesql_contract_version,
1575
+ count: data.meta.count
1576
+ }
1577
+ };
1578
+ }
1579
+ async function matchQuery(transport, collection, queryString, params, options) {
1580
+ const body = {
1581
+ query: queryString,
1582
+ params: params ?? {}
1583
+ };
1584
+ if (options?.vector !== void 0) {
1585
+ body.vector = toNumberArray(options.vector);
1586
+ }
1587
+ if (options?.threshold !== void 0) {
1588
+ body.threshold = options.threshold;
1589
+ }
1590
+ const response = await transport.requestJson(
1591
+ "POST",
1592
+ `${collectionPath(collection)}/match`,
1593
+ body
1594
+ );
1595
+ throwOnError(response, `Collection '${collection}'`);
1596
+ const data = response.data;
1597
+ const items = data.results.map((r) => ({
1598
+ bindings: r.bindings,
1599
+ score: r.score,
1600
+ depth: r.depth,
1601
+ projected: r.projected ?? {}
1602
+ }));
1603
+ return {
1604
+ results: items,
1605
+ tookMs: data.took_ms,
1606
+ count: data.count,
1607
+ meta: { velesqlContractVersion: data.meta.velesql_contract_version }
1608
+ };
1609
+ }
1610
+ async function removeEdge(transport, collection, edgeId) {
1611
+ const response = await transport.requestJson(
1612
+ "DELETE",
1613
+ `${collectionPath(collection)}/graph/edges/${edgeId}`
1614
+ );
1615
+ if (response.error !== void 0) {
1616
+ const { code, message } = response.error;
1617
+ const err = parseVelesError(code, message);
1618
+ if (err instanceof EdgeNotFoundError) {
1619
+ return false;
1620
+ }
1621
+ if (code === "NOT_FOUND") {
1622
+ return false;
1623
+ }
1624
+ throwOnError(response, `Collection '${collection}'`);
1625
+ }
1626
+ return true;
1627
+ }
1628
+ async function getEdgeCount(transport, collection) {
1629
+ const response = await transport.requestJson(
1630
+ "GET",
1631
+ `${collectionPath(collection)}/graph/edges/count`
1632
+ );
1633
+ throwOnError(response, `Collection '${collection}'`);
1634
+ return response.data?.count ?? 0;
1635
+ }
1636
+ async function listNodes(transport, collection) {
1637
+ const response = await transport.requestJson(
1638
+ "GET",
1639
+ `${collectionPath(collection)}/graph/nodes`
1640
+ );
1641
+ throwOnError(response, `Collection '${collection}'`);
1642
+ const data = response.data;
1643
+ return { nodeIds: data.node_ids, count: data.count };
1644
+ }
1645
+ function idToNumber(id) {
1646
+ return typeof id === "string" ? Number(id) : id;
1647
+ }
1648
+ async function getNodeEdges(transport, collection, nodeId, options) {
1649
+ const params = new URLSearchParams();
1650
+ if (options?.direction) params.set("direction", options.direction);
1651
+ if (options?.label) params.set("label", options.label);
1652
+ const qs = params.toString();
1653
+ const url = `${collectionPath(collection)}/graph/nodes/${nodeId}/edges` + (qs ? `?${qs}` : "");
1654
+ const response = await transport.requestJson("GET", url);
1655
+ throwOnError(response, `Collection '${collection}'`);
1656
+ return (response.data?.edges ?? []).map((e) => ({
1657
+ id: idToNumber(e.id),
1658
+ source: idToNumber(e.source),
1659
+ target: idToNumber(e.target),
1660
+ label: e.label,
1661
+ properties: e.properties
1662
+ }));
1663
+ }
1664
+ async function getNodePayload(transport, collection, nodeId) {
1665
+ const response = await transport.requestJson("GET", `${collectionPath(collection)}/graph/nodes/${nodeId}/payload`);
1666
+ throwOnError(response, `Collection '${collection}'`);
1667
+ const data = response.data;
1668
+ return {
1669
+ nodeId: idToNumber(data.node_id),
1670
+ payload: data.payload
1671
+ };
1672
+ }
1673
+ async function upsertNodePayload(transport, collection, nodeId, payload) {
1674
+ const response = await transport.requestJson(
1675
+ "PUT",
1676
+ `${collectionPath(collection)}/graph/nodes/${nodeId}/payload`,
1677
+ { payload }
1678
+ );
1679
+ throwOnError(response, `Collection '${collection}'`);
1680
+ }
1681
+ async function graphSearch(transport, collection, request2) {
1682
+ const response = await transport.requestJson(
1683
+ "POST",
1684
+ `${collectionPath(collection)}/graph/search`,
1685
+ {
1686
+ vector: toNumberArray(request2.vector),
1687
+ top_k: request2.k ?? 10
1688
+ }
1689
+ );
1690
+ throwOnError(response, `Collection '${collection}'`);
1691
+ const items = (response.data?.results ?? []).map(
1692
+ (r) => ({
1693
+ id: idToNumber(r.id),
1694
+ score: r.score,
1695
+ payload: r.payload
1696
+ })
1697
+ );
1698
+ return { results: items };
1699
+ }
1700
+
603
1701
  // src/backends/agent-memory-backend.ts
604
1702
  var _idCounter = 0;
605
1703
  var _lastTimestamp = 0;
606
1704
  function generateUniqueId() {
607
- let now = Date.now();
1705
+ const now = Date.now();
608
1706
  if (now <= _lastTimestamp) {
609
1707
  _idCounter++;
610
1708
  if (_idCounter >= 1e3) {
@@ -685,14 +1783,23 @@ async function matchProceduralPatterns(transport, collection, embedding, k = 5)
685
1783
  return transport.searchVectors(collection, embedding, k, { _memory_type: "procedural" });
686
1784
  }
687
1785
 
1786
+ // src/search-quality.ts
1787
+ function searchQualityToMode(quality) {
1788
+ if (quality === void 0) {
1789
+ return {};
1790
+ }
1791
+ return { mode: quality };
1792
+ }
1793
+
688
1794
  // src/backends/search-backend.ts
689
- async function search(transport, collection, query2, options) {
690
- const queryVector = toNumberArray(query2);
1795
+ async function search(transport, collection, query3, options) {
1796
+ const queryVector = toNumberArray(query3);
691
1797
  const body = {
692
1798
  vector: queryVector,
693
1799
  top_k: options?.k ?? 10,
694
1800
  filter: options?.filter,
695
- include_vectors: options?.includeVectors ?? false
1801
+ include_vectors: options?.includeVectors ?? false,
1802
+ ...searchQualityToMode(options?.quality)
696
1803
  };
697
1804
  if (options?.sparseVector) {
698
1805
  body.sparse_vector = transport.sparseToRest(options.sparseVector);
@@ -709,7 +1816,8 @@ async function searchBatch(transport, collection, searches) {
709
1816
  const formattedSearches = searches.map((s) => ({
710
1817
  vector: toNumberArray(s.vector),
711
1818
  top_k: s.k ?? 10,
712
- filter: s.filter
1819
+ filter: s.filter,
1820
+ ...searchQualityToMode(s.quality)
713
1821
  }));
714
1822
  const response = await transport.requestJson(
715
1823
  "POST",
@@ -719,12 +1827,12 @@ async function searchBatch(transport, collection, searches) {
719
1827
  throwOnError(response, `Collection '${collection}'`);
720
1828
  return response.data?.results.map((r) => r.results) ?? [];
721
1829
  }
722
- async function textSearch(transport, collection, query2, options) {
1830
+ async function textSearch(transport, collection, query3, options) {
723
1831
  const response = await transport.requestJson(
724
1832
  "POST",
725
1833
  `${collectionPath(collection)}/search/text`,
726
1834
  {
727
- query: query2,
1835
+ query: query3,
728
1836
  top_k: options?.k ?? 10,
729
1837
  filter: options?.filter
730
1838
  }
@@ -767,15 +1875,16 @@ async function multiQuerySearch(transport, collection, vectors, options) {
767
1875
  throwOnError(response, `Collection '${collection}'`);
768
1876
  return response.data?.results ?? [];
769
1877
  }
770
- async function searchIds(transport, collection, query2, options) {
771
- const queryVector = toNumberArray(query2);
1878
+ async function searchIds(transport, collection, query3, options) {
1879
+ const queryVector = toNumberArray(query3);
772
1880
  const response = await transport.requestJson(
773
1881
  "POST",
774
1882
  `${collectionPath(collection)}/search/ids`,
775
1883
  {
776
1884
  vector: queryVector,
777
1885
  top_k: options?.k ?? 10,
778
- filter: options?.filter
1886
+ filter: options?.filter,
1887
+ ...searchQualityToMode(options?.quality)
779
1888
  }
780
1889
  );
781
1890
  throwOnError(response, `Collection '${collection}'`);
@@ -797,6 +1906,16 @@ async function addEdge(transport, collection, edge) {
797
1906
  );
798
1907
  throwOnError(response, `Collection '${collection}'`);
799
1908
  }
1909
+ function toGraphEdge(e) {
1910
+ const toNum = (v) => typeof v === "string" ? Number(v) : v;
1911
+ return {
1912
+ id: toNum(e.id),
1913
+ source: toNum(e.source),
1914
+ target: toNum(e.target),
1915
+ label: e.label,
1916
+ properties: e.properties
1917
+ };
1918
+ }
800
1919
  async function getEdges(transport, collection, options) {
801
1920
  const queryParams = options?.label ? `?label=${encodeURIComponent(options.label)}` : "";
802
1921
  const response = await transport.requestJson(
@@ -804,19 +1923,19 @@ async function getEdges(transport, collection, options) {
804
1923
  `${collectionPath(collection)}/graph/edges${queryParams}`
805
1924
  );
806
1925
  throwOnError(response, `Collection '${collection}'`);
807
- return response.data?.edges ?? [];
1926
+ return (response.data?.edges ?? []).map(toGraphEdge);
808
1927
  }
809
- async function traverseGraph(transport, collection, request) {
1928
+ async function traverseGraph(transport, collection, request2) {
810
1929
  const response = await transport.requestJson(
811
1930
  "POST",
812
1931
  `${collectionPath(collection)}/graph/traverse`,
813
1932
  {
814
- source: request.source,
815
- strategy: request.strategy ?? "bfs",
816
- max_depth: request.maxDepth ?? 3,
817
- limit: request.limit ?? 100,
818
- cursor: request.cursor,
819
- rel_types: request.relTypes ?? []
1933
+ source: request2.source,
1934
+ strategy: request2.strategy ?? "bfs",
1935
+ max_depth: request2.maxDepth ?? 3,
1936
+ limit: request2.limit ?? 100,
1937
+ cursor: request2.cursor,
1938
+ rel_types: request2.relTypes ?? []
820
1939
  }
821
1940
  );
822
1941
  throwOnError(response, `Collection '${collection}'`);
@@ -856,6 +1975,33 @@ async function createGraphCollection(transport, name, config) {
856
1975
  });
857
1976
  throwOnError(response);
858
1977
  }
1978
+ async function traverseParallel(transport, collection, request2) {
1979
+ const response = await transport.requestJson(
1980
+ "POST",
1981
+ `${collectionPath(collection)}/graph/traverse/parallel`,
1982
+ {
1983
+ sources: request2.sources,
1984
+ max_depth: request2.maxDepth ?? 3,
1985
+ limit: request2.limit ?? 100,
1986
+ rel_types: request2.relTypes ?? []
1987
+ }
1988
+ );
1989
+ throwOnError(response, `Collection '${collection}'`);
1990
+ const data = response.data;
1991
+ return {
1992
+ results: data.results.map((r) => ({
1993
+ targetId: r.target_id,
1994
+ depth: r.depth,
1995
+ path: r.path
1996
+ })),
1997
+ nextCursor: data.next_cursor ?? void 0,
1998
+ hasMore: data.has_more,
1999
+ stats: {
2000
+ visited: data.stats.visited,
2001
+ depthReached: data.stats.depth_reached
2002
+ }
2003
+ };
2004
+ }
859
2005
 
860
2006
  // src/backends/query-backend.ts
861
2007
  function isLikelyAggregationQuery(queryString) {
@@ -900,14 +2046,18 @@ async function query(transport, collection, queryString, params, options) {
900
2046
  }
901
2047
  };
902
2048
  }
903
- async function queryExplain(transport, queryString, params) {
2049
+ async function queryExplain(transport, queryString, params, options) {
2050
+ const body = {
2051
+ query: queryString,
2052
+ params: params ?? {}
2053
+ };
2054
+ if (options?.analyze) {
2055
+ body.analyze = true;
2056
+ }
904
2057
  const response = await transport.requestJson(
905
2058
  "POST",
906
2059
  "/query/explain",
907
- {
908
- query: queryString,
909
- params: params ?? {}
910
- }
2060
+ body
911
2061
  );
912
2062
  throwOnError(response);
913
2063
  const data = response.data;
@@ -919,7 +2069,8 @@ async function queryExplain(transport, queryString, params) {
919
2069
  step: step.step,
920
2070
  operation: step.operation,
921
2071
  description: step.description,
922
- estimatedRows: step.estimated_rows
2072
+ estimatedRows: step.estimated_rows,
2073
+ estimationMethod: step.estimation_method ?? null
923
2074
  })),
924
2075
  estimatedCost: {
925
2076
  usesIndex: data.estimated_cost.uses_index,
@@ -937,7 +2088,22 @@ async function queryExplain(transport, queryString, params) {
937
2088
  hasFusion: data.features.has_fusion,
938
2089
  limit: data.features.limit,
939
2090
  offset: data.features.offset
940
- }
2091
+ },
2092
+ actualStats: data.actual_stats ? {
2093
+ actualRows: data.actual_stats.actual_rows,
2094
+ actualTimeMs: data.actual_stats.actual_time_ms,
2095
+ loops: data.actual_stats.loops,
2096
+ nodesVisited: data.actual_stats.nodes_visited,
2097
+ edgesTraversed: data.actual_stats.edges_traversed
2098
+ } : data.actual_stats === null ? null : void 0,
2099
+ nodeStats: data.node_stats ? data.node_stats.map((ns) => ({
2100
+ nodeLabel: ns.node_label,
2101
+ actualTimeMs: ns.actual_time_ms,
2102
+ actualRowsIn: ns.actual_rows_in,
2103
+ actualRowsOut: ns.actual_rows_out,
2104
+ loops: ns.loops,
2105
+ estimated: ns.estimated
2106
+ })) : data.node_stats === null ? null : void 0
941
2107
  };
942
2108
  }
943
2109
  async function collectionSanity(transport, collection) {
@@ -968,8 +2134,49 @@ async function collectionSanity(transport, collection) {
968
2134
  };
969
2135
  }
970
2136
 
2137
+ // src/backends/scroll-backend.ts
2138
+ async function scroll(transport, collection, request2) {
2139
+ const body = {};
2140
+ if (request2?.cursor !== void 0) {
2141
+ body.cursor = request2.cursor;
2142
+ }
2143
+ if (request2?.batchSize !== void 0) {
2144
+ body.batch_size = request2.batchSize;
2145
+ }
2146
+ if (request2?.filter !== void 0) {
2147
+ body.filter = request2.filter;
2148
+ }
2149
+ const response = await transport.requestJson(
2150
+ "POST",
2151
+ `${collectionPath(collection)}/points/scroll`,
2152
+ body
2153
+ );
2154
+ throwOnError(response, `Collection '${collection}'`);
2155
+ const data = response.data;
2156
+ return {
2157
+ points: data.points,
2158
+ nextCursor: data.next_cursor
2159
+ };
2160
+ }
2161
+
971
2162
  // src/backends/admin-backend.ts
972
2163
  function mapStatsResponse(data) {
2164
+ let columnStats;
2165
+ if (data.column_stats) {
2166
+ columnStats = {};
2167
+ for (const [key, col] of Object.entries(data.column_stats)) {
2168
+ columnStats[key] = {
2169
+ name: col.name,
2170
+ nullCount: col.null_count,
2171
+ distinctCount: col.distinct_count,
2172
+ minValue: col.min_value,
2173
+ maxValue: col.max_value,
2174
+ avgSizeBytes: col.avg_size_bytes,
2175
+ histogramBuckets: col.histogram_buckets,
2176
+ histogramStale: col.histogram_stale
2177
+ };
2178
+ }
2179
+ }
973
2180
  return {
974
2181
  totalPoints: data.total_points,
975
2182
  totalSizeBytes: data.total_size_bytes,
@@ -977,7 +2184,8 @@ function mapStatsResponse(data) {
977
2184
  deletedCount: data.deleted_count,
978
2185
  avgRowSizeBytes: data.avg_row_size_bytes,
979
2186
  payloadSizeBytes: data.payload_size_bytes,
980
- lastAnalyzedEpochMs: data.last_analyzed_epoch_ms
2187
+ lastAnalyzedEpochMs: data.last_analyzed_epoch_ms,
2188
+ columnStats
981
2189
  };
982
2190
  }
983
2191
  async function getCollectionStats(transport, collection) {
@@ -998,10 +2206,7 @@ async function analyzeCollection(transport, collection) {
998
2206
  throwOnError(response, `Collection '${collection}'`);
999
2207
  return mapStatsResponse(response.data);
1000
2208
  }
1001
- async function getCollectionConfig(transport, collection) {
1002
- const response = await transport.requestJson("GET", `${collectionPath(collection)}/config`);
1003
- throwOnError(response, `Collection '${collection}'`);
1004
- const data = response.data;
2209
+ function mapConfigResponse(data) {
1005
2210
  return {
1006
2211
  name: data.name,
1007
2212
  dimension: data.dimension,
@@ -1010,9 +2215,22 @@ async function getCollectionConfig(transport, collection) {
1010
2215
  pointCount: data.point_count,
1011
2216
  metadataOnly: data.metadata_only,
1012
2217
  graphSchema: data.graph_schema,
1013
- embeddingDimension: data.embedding_dimension
2218
+ embeddingDimension: data.embedding_dimension,
2219
+ schemaVersion: data.schema_version,
2220
+ pqRescoreOversampling: data.pq_rescore_oversampling,
2221
+ hnswParams: data.hnsw_params,
2222
+ deferredIndexing: data.deferred_indexing,
2223
+ asyncIndexBuilder: data.async_index_builder
1014
2224
  };
1015
2225
  }
2226
+ async function getCollectionConfig(transport, collection) {
2227
+ const response = await transport.requestJson(
2228
+ "GET",
2229
+ `${collectionPath(collection)}/config`
2230
+ );
2231
+ throwOnError(response, `Collection '${collection}'`);
2232
+ return mapConfigResponse(response.data);
2233
+ }
1016
2234
 
1017
2235
  // src/backends/index-backend.ts
1018
2236
  async function createIndex(transport, collection, options) {
@@ -1047,218 +2265,170 @@ async function hasIndex(transport, collection, label, property) {
1047
2265
  }
1048
2266
  async function dropIndex(transport, collection, label, property) {
1049
2267
  const response = await transport.requestJson(
1050
- "DELETE",
1051
- `${collectionPath(collection)}/indexes/${encodeURIComponent(label)}/${encodeURIComponent(property)}`
1052
- );
1053
- if (returnNullOnNotFound(response)) {
1054
- return false;
1055
- }
1056
- return response.data?.dropped ?? true;
1057
- }
1058
-
1059
- // src/backends/streaming-backend.ts
1060
- async function trainPq(transport, collection, options) {
1061
- const m = options?.m ?? 8;
1062
- const k = options?.k ?? 256;
1063
- const withClause = options?.opq ? `WITH (m=${m}, k=${k}, opq=true)` : `WITH (m=${m}, k=${k})`;
1064
- const queryString = `TRAIN QUANTIZER ON ${collection} ${withClause}`;
1065
- const response = await transport.requestJson(
1066
- "POST",
1067
- "/query",
1068
- { query: queryString }
1069
- );
1070
- throwOnError(response);
1071
- return response.data?.message ?? "PQ training initiated";
1072
- }
1073
- async function streamInsert(transport, collection, docs) {
1074
- for (const doc of docs) {
1075
- const restId = transport.parseRestPointId(doc.id);
1076
- const vector = toNumberArray(doc.vector);
1077
- const body = {
1078
- id: restId,
1079
- vector,
1080
- payload: doc.payload
1081
- };
1082
- if (doc.sparseVector) {
1083
- body.sparse_vector = transport.sparseVectorToRestFormat(doc.sparseVector);
1084
- }
1085
- const url = `${transport.baseUrl}${collectionPath(collection)}/stream/insert`;
1086
- const headers = {
1087
- "Content-Type": "application/json"
1088
- };
1089
- if (transport.apiKey) {
1090
- headers["Authorization"] = `Bearer ${transport.apiKey}`;
1091
- }
1092
- const controller = new AbortController();
1093
- const timeoutId = setTimeout(() => controller.abort(), transport.timeout);
1094
- try {
1095
- const response = await fetch(url, {
1096
- method: "POST",
1097
- headers,
1098
- body: JSON.stringify(body),
1099
- signal: controller.signal
1100
- });
1101
- clearTimeout(timeoutId);
1102
- if (response.status === 429) {
1103
- throw new BackpressureError();
1104
- }
1105
- if (!response.ok && response.status !== 202) {
1106
- const data = await response.json().catch(() => ({}));
1107
- const errorPayload = transport.extractErrorPayload(data);
1108
- throw new VelesDBError(
1109
- errorPayload.message ?? `HTTP ${response.status}`,
1110
- errorPayload.code ?? transport.mapStatusToErrorCode(response.status)
1111
- );
1112
- }
1113
- } catch (error) {
1114
- clearTimeout(timeoutId);
1115
- if (error instanceof BackpressureError || error instanceof VelesDBError) {
1116
- throw error;
1117
- }
1118
- if (error instanceof Error && error.name === "AbortError") {
1119
- throw new ConnectionError("Request timeout");
1120
- }
1121
- throw new ConnectionError(
1122
- `Stream insert failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1123
- error instanceof Error ? error : void 0
1124
- );
1125
- }
1126
- }
1127
- }
1128
-
1129
- // src/backends/crud-backend.ts
1130
- function parseRestPointId(id) {
1131
- if (typeof id !== "number" || !Number.isFinite(id) || id < 0 || !Number.isInteger(id) || id > Number.MAX_SAFE_INTEGER) {
1132
- throw new ValidationError(
1133
- `REST backend requires numeric u64-compatible IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER}). Received: ${String(id)}`
1134
- );
1135
- }
1136
- return id;
1137
- }
1138
- function sparseVectorToRestFormat(sv) {
1139
- const result = {};
1140
- for (const [k, v] of Object.entries(sv)) {
1141
- result[String(k)] = v;
1142
- }
1143
- return result;
1144
- }
1145
- async function createCollection(transport, name, config) {
1146
- const response = await transport.requestJson("POST", "/collections", {
1147
- name,
1148
- dimension: config.dimension,
1149
- metric: config.metric ?? "cosine",
1150
- storage_mode: config.storageMode ?? "full",
1151
- collection_type: config.collectionType ?? "vector",
1152
- description: config.description,
1153
- hnsw_m: config.hnsw?.m,
1154
- hnsw_ef_construction: config.hnsw?.efConstruction
1155
- });
1156
- throwOnError(response);
1157
- }
1158
- async function deleteCollection(transport, name) {
1159
- const response = await transport.requestJson(
1160
- "DELETE",
1161
- collectionPath(name)
1162
- );
1163
- throwOnError(response, `Collection '${name}'`);
1164
- }
1165
- async function getCollection(transport, name) {
1166
- const response = await transport.requestJson(
1167
- "GET",
1168
- collectionPath(name)
1169
- );
1170
- if (returnNullOnNotFound(response)) {
1171
- return null;
1172
- }
1173
- return response.data ?? null;
1174
- }
1175
- async function listCollections(transport) {
1176
- const response = await transport.requestJson("GET", "/collections");
1177
- throwOnError(response);
1178
- return response.data ?? [];
1179
- }
1180
- async function insert(transport, collection, doc) {
1181
- const restId = parseRestPointId(doc.id);
1182
- const vector = toNumberArray(doc.vector);
1183
- const response = await transport.requestJson(
1184
- "POST",
1185
- `${collectionPath(collection)}/points`,
1186
- { points: [{ id: restId, vector, payload: doc.payload }] }
1187
- );
1188
- throwOnError(response, `Collection '${collection}'`);
1189
- }
1190
- async function insertBatch(transport, collection, docs) {
1191
- const vectors = docs.map((doc) => ({
1192
- id: parseRestPointId(doc.id),
1193
- vector: toNumberArray(doc.vector),
1194
- payload: doc.payload
1195
- }));
1196
- const response = await transport.requestJson(
1197
- "POST",
1198
- `${collectionPath(collection)}/points`,
1199
- { points: vectors }
1200
- );
1201
- throwOnError(response, `Collection '${collection}'`);
1202
- }
1203
- async function deletePoint(transport, collection, id) {
1204
- const restId = parseRestPointId(id);
1205
- const response = await transport.requestJson(
1206
- "DELETE",
1207
- `${collectionPath(collection)}/points/${encodeURIComponent(String(restId))}`
1208
- );
1209
- if (returnNullOnNotFound(response)) {
1210
- return false;
1211
- }
1212
- return response.data?.deleted ?? false;
1213
- }
1214
- async function get(transport, collection, id) {
1215
- const restId = parseRestPointId(id);
1216
- const response = await transport.requestJson(
1217
- "GET",
1218
- `${collectionPath(collection)}/points/${encodeURIComponent(String(restId))}`
2268
+ "DELETE",
2269
+ `${collectionPath(collection)}/indexes/${encodeURIComponent(label)}/${encodeURIComponent(property)}`
1219
2270
  );
1220
2271
  if (returnNullOnNotFound(response)) {
1221
- return null;
2272
+ return false;
1222
2273
  }
1223
- return response.data ?? null;
1224
- }
1225
- async function isEmpty(transport, collection) {
1226
- const response = await transport.requestJson(
1227
- "GET",
1228
- `${collectionPath(collection)}/empty`
1229
- );
1230
- throwOnError(response, `Collection '${collection}'`);
1231
- return response.data?.is_empty ?? true;
2274
+ return response.data?.dropped ?? true;
1232
2275
  }
1233
- async function flush(transport, collection) {
2276
+
2277
+ // src/backends/streaming-backend.ts
2278
+ async function trainPq(transport, collection, options) {
2279
+ validateCollectionName(collection);
2280
+ const m = options?.m ?? 8;
2281
+ const k = options?.k ?? 256;
2282
+ const withClause = options?.opq ? `WITH (m=${m}, k=${k}, opq=true)` : `WITH (m=${m}, k=${k})`;
2283
+ const queryString = `TRAIN QUANTIZER ON ${collection} ${withClause}`;
1234
2284
  const response = await transport.requestJson(
1235
2285
  "POST",
1236
- `${collectionPath(collection)}/flush`
2286
+ "/query",
2287
+ { query: queryString }
1237
2288
  );
1238
- throwOnError(response, `Collection '${collection}'`);
2289
+ throwOnError(response);
2290
+ return response.data?.message ?? "PQ training initiated";
2291
+ }
2292
+ async function streamInsert(transport, collection, docs) {
2293
+ for (const doc of docs) {
2294
+ const restId = transport.parseRestPointId(doc.id);
2295
+ const vector = toNumberArray(doc.vector);
2296
+ const body = {
2297
+ id: restId,
2298
+ vector,
2299
+ payload: doc.payload ?? null
2300
+ };
2301
+ if (doc.sparseVector) {
2302
+ body.sparse_vector = transport.sparseVectorToRestFormat(doc.sparseVector);
2303
+ }
2304
+ const url = `${transport.baseUrl}${collectionPath(collection)}/stream/insert`;
2305
+ const headers = {
2306
+ "Content-Type": "application/json"
2307
+ };
2308
+ if (transport.apiKey) {
2309
+ headers["Authorization"] = `Bearer ${transport.apiKey}`;
2310
+ }
2311
+ const controller = new AbortController();
2312
+ const timeoutId = setTimeout(() => controller.abort(), transport.timeout);
2313
+ try {
2314
+ const response = await fetch(url, {
2315
+ method: "POST",
2316
+ headers,
2317
+ body: JSON.stringify(body),
2318
+ signal: controller.signal
2319
+ });
2320
+ clearTimeout(timeoutId);
2321
+ if (response.status === 429) {
2322
+ throw new BackpressureError();
2323
+ }
2324
+ if (!response.ok && response.status !== 202) {
2325
+ const data = await response.json().catch(() => ({}));
2326
+ const errorPayload = transport.extractErrorPayload(data);
2327
+ throw new VelesDBError(
2328
+ errorPayload.message ?? `HTTP ${response.status}`,
2329
+ errorPayload.code ?? transport.mapStatusToErrorCode(response.status)
2330
+ );
2331
+ }
2332
+ } catch (error) {
2333
+ clearTimeout(timeoutId);
2334
+ if (error instanceof BackpressureError || error instanceof VelesDBError) {
2335
+ throw error;
2336
+ }
2337
+ if (error instanceof Error && error.name === "AbortError") {
2338
+ throw new ConnectionError("Request timeout");
2339
+ }
2340
+ throw new ConnectionError(
2341
+ `Stream insert failed: ${error instanceof Error ? error.message : "Unknown error"}`,
2342
+ error instanceof Error ? error : void 0
2343
+ );
2344
+ }
2345
+ }
2346
+ }
2347
+ async function streamUpsertPoints(transport, collection, docs) {
2348
+ const ndjsonLines = docs.map((doc) => {
2349
+ const restId = transport.parseRestPointId(doc.id);
2350
+ const vector = toNumberArray(doc.vector);
2351
+ const point = {
2352
+ id: restId,
2353
+ vector,
2354
+ payload: doc.payload ?? null
2355
+ };
2356
+ if (doc.sparseVector) {
2357
+ point.sparse_vector = transport.sparseVectorToRestFormat(doc.sparseVector);
2358
+ }
2359
+ return JSON.stringify(point);
2360
+ });
2361
+ const body = ndjsonLines.join("\n");
2362
+ const url = `${transport.baseUrl}${collectionPath(collection)}/points/stream`;
2363
+ const headers = {
2364
+ "Content-Type": "application/x-ndjson"
2365
+ };
2366
+ if (transport.apiKey) {
2367
+ headers["Authorization"] = `Bearer ${transport.apiKey}`;
2368
+ }
2369
+ const controller = new AbortController();
2370
+ const timeoutId = setTimeout(() => controller.abort(), transport.timeout);
2371
+ try {
2372
+ const response = await fetch(url, {
2373
+ method: "POST",
2374
+ headers,
2375
+ body,
2376
+ signal: controller.signal
2377
+ });
2378
+ clearTimeout(timeoutId);
2379
+ if (response.status === 429) {
2380
+ throw new BackpressureError();
2381
+ }
2382
+ if (!response.ok) {
2383
+ const data2 = await response.json().catch(() => ({}));
2384
+ const errorPayload = transport.extractErrorPayload(data2);
2385
+ throw new VelesDBError(
2386
+ errorPayload.message ?? `HTTP ${response.status}`,
2387
+ errorPayload.code ?? transport.mapStatusToErrorCode(response.status)
2388
+ );
2389
+ }
2390
+ const data = await response.json().catch(() => ({}));
2391
+ return {
2392
+ message: typeof data.message === "string" ? data.message : "Stream processed",
2393
+ inserted: typeof data.inserted === "number" ? data.inserted : 0,
2394
+ malformed: typeof data.malformed === "number" ? data.malformed : 0,
2395
+ failedUpserts: typeof data.failed_upserts === "number" ? data.failed_upserts : 0,
2396
+ networkErrors: typeof data.network_errors === "number" ? data.network_errors : 0
2397
+ };
2398
+ } catch (error) {
2399
+ clearTimeout(timeoutId);
2400
+ if (error instanceof BackpressureError || error instanceof VelesDBError) {
2401
+ throw error;
2402
+ }
2403
+ if (error instanceof Error && error.name === "AbortError") {
2404
+ throw new ConnectionError("Request timeout");
2405
+ }
2406
+ throw new ConnectionError(
2407
+ `Stream upsert failed: ${error instanceof Error ? error.message : "Unknown error"}`,
2408
+ error instanceof Error ? error : void 0
2409
+ );
2410
+ }
1239
2411
  }
1240
2412
 
1241
2413
  // src/backends/rest.ts
1242
2414
  var RestBackend = class {
1243
2415
  constructor(url, apiKey, timeout = 3e4) {
1244
2416
  this._initialized = false;
1245
- this.baseUrl = url.replace(/\/$/, "");
1246
- this.apiKey = apiKey;
1247
- this.timeout = timeout;
2417
+ this.httpConfig = { baseUrl: url.replace(/\/$/, ""), apiKey, timeout };
1248
2418
  }
1249
2419
  async init() {
1250
2420
  if (this._initialized) {
1251
2421
  return;
1252
2422
  }
1253
2423
  try {
1254
- const response = await this.request("GET", "/health");
2424
+ const response = await request(this.httpConfig, "GET", "/health");
1255
2425
  if (response.error) {
1256
2426
  throw new Error(response.error.message);
1257
2427
  }
1258
2428
  this._initialized = true;
1259
2429
  } catch (error) {
1260
2430
  throw new ConnectionError(
1261
- `Failed to connect to VelesDB server at ${this.baseUrl}`,
2431
+ `Failed to connect to VelesDB server at ${this.httpConfig.baseUrl}`,
1262
2432
  error instanceof Error ? error : void 0
1263
2433
  );
1264
2434
  }
@@ -1266,316 +2436,242 @@ var RestBackend = class {
1266
2436
  isInitialized() {
1267
2437
  return this._initialized;
1268
2438
  }
2439
+ capabilities() {
2440
+ return REST_CAPABILITIES;
2441
+ }
2442
+ async close() {
2443
+ this._initialized = false;
2444
+ }
1269
2445
  ensureInitialized() {
1270
2446
  if (!this._initialized) {
1271
2447
  throw new ConnectionError("REST backend not initialized");
1272
2448
  }
1273
2449
  }
1274
- mapStatusToErrorCode(status) {
1275
- switch (status) {
1276
- case 400:
1277
- return "BAD_REQUEST";
1278
- case 401:
1279
- return "UNAUTHORIZED";
1280
- case 403:
1281
- return "FORBIDDEN";
1282
- case 404:
1283
- return "NOT_FOUND";
1284
- case 409:
1285
- return "CONFLICT";
1286
- case 429:
1287
- return "RATE_LIMITED";
1288
- case 500:
1289
- return "INTERNAL_ERROR";
1290
- case 503:
1291
- return "SERVICE_UNAVAILABLE";
1292
- default:
1293
- return "UNKNOWN_ERROR";
1294
- }
2450
+ // Collection CRUD
2451
+ async createCollection(n, c) {
2452
+ this.ensureInitialized();
2453
+ return createCollection(buildCrudTransport(this.httpConfig), n, c);
1295
2454
  }
1296
- extractErrorPayload(data) {
1297
- if (!data || typeof data !== "object") {
1298
- return {};
1299
- }
1300
- const payload = data;
1301
- const nestedError = payload.error && typeof payload.error === "object" ? payload.error : void 0;
1302
- const codeField = nestedError?.code ?? payload.code;
1303
- const code = typeof codeField === "string" ? codeField : void 0;
1304
- const messageField = nestedError?.message ?? payload.message ?? payload.error;
1305
- const message = typeof messageField === "string" ? messageField : void 0;
1306
- return { code, message };
2455
+ async deleteCollection(n) {
2456
+ this.ensureInitialized();
2457
+ return deleteCollection(buildCrudTransport(this.httpConfig), n);
1307
2458
  }
1308
- parseNodeId(value) {
1309
- if (value === null || value === void 0) {
1310
- return 0;
1311
- }
1312
- if (typeof value === "bigint") {
1313
- return value;
1314
- }
1315
- if (typeof value === "string") {
1316
- const num = Number(value);
1317
- return num > Number.MAX_SAFE_INTEGER ? BigInt(value) : num;
1318
- }
1319
- if (typeof value === "number") {
1320
- return value;
1321
- }
1322
- return 0;
2459
+ async getCollection(n) {
2460
+ this.ensureInitialized();
2461
+ return getCollection(buildCrudTransport(this.httpConfig), n);
1323
2462
  }
1324
- async request(method, path, body) {
1325
- const url = `${this.baseUrl}${path}`;
1326
- const headers = { "Content-Type": "application/json" };
1327
- if (this.apiKey) {
1328
- headers["Authorization"] = `Bearer ${this.apiKey}`;
1329
- }
1330
- const controller = new AbortController();
1331
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1332
- try {
1333
- const response = await fetch(url, {
1334
- method,
1335
- headers,
1336
- body: body ? JSON.stringify(body) : void 0,
1337
- signal: controller.signal
1338
- });
1339
- clearTimeout(timeoutId);
1340
- const data = await response.json().catch(() => ({}));
1341
- if (!response.ok) {
1342
- const errorPayload = this.extractErrorPayload(data);
1343
- return {
1344
- error: {
1345
- code: errorPayload.code ?? this.mapStatusToErrorCode(response.status),
1346
- message: errorPayload.message ?? `HTTP ${response.status}`
1347
- }
1348
- };
1349
- }
1350
- return { data };
1351
- } catch (error) {
1352
- clearTimeout(timeoutId);
1353
- if (error instanceof Error && error.name === "AbortError") {
1354
- throw new ConnectionError("Request timeout");
1355
- }
1356
- throw new ConnectionError(
1357
- `Request failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1358
- error instanceof Error ? error : void 0
1359
- );
1360
- }
2463
+ async listCollections() {
2464
+ this.ensureInitialized();
2465
+ return listCollections(buildCrudTransport(this.httpConfig));
1361
2466
  }
1362
- // ==========================================================================
1363
- // Transport adapters
1364
- // ==========================================================================
1365
- asCrudTransport() {
1366
- return {
1367
- requestJson: (m, p, b) => this.request(m, p, b)
1368
- };
2467
+ async upsert(c, d) {
2468
+ this.ensureInitialized();
2469
+ return upsert(buildCrudTransport(this.httpConfig), c, d);
1369
2470
  }
1370
- asSearchTransport() {
1371
- return {
1372
- requestJson: (m, p, b) => this.request(m, p, b),
1373
- sparseToRest: (sv) => sparseVectorToRestFormat(sv)
1374
- };
2471
+ async upsertBatch(c, d) {
2472
+ this.ensureInitialized();
2473
+ return upsertBatch(buildCrudTransport(this.httpConfig), c, d);
1375
2474
  }
1376
- asAgentMemoryTransport() {
1377
- return {
1378
- requestJson: (m, p, b) => this.request(m, p, b),
1379
- searchVectors: (c, e, k, f) => this.search(c, e, { k, filter: f })
1380
- };
2475
+ async delete(c, id) {
2476
+ this.ensureInitialized();
2477
+ return deletePoint(buildCrudTransport(this.httpConfig), c, id);
1381
2478
  }
1382
- asQueryTransport() {
1383
- return {
1384
- requestJson: (m, p, b) => this.request(m, p, b),
1385
- parseNodeId: (v) => this.parseNodeId(v)
1386
- };
2479
+ async get(c, id) {
2480
+ this.ensureInitialized();
2481
+ return get(buildCrudTransport(this.httpConfig), c, id);
1387
2482
  }
1388
- asStreamingTransport() {
1389
- return {
1390
- requestJson: (m, p, b) => this.request(m, p, b),
1391
- baseUrl: this.baseUrl,
1392
- apiKey: this.apiKey,
1393
- timeout: this.timeout,
1394
- parseRestPointId,
1395
- sparseVectorToRestFormat,
1396
- mapStatusToErrorCode: (s) => this.mapStatusToErrorCode(s),
1397
- extractErrorPayload: (d) => this.extractErrorPayload(d)
1398
- };
2483
+ async isEmpty(c) {
2484
+ this.ensureInitialized();
2485
+ return isEmpty(buildCrudTransport(this.httpConfig), c);
1399
2486
  }
1400
- // ==========================================================================
1401
- // Collection CRUD — delegates to crud-backend.ts
1402
- // ==========================================================================
1403
- async createCollection(name, config) {
2487
+ async flush(c) {
1404
2488
  this.ensureInitialized();
1405
- return createCollection(this.asCrudTransport(), name, config);
2489
+ return flush(buildCrudTransport(this.httpConfig), c);
1406
2490
  }
1407
- async deleteCollection(name) {
2491
+ // Additional REST endpoints (Sprint 2 Wave 4)
2492
+ async rebuildIndex(c) {
1408
2493
  this.ensureInitialized();
1409
- return deleteCollection(this.asCrudTransport(), name);
2494
+ return rebuildIndex(buildBaseTransport(this.httpConfig), c);
1410
2495
  }
1411
- async getCollection(name) {
2496
+ async getGuardrails() {
1412
2497
  this.ensureInitialized();
1413
- return getCollection(this.asCrudTransport(), name);
2498
+ return getGuardrails(buildBaseTransport(this.httpConfig));
1414
2499
  }
1415
- async listCollections() {
2500
+ async updateGuardrails(r) {
1416
2501
  this.ensureInitialized();
1417
- return listCollections(this.asCrudTransport());
2502
+ return updateGuardrails(buildBaseTransport(this.httpConfig), r);
1418
2503
  }
1419
- async insert(collection, doc) {
2504
+ async aggregate(q, p, o) {
1420
2505
  this.ensureInitialized();
1421
- return insert(this.asCrudTransport(), collection, doc);
2506
+ return aggregate(buildBaseTransport(this.httpConfig), q, p, o);
1422
2507
  }
1423
- async insertBatch(collection, docs) {
2508
+ async matchQuery(c, q, p, o) {
1424
2509
  this.ensureInitialized();
1425
- return insertBatch(this.asCrudTransport(), collection, docs);
2510
+ return matchQuery(buildBaseTransport(this.httpConfig), c, q, p, o);
1426
2511
  }
1427
- async delete(collection, id) {
2512
+ async removeEdge(c, id) {
1428
2513
  this.ensureInitialized();
1429
- return deletePoint(this.asCrudTransport(), collection, id);
2514
+ return removeEdge(buildBaseTransport(this.httpConfig), c, id);
1430
2515
  }
1431
- async get(collection, id) {
2516
+ async getEdgeCount(c) {
1432
2517
  this.ensureInitialized();
1433
- return get(this.asCrudTransport(), collection, id);
2518
+ return getEdgeCount(buildBaseTransport(this.httpConfig), c);
1434
2519
  }
1435
- async isEmpty(collection) {
2520
+ async listNodes(c) {
1436
2521
  this.ensureInitialized();
1437
- return isEmpty(this.asCrudTransport(), collection);
2522
+ return listNodes(buildBaseTransport(this.httpConfig), c);
1438
2523
  }
1439
- async flush(collection) {
2524
+ async getNodeEdges(c, id, o) {
1440
2525
  this.ensureInitialized();
1441
- return flush(this.asCrudTransport(), collection);
2526
+ return getNodeEdges(buildBaseTransport(this.httpConfig), c, id, o);
1442
2527
  }
1443
- async close() {
1444
- this._initialized = false;
2528
+ async getNodePayload(c, id) {
2529
+ this.ensureInitialized();
2530
+ return getNodePayload(buildBaseTransport(this.httpConfig), c, id);
2531
+ }
2532
+ async upsertNodePayload(c, id, p) {
2533
+ this.ensureInitialized();
2534
+ return upsertNodePayload(buildBaseTransport(this.httpConfig), c, id, p);
1445
2535
  }
1446
- // ==========================================================================
1447
- // Search — delegates to search-backend.ts
1448
- // ==========================================================================
2536
+ async graphSearch(c, r) {
2537
+ this.ensureInitialized();
2538
+ return graphSearch(buildBaseTransport(this.httpConfig), c, r);
2539
+ }
2540
+ // Search
1449
2541
  async search(c, q, o) {
1450
2542
  this.ensureInitialized();
1451
- return search(this.asSearchTransport(), c, q, o);
2543
+ return search(buildSearchTransport(this.httpConfig), c, q, o);
1452
2544
  }
1453
- async searchBatch(collection, searches) {
2545
+ async searchBatch(c, s) {
1454
2546
  this.ensureInitialized();
1455
- return searchBatch(this.asSearchTransport(), collection, searches);
2547
+ return searchBatch(buildSearchTransport(this.httpConfig), c, s);
1456
2548
  }
1457
2549
  async textSearch(c, q, o) {
1458
2550
  this.ensureInitialized();
1459
- return textSearch(this.asSearchTransport(), c, q, o);
2551
+ return textSearch(buildSearchTransport(this.httpConfig), c, q, o);
1460
2552
  }
1461
2553
  async hybridSearch(c, v, t, o) {
1462
2554
  this.ensureInitialized();
1463
- return hybridSearch(this.asSearchTransport(), c, v, t, o);
2555
+ return hybridSearch(buildSearchTransport(this.httpConfig), c, v, t, o);
1464
2556
  }
1465
2557
  async multiQuerySearch(c, v, o) {
1466
2558
  this.ensureInitialized();
1467
- return multiQuerySearch(this.asSearchTransport(), c, v, o);
2559
+ return multiQuerySearch(buildSearchTransport(this.httpConfig), c, v, o);
1468
2560
  }
1469
2561
  async searchIds(c, q, o) {
1470
2562
  this.ensureInitialized();
1471
- return searchIds(this.asSearchTransport(), c, q, o);
2563
+ return searchIds(buildSearchTransport(this.httpConfig), c, q, o);
1472
2564
  }
1473
- // ==========================================================================
1474
- // Query — delegates to query-backend.ts
1475
- // ==========================================================================
2565
+ // Query
1476
2566
  async query(c, q, p, o) {
1477
2567
  this.ensureInitialized();
1478
- return query(this.asQueryTransport(), c, q, p, o);
2568
+ return query(buildQueryTransport(this.httpConfig), c, q, p, o);
1479
2569
  }
1480
- async queryExplain(q, p) {
2570
+ async queryExplain(q, p, o) {
1481
2571
  this.ensureInitialized();
1482
- return queryExplain(this.asQueryTransport(), q, p);
2572
+ return queryExplain(buildQueryTransport(this.httpConfig), q, p, o);
1483
2573
  }
1484
- async collectionSanity(collection) {
2574
+ async collectionSanity(c) {
1485
2575
  this.ensureInitialized();
1486
- return collectionSanity(this.asQueryTransport(), collection);
2576
+ return collectionSanity(buildQueryTransport(this.httpConfig), c);
1487
2577
  }
1488
- // ==========================================================================
1489
- // Graph delegates to graph-backend.ts
1490
- // ==========================================================================
1491
- async addEdge(collection, edge) {
2578
+ // Scroll
2579
+ async scroll(c, r) {
1492
2580
  this.ensureInitialized();
1493
- return addEdge(this.asCrudTransport(), collection, edge);
2581
+ return scroll(buildCrudTransport(this.httpConfig), c, r);
1494
2582
  }
1495
- async getEdges(collection, options) {
2583
+ // Graph
2584
+ async addEdge(c, e) {
1496
2585
  this.ensureInitialized();
1497
- return getEdges(this.asCrudTransport(), collection, options);
2586
+ return addEdge(buildCrudTransport(this.httpConfig), c, e);
1498
2587
  }
1499
- async traverseGraph(collection, req) {
2588
+ async getEdges(c, o) {
1500
2589
  this.ensureInitialized();
1501
- return traverseGraph(this.asCrudTransport(), collection, req);
2590
+ return getEdges(buildCrudTransport(this.httpConfig), c, o);
1502
2591
  }
1503
- async getNodeDegree(collection, nodeId) {
2592
+ async traverseGraph(c, r) {
1504
2593
  this.ensureInitialized();
1505
- return getNodeDegree(this.asCrudTransport(), collection, nodeId);
2594
+ return traverseGraph(buildCrudTransport(this.httpConfig), c, r);
1506
2595
  }
1507
- async createGraphCollection(name, config) {
2596
+ async traverseParallel(c, r) {
1508
2597
  this.ensureInitialized();
1509
- return createGraphCollection(this.asCrudTransport(), name, config);
2598
+ return traverseParallel(buildCrudTransport(this.httpConfig), c, r);
1510
2599
  }
1511
- // ==========================================================================
1512
- // Index — delegates to index-backend.ts
1513
- // ==========================================================================
1514
- async createIndex(collection, options) {
2600
+ async getNodeDegree(c, id) {
1515
2601
  this.ensureInitialized();
1516
- return createIndex(this.asCrudTransport(), collection, options);
2602
+ return getNodeDegree(buildCrudTransport(this.httpConfig), c, id);
1517
2603
  }
1518
- async listIndexes(collection) {
2604
+ async createGraphCollection(n, c) {
1519
2605
  this.ensureInitialized();
1520
- return listIndexes(this.asCrudTransport(), collection);
2606
+ return createGraphCollection(buildCrudTransport(this.httpConfig), n, c);
1521
2607
  }
1522
- async hasIndex(collection, label, property) {
2608
+ // Index
2609
+ async createIndex(c, o) {
1523
2610
  this.ensureInitialized();
1524
- return hasIndex(this.asCrudTransport(), collection, label, property);
2611
+ return createIndex(buildCrudTransport(this.httpConfig), c, o);
1525
2612
  }
1526
- async dropIndex(collection, label, property) {
2613
+ async listIndexes(c) {
1527
2614
  this.ensureInitialized();
1528
- return dropIndex(this.asCrudTransport(), collection, label, property);
2615
+ return listIndexes(buildCrudTransport(this.httpConfig), c);
1529
2616
  }
1530
- // ==========================================================================
1531
- // Admin — delegates to admin-backend.ts
1532
- // ==========================================================================
1533
- async getCollectionStats(collection) {
2617
+ async hasIndex(c, l, p) {
1534
2618
  this.ensureInitialized();
1535
- return getCollectionStats(this.asCrudTransport(), collection);
2619
+ return hasIndex(buildCrudTransport(this.httpConfig), c, l, p);
1536
2620
  }
1537
- async analyzeCollection(collection) {
2621
+ async dropIndex(c, l, p) {
1538
2622
  this.ensureInitialized();
1539
- return analyzeCollection(this.asCrudTransport(), collection);
2623
+ return dropIndex(buildCrudTransport(this.httpConfig), c, l, p);
1540
2624
  }
1541
- async getCollectionConfig(collection) {
2625
+ // Admin
2626
+ async getCollectionStats(c) {
1542
2627
  this.ensureInitialized();
1543
- return getCollectionConfig(this.asCrudTransport(), collection);
2628
+ return getCollectionStats(buildCrudTransport(this.httpConfig), c);
1544
2629
  }
1545
- // ==========================================================================
1546
- // Streaming / PQ — delegates to streaming-backend.ts
1547
- // ==========================================================================
1548
- async trainPq(collection, options) {
2630
+ async analyzeCollection(c) {
1549
2631
  this.ensureInitialized();
1550
- return trainPq(this.asStreamingTransport(), collection, options);
2632
+ return analyzeCollection(buildCrudTransport(this.httpConfig), c);
1551
2633
  }
1552
- async streamInsert(collection, docs) {
2634
+ async getCollectionConfig(c) {
2635
+ this.ensureInitialized();
2636
+ return getCollectionConfig(buildCrudTransport(this.httpConfig), c);
2637
+ }
2638
+ // Streaming / PQ
2639
+ async trainPq(c, o) {
2640
+ this.ensureInitialized();
2641
+ return trainPq(buildStreamingTransport(this.httpConfig), c, o);
2642
+ }
2643
+ async streamInsert(c, d) {
2644
+ this.ensureInitialized();
2645
+ return streamInsert(buildStreamingTransport(this.httpConfig), c, d);
2646
+ }
2647
+ async streamUpsertPoints(c, d) {
1553
2648
  this.ensureInitialized();
1554
- return streamInsert(this.asStreamingTransport(), collection, docs);
2649
+ return streamUpsertPoints(buildStreamingTransport(this.httpConfig), c, d);
1555
2650
  }
1556
- // ==========================================================================
1557
- // Agent Memory — delegates to agent-memory-backend.ts
1558
- // ==========================================================================
1559
- async storeSemanticFact(collection, entry) {
2651
+ // Agent Memory
2652
+ async storeSemanticFact(c, e) {
1560
2653
  this.ensureInitialized();
1561
- return storeSemanticFact(this.asAgentMemoryTransport(), collection, entry);
2654
+ return storeSemanticFact(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, e);
1562
2655
  }
1563
- async searchSemanticMemory(collection, embedding, k = 5) {
1564
- return searchSemanticMemory(this.asAgentMemoryTransport(), collection, embedding, k);
2656
+ async searchSemanticMemory(c, e, k = 5) {
2657
+ this.ensureInitialized();
2658
+ return searchSemanticMemory(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, e, k);
1565
2659
  }
1566
- async recordEpisodicEvent(collection, event) {
2660
+ async recordEpisodicEvent(c, e) {
1567
2661
  this.ensureInitialized();
1568
- return recordEpisodicEvent(this.asAgentMemoryTransport(), collection, event);
2662
+ return recordEpisodicEvent(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, e);
1569
2663
  }
1570
- async recallEpisodicEvents(collection, embedding, k = 5) {
1571
- return recallEpisodicEvents(this.asAgentMemoryTransport(), collection, embedding, k);
2664
+ async recallEpisodicEvents(c, e, k = 5) {
2665
+ this.ensureInitialized();
2666
+ return recallEpisodicEvents(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, e, k);
1572
2667
  }
1573
- async storeProceduralPattern(collection, pattern) {
2668
+ async storeProceduralPattern(c, p) {
1574
2669
  this.ensureInitialized();
1575
- return storeProceduralPattern(this.asAgentMemoryTransport(), collection, pattern);
2670
+ return storeProceduralPattern(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, p);
1576
2671
  }
1577
- async matchProceduralPatterns(collection, embedding, k = 5) {
1578
- return matchProceduralPatterns(this.asAgentMemoryTransport(), collection, embedding, k);
2672
+ async matchProceduralPatterns(c, e, k = 5) {
2673
+ this.ensureInitialized();
2674
+ return matchProceduralPatterns(buildAgentMemoryTransport(this.httpConfig, (col, emb, opts) => this.search(col, emb, opts)), c, e, k);
1579
2675
  }
1580
2676
  };
1581
2677
 
@@ -1615,7 +2711,7 @@ var AgentMemoryClient = class {
1615
2711
  }
1616
2712
  };
1617
2713
 
1618
- // src/client.ts
2714
+ // src/client/validation.ts
1619
2715
  function requireNonEmptyString(value, label) {
1620
2716
  if (!value || typeof value !== "string") {
1621
2717
  throw new ValidationError(`${label} must be a non-empty string`);
@@ -1634,13 +2730,187 @@ function validateDocsBatch(docs, validateDoc) {
1634
2730
  validateDoc(doc);
1635
2731
  }
1636
2732
  }
2733
+ function validateDocument(doc, config) {
2734
+ if (doc.id === void 0 || doc.id === null) {
2735
+ throw new ValidationError("Document ID is required");
2736
+ }
2737
+ requireVector(doc.vector, "Vector");
2738
+ validateRestPointId(doc.id, config);
2739
+ }
2740
+ function validateRestPointId(id, config) {
2741
+ if (config.backend === "rest" && (typeof id !== "number" || !Number.isInteger(id) || id < 0 || id > Number.MAX_SAFE_INTEGER)) {
2742
+ throw new ValidationError(
2743
+ `REST backend requires numeric u64-compatible document IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER})`
2744
+ );
2745
+ }
2746
+ }
2747
+
2748
+ // src/client/search-methods.ts
2749
+ function search2(backend, collection, query3, options) {
2750
+ requireVector(query3, "Query");
2751
+ return backend.search(collection, query3, options);
2752
+ }
2753
+ function searchBatch2(backend, collection, searches) {
2754
+ if (!Array.isArray(searches)) {
2755
+ throw new ValidationError("Searches must be an array");
2756
+ }
2757
+ for (const s of searches) {
2758
+ requireVector(s.vector, "Each search vector");
2759
+ }
2760
+ return backend.searchBatch(collection, searches);
2761
+ }
2762
+ function textSearch2(backend, collection, query3, options) {
2763
+ requireNonEmptyString(query3, "Query");
2764
+ return backend.textSearch(collection, query3, options);
2765
+ }
2766
+ function hybridSearch2(backend, collection, vector, textQuery, options) {
2767
+ requireVector(vector, "Vector");
2768
+ requireNonEmptyString(textQuery, "Text query");
2769
+ return backend.hybridSearch(collection, vector, textQuery, options);
2770
+ }
2771
+ function multiQuerySearch2(backend, collection, vectors, options) {
2772
+ if (!Array.isArray(vectors) || vectors.length === 0) {
2773
+ throw new ValidationError("Vectors must be a non-empty array");
2774
+ }
2775
+ for (const v of vectors) {
2776
+ requireVector(v, "Each vector");
2777
+ }
2778
+ return backend.multiQuerySearch(collection, vectors, options);
2779
+ }
2780
+ function trainPq2(backend, collection, options) {
2781
+ return backend.trainPq(collection, options);
2782
+ }
2783
+ function streamInsert2(backend, config, collection, docs) {
2784
+ validateDocsBatch(docs, (doc) => validateDocument(doc, config));
2785
+ return backend.streamInsert(collection, docs);
2786
+ }
2787
+ function streamUpsertPoints2(backend, config, collection, docs) {
2788
+ validateDocsBatch(docs, (doc) => validateDocument(doc, config));
2789
+ return backend.streamUpsertPoints(collection, docs);
2790
+ }
2791
+ function scroll2(backend, collection, request2) {
2792
+ requireNonEmptyString(collection, "Collection name");
2793
+ if (request2?.batchSize !== void 0) {
2794
+ if (request2.batchSize < 1 || request2.batchSize > 1e4) {
2795
+ throw new ValidationError("batchSize must be between 1 and 10000");
2796
+ }
2797
+ }
2798
+ return backend.scroll(collection, request2);
2799
+ }
2800
+ function searchIds2(backend, collection, query3, options) {
2801
+ return backend.searchIds(collection, query3, options);
2802
+ }
2803
+ function query2(backend, collection, queryString, params, options) {
2804
+ requireNonEmptyString(collection, "Collection name");
2805
+ requireNonEmptyString(queryString, "Query string");
2806
+ return backend.query(collection, queryString, params, options);
2807
+ }
2808
+ function queryExplain2(backend, queryString, params, options) {
2809
+ requireNonEmptyString(queryString, "Query string");
2810
+ return backend.queryExplain(queryString, params, options);
2811
+ }
2812
+ function collectionSanity2(backend, collection) {
2813
+ requireNonEmptyString(collection, "Collection name");
2814
+ return backend.collectionSanity(collection);
2815
+ }
2816
+ function getCollectionStats2(backend, collection) {
2817
+ return backend.getCollectionStats(collection);
2818
+ }
2819
+ function analyzeCollection2(backend, collection) {
2820
+ return backend.analyzeCollection(collection);
2821
+ }
2822
+ function getCollectionConfig2(backend, collection) {
2823
+ return backend.getCollectionConfig(collection);
2824
+ }
2825
+ function rebuildIndex2(backend, collection) {
2826
+ requireNonEmptyString(collection, "Collection");
2827
+ return backend.rebuildIndex(collection);
2828
+ }
2829
+ function getGuardrails2(backend) {
2830
+ return backend.getGuardrails();
2831
+ }
2832
+ function updateGuardrails2(backend, req) {
2833
+ return backend.updateGuardrails(req);
2834
+ }
2835
+ function aggregate2(backend, queryString, params, options) {
2836
+ requireNonEmptyString(queryString, "Query string");
2837
+ return backend.aggregate(queryString, params, options);
2838
+ }
2839
+
2840
+ // src/client/graph-methods.ts
2841
+ function addEdge2(backend, collection, edge) {
2842
+ if (!edge.label || typeof edge.label !== "string") {
2843
+ throw new ValidationError("Edge label is required and must be a string");
2844
+ }
2845
+ if (typeof edge.source !== "number" || typeof edge.target !== "number") {
2846
+ throw new ValidationError("Edge source and target must be numbers");
2847
+ }
2848
+ return backend.addEdge(collection, edge);
2849
+ }
2850
+ function getEdges2(backend, collection, options) {
2851
+ return backend.getEdges(collection, options);
2852
+ }
2853
+ function traverseGraph2(backend, collection, request2) {
2854
+ if (typeof request2.source !== "number") {
2855
+ throw new ValidationError("Source node ID must be a number");
2856
+ }
2857
+ if (request2.strategy && !["bfs", "dfs"].includes(request2.strategy)) {
2858
+ throw new ValidationError("Strategy must be 'bfs' or 'dfs'");
2859
+ }
2860
+ return backend.traverseGraph(collection, request2);
2861
+ }
2862
+ function traverseParallel2(backend, collection, request2) {
2863
+ if (!Array.isArray(request2.sources) || request2.sources.length === 0) {
2864
+ throw new ValidationError("At least one source node ID is required");
2865
+ }
2866
+ return backend.traverseParallel(collection, request2);
2867
+ }
2868
+ function getNodeDegree2(backend, collection, nodeId) {
2869
+ if (typeof nodeId !== "number") {
2870
+ throw new ValidationError("Node ID must be a number");
2871
+ }
2872
+ return backend.getNodeDegree(collection, nodeId);
2873
+ }
2874
+ function createGraphCollection2(backend, name, config) {
2875
+ requireNonEmptyString(name, "Collection name");
2876
+ return backend.createGraphCollection(name, config);
2877
+ }
2878
+ function matchQuery2(backend, collection, queryString, params, options) {
2879
+ requireNonEmptyString(collection, "Collection");
2880
+ requireNonEmptyString(queryString, "Query string");
2881
+ return backend.matchQuery(collection, queryString, params, options);
2882
+ }
2883
+ function removeEdge2(backend, collection, edgeId) {
2884
+ requireNonEmptyString(collection, "Collection");
2885
+ return backend.removeEdge(collection, edgeId);
2886
+ }
2887
+ function getEdgeCount2(backend, collection) {
2888
+ requireNonEmptyString(collection, "Collection");
2889
+ return backend.getEdgeCount(collection);
2890
+ }
2891
+ function listNodes2(backend, collection) {
2892
+ requireNonEmptyString(collection, "Collection");
2893
+ return backend.listNodes(collection);
2894
+ }
2895
+ function getNodeEdges2(backend, collection, nodeId, options) {
2896
+ requireNonEmptyString(collection, "Collection");
2897
+ return backend.getNodeEdges(collection, nodeId, options);
2898
+ }
2899
+ function getNodePayload2(backend, collection, nodeId) {
2900
+ requireNonEmptyString(collection, "Collection");
2901
+ return backend.getNodePayload(collection, nodeId);
2902
+ }
2903
+ function upsertNodePayload2(backend, collection, nodeId, payload) {
2904
+ requireNonEmptyString(collection, "Collection");
2905
+ return backend.upsertNodePayload(collection, nodeId, payload);
2906
+ }
2907
+ function graphSearch2(backend, collection, request2) {
2908
+ requireNonEmptyString(collection, "Collection");
2909
+ return backend.graphSearch(collection, request2);
2910
+ }
2911
+
2912
+ // src/client.ts
1637
2913
  var VelesDB = class {
1638
- /**
1639
- * Create a new VelesDB client
1640
- *
1641
- * @param config - Client configuration
1642
- * @throws {ValidationError} If configuration is invalid
1643
- */
1644
2914
  constructor(config) {
1645
2915
  this.initialized = false;
1646
2916
  this.validateConfig(config);
@@ -1668,10 +2938,7 @@ var VelesDB = class {
1668
2938
  throw new ValidationError(`Unknown backend: ${config.backend}`);
1669
2939
  }
1670
2940
  }
1671
- /**
1672
- * Initialize the client
1673
- * Must be called before any other operations
1674
- */
2941
+ /** Initialize the client. Must be called before any other operations. */
1675
2942
  async init() {
1676
2943
  if (this.initialized) {
1677
2944
  return;
@@ -1679,9 +2946,7 @@ var VelesDB = class {
1679
2946
  await this.backend.init();
1680
2947
  this.initialized = true;
1681
2948
  }
1682
- /**
1683
- * Check if client is initialized
1684
- */
2949
+ /** Check if client is initialized. */
1685
2950
  isInitialized() {
1686
2951
  return this.initialized;
1687
2952
  }
@@ -1690,12 +2955,9 @@ var VelesDB = class {
1690
2955
  throw new ValidationError("Client not initialized. Call init() first.");
1691
2956
  }
1692
2957
  }
1693
- /**
1694
- * Create a new collection
1695
- *
1696
- * @param name - Collection name
1697
- * @param config - Collection configuration
1698
- */
2958
+ // ========================================================================
2959
+ // Collection CRUD
2960
+ // ========================================================================
1699
2961
  async createCollection(name, config) {
1700
2962
  this.ensureInitialized();
1701
2963
  requireNonEmptyString(name, "Collection name");
@@ -1705,329 +2967,149 @@ var VelesDB = class {
1705
2967
  }
1706
2968
  await this.backend.createCollection(name, config);
1707
2969
  }
1708
- /**
1709
- * Create a metadata-only collection (no vectors, just payload data)
1710
- *
1711
- * Useful for storing reference data that can be JOINed with vector collections.
1712
- *
1713
- * @param name - Collection name
1714
- *
1715
- * @example
1716
- * ```typescript
1717
- * await db.createMetadataCollection('products');
1718
- * await db.insertMetadata('products', { id: 'P001', name: 'Widget', price: 99 });
1719
- * ```
1720
- */
1721
2970
  async createMetadataCollection(name) {
1722
2971
  this.ensureInitialized();
1723
2972
  requireNonEmptyString(name, "Collection name");
1724
2973
  await this.backend.createCollection(name, { collectionType: "metadata_only" });
1725
2974
  }
1726
- /**
1727
- * Delete a collection
1728
- *
1729
- * @param name - Collection name
1730
- */
1731
2975
  async deleteCollection(name) {
1732
2976
  this.ensureInitialized();
1733
2977
  await this.backend.deleteCollection(name);
1734
2978
  }
1735
- /**
1736
- * Get collection information
1737
- *
1738
- * @param name - Collection name
1739
- * @returns Collection info or null if not found
1740
- */
1741
2979
  async getCollection(name) {
1742
2980
  this.ensureInitialized();
1743
2981
  return this.backend.getCollection(name);
1744
2982
  }
1745
- /**
1746
- * List all collections
1747
- *
1748
- * @returns Array of collections
1749
- */
1750
2983
  async listCollections() {
1751
2984
  this.ensureInitialized();
1752
2985
  return this.backend.listCollections();
1753
2986
  }
1754
- /**
1755
- * Insert a vector document
1756
- *
1757
- * @param collection - Collection name
1758
- * @param doc - Document to insert
1759
- */
1760
- async insert(collection, doc) {
2987
+ // ========================================================================
2988
+ // Point CRUD
2989
+ // ========================================================================
2990
+ async upsert(collection, doc) {
1761
2991
  this.ensureInitialized();
1762
- this.validateDocument(doc);
1763
- await this.backend.insert(collection, doc);
2992
+ validateDocument(doc, this.config);
2993
+ await this.backend.upsert(collection, doc);
1764
2994
  }
1765
- /**
1766
- * Insert multiple vector documents
1767
- *
1768
- * @param collection - Collection name
1769
- * @param docs - Documents to insert
1770
- */
1771
- async insertBatch(collection, docs) {
2995
+ async upsertBatch(collection, docs) {
1772
2996
  this.ensureInitialized();
1773
- validateDocsBatch(docs, (doc) => this.validateDocument(doc));
1774
- await this.backend.insertBatch(collection, docs);
2997
+ validateDocsBatch(docs, (doc) => validateDocument(doc, this.config));
2998
+ await this.backend.upsertBatch(collection, docs);
1775
2999
  }
1776
- validateDocument(doc) {
1777
- if (doc.id === void 0 || doc.id === null) {
1778
- throw new ValidationError("Document ID is required");
1779
- }
1780
- requireVector(doc.vector, "Vector");
1781
- this.validateRestPointId(doc.id);
3000
+ async delete(collection, id) {
3001
+ this.ensureInitialized();
3002
+ validateRestPointId(id, this.config);
3003
+ return this.backend.delete(collection, id);
1782
3004
  }
1783
- validateRestPointId(id) {
1784
- if (this.config.backend === "rest" && (typeof id !== "number" || !Number.isInteger(id) || id < 0 || id > Number.MAX_SAFE_INTEGER)) {
1785
- throw new ValidationError(
1786
- `REST backend requires numeric u64-compatible document IDs in JS safe integer range (0..${Number.MAX_SAFE_INTEGER})`
1787
- );
1788
- }
3005
+ async get(collection, id) {
3006
+ this.ensureInitialized();
3007
+ validateRestPointId(id, this.config);
3008
+ return this.backend.get(collection, id);
1789
3009
  }
1790
- /**
1791
- * Search for similar vectors
1792
- *
1793
- * @param collection - Collection name
1794
- * @param query - Query vector
1795
- * @param options - Search options
1796
- * @returns Search results sorted by relevance
1797
- */
1798
- async search(collection, query2, options) {
3010
+ async isEmpty(collection) {
1799
3011
  this.ensureInitialized();
1800
- requireVector(query2, "Query");
1801
- return this.backend.search(collection, query2, options);
3012
+ return this.backend.isEmpty(collection);
1802
3013
  }
1803
- /**
1804
- * Search for multiple vectors in parallel
1805
- *
1806
- * @param collection - Collection name
1807
- * @param searches - List of search queries
1808
- * @returns List of search results for each query
1809
- */
1810
- async searchBatch(collection, searches) {
3014
+ async flush(collection) {
1811
3015
  this.ensureInitialized();
1812
- if (!Array.isArray(searches)) {
1813
- throw new ValidationError("Searches must be an array");
1814
- }
1815
- for (const s of searches) {
1816
- requireVector(s.vector, "Each search vector");
3016
+ await this.backend.flush(collection);
3017
+ }
3018
+ async close() {
3019
+ if (this.initialized) {
3020
+ await this.backend.close();
3021
+ this.initialized = false;
1817
3022
  }
1818
- return this.backend.searchBatch(collection, searches);
1819
3023
  }
1820
- /**
1821
- * Delete a vector by ID
1822
- *
1823
- * @param collection - Collection name
1824
- * @param id - Document ID
1825
- * @returns true if deleted, false if not found
1826
- */
1827
- async delete(collection, id) {
3024
+ // ========================================================================
3025
+ // Search & Query -- delegates to client/search-methods.ts
3026
+ // ========================================================================
3027
+ async search(collection, query3, options) {
1828
3028
  this.ensureInitialized();
1829
- this.validateRestPointId(id);
1830
- return this.backend.delete(collection, id);
3029
+ return search2(this.backend, collection, query3, options);
1831
3030
  }
1832
- /**
1833
- * Get a vector by ID
1834
- *
1835
- * @param collection - Collection name
1836
- * @param id - Document ID
1837
- * @returns Document or null if not found
1838
- */
1839
- async get(collection, id) {
3031
+ async searchBatch(collection, searches) {
1840
3032
  this.ensureInitialized();
1841
- this.validateRestPointId(id);
1842
- return this.backend.get(collection, id);
3033
+ return searchBatch2(this.backend, collection, searches);
1843
3034
  }
1844
- /**
1845
- * Perform full-text search using BM25
1846
- *
1847
- * @param collection - Collection name
1848
- * @param query - Text query
1849
- * @param options - Search options (k, filter)
1850
- * @returns Search results sorted by BM25 score
1851
- */
1852
- async textSearch(collection, query2, options) {
3035
+ async textSearch(collection, query3, options) {
1853
3036
  this.ensureInitialized();
1854
- requireNonEmptyString(query2, "Query");
1855
- return this.backend.textSearch(collection, query2, options);
3037
+ return textSearch2(this.backend, collection, query3, options);
1856
3038
  }
1857
- /**
1858
- * Perform hybrid search combining vector similarity and BM25 text search
1859
- *
1860
- * @param collection - Collection name
1861
- * @param vector - Query vector
1862
- * @param textQuery - Text query for BM25
1863
- * @param options - Search options (k, vectorWeight, filter)
1864
- * @returns Search results sorted by fused score
1865
- */
1866
3039
  async hybridSearch(collection, vector, textQuery, options) {
1867
3040
  this.ensureInitialized();
1868
- requireVector(vector, "Vector");
1869
- requireNonEmptyString(textQuery, "Text query");
1870
- return this.backend.hybridSearch(collection, vector, textQuery, options);
3041
+ return hybridSearch2(this.backend, collection, vector, textQuery, options);
3042
+ }
3043
+ async multiQuerySearch(collection, vectors, options) {
3044
+ this.ensureInitialized();
3045
+ return multiQuerySearch2(this.backend, collection, vectors, options);
1871
3046
  }
1872
- /**
1873
- * Execute a VelesQL multi-model query (EPIC-031 US-011)
1874
- *
1875
- * Supports hybrid vector + graph queries with VelesQL syntax.
1876
- *
1877
- * @param collection - Collection name
1878
- * @param queryString - VelesQL query string
1879
- * @param params - Query parameters (vectors, scalars)
1880
- * @param options - Query options (timeout, streaming)
1881
- * @returns Query response with results and execution stats
1882
- *
1883
- * @example
1884
- * ```typescript
1885
- * const response = await db.query('docs', `
1886
- * MATCH (d:Doc) WHERE vector NEAR $q LIMIT 20
1887
- * `, { q: queryVector });
1888
- *
1889
- * for (const r of response.results) {
1890
- * console.log(`ID ${r.id}, title: ${r.title}`);
1891
- * }
1892
- * ```
1893
- */
1894
3047
  async query(collection, queryString, params, options) {
1895
3048
  this.ensureInitialized();
1896
- requireNonEmptyString(collection, "Collection name");
1897
- requireNonEmptyString(queryString, "Query string");
1898
- return this.backend.query(collection, queryString, params, options);
3049
+ return query2(this.backend, collection, queryString, params, options);
1899
3050
  }
1900
- /**
1901
- * Explain the execution plan for a VelesQL query without running it
1902
- *
1903
- * @param queryString - VelesQL query string to explain
1904
- * @param params - Optional query parameters (vectors, scalars)
1905
- * @returns Explain response with the query execution plan
1906
- */
1907
- async queryExplain(queryString, params) {
3051
+ async queryExplain(queryString, params, options) {
1908
3052
  this.ensureInitialized();
1909
- requireNonEmptyString(queryString, "Query string");
1910
- return this.backend.queryExplain(queryString, params);
3053
+ return queryExplain2(this.backend, queryString, params, options);
1911
3054
  }
1912
3055
  async collectionSanity(collection) {
1913
3056
  this.ensureInitialized();
1914
- requireNonEmptyString(collection, "Collection name");
1915
- return this.backend.collectionSanity(collection);
3057
+ return collectionSanity2(this.backend, collection);
1916
3058
  }
1917
- /**
1918
- * Multi-query fusion search combining results from multiple query vectors
1919
- *
1920
- * Ideal for RAG pipelines using Multiple Query Generation (MQG).
1921
- *
1922
- * @param collection - Collection name
1923
- * @param vectors - Array of query vectors
1924
- * @param options - Search options (k, fusion strategy, fusionParams, filter)
1925
- * @returns Fused search results
1926
- *
1927
- * @example
1928
- * ```typescript
1929
- * // RRF fusion (default)
1930
- * const results = await db.multiQuerySearch('docs', [emb1, emb2, emb3], {
1931
- * k: 10,
1932
- * fusion: 'rrf',
1933
- * fusionParams: { k: 60 }
1934
- * });
1935
- *
1936
- * // Weighted fusion
1937
- * const results = await db.multiQuerySearch('docs', [emb1, emb2], {
1938
- * k: 10,
1939
- * fusion: 'weighted',
1940
- * fusionParams: { avgWeight: 0.6, maxWeight: 0.3, hitWeight: 0.1 }
1941
- * });
1942
- * ```
1943
- */
1944
- async multiQuerySearch(collection, vectors, options) {
3059
+ async scroll(collection, request2) {
1945
3060
  this.ensureInitialized();
1946
- if (!Array.isArray(vectors) || vectors.length === 0) {
1947
- throw new ValidationError("Vectors must be a non-empty array");
1948
- }
1949
- for (const v of vectors) {
1950
- requireVector(v, "Each vector");
1951
- }
1952
- return this.backend.multiQuerySearch(collection, vectors, options);
3061
+ return scroll2(this.backend, collection, request2);
1953
3062
  }
1954
- /**
1955
- * Train Product Quantization on a collection
1956
- *
1957
- * @param collection - Collection name
1958
- * @param options - PQ training options (m, k, opq)
1959
- * @returns Server response message
1960
- */
1961
3063
  async trainPq(collection, options) {
1962
3064
  this.ensureInitialized();
1963
- return this.backend.trainPq(collection, options);
3065
+ return trainPq2(this.backend, collection, options);
1964
3066
  }
1965
- /**
1966
- * Stream-insert documents with backpressure support
1967
- *
1968
- * Sends documents sequentially to respect server backpressure.
1969
- * Throws BackpressureError on 429 responses.
1970
- *
1971
- * @param collection - Collection name
1972
- * @param docs - Documents to insert
1973
- */
1974
3067
  async streamInsert(collection, docs) {
1975
3068
  this.ensureInitialized();
1976
- validateDocsBatch(docs, (doc) => this.validateDocument(doc));
1977
- await this.backend.streamInsert(collection, docs);
3069
+ return streamInsert2(this.backend, this.config, collection, docs);
1978
3070
  }
1979
- /**
1980
- * Check if a collection is empty
1981
- *
1982
- * @param collection - Collection name
1983
- * @returns true if empty, false otherwise
1984
- */
1985
- async isEmpty(collection) {
3071
+ async streamUpsertPoints(collection, docs) {
1986
3072
  this.ensureInitialized();
1987
- return this.backend.isEmpty(collection);
3073
+ return streamUpsertPoints2(this.backend, this.config, collection, docs);
1988
3074
  }
1989
- /**
1990
- * Flush pending changes to disk
1991
- *
1992
- * @param collection - Collection name
1993
- */
1994
- async flush(collection) {
3075
+ async searchIds(collection, query3, options) {
1995
3076
  this.ensureInitialized();
1996
- await this.backend.flush(collection);
3077
+ return searchIds2(this.backend, collection, query3, options);
1997
3078
  }
1998
- /**
1999
- * Close the client and release resources
2000
- */
2001
- async close() {
2002
- if (this.initialized) {
2003
- await this.backend.close();
2004
- this.initialized = false;
2005
- }
3079
+ // ========================================================================
3080
+ // Admin / Stats -- delegates to client/search-methods.ts
3081
+ // ========================================================================
3082
+ async rebuildIndex(collection) {
3083
+ this.ensureInitialized();
3084
+ return rebuildIndex2(this.backend, collection);
2006
3085
  }
2007
- /**
2008
- * Get the current backend type
2009
- */
2010
- get backendType() {
2011
- return this.config.backend;
3086
+ async getGuardrails() {
3087
+ this.ensureInitialized();
3088
+ return getGuardrails2(this.backend);
3089
+ }
3090
+ async updateGuardrails(req) {
3091
+ this.ensureInitialized();
3092
+ return updateGuardrails2(this.backend, req);
3093
+ }
3094
+ async aggregate(queryString, params, options) {
3095
+ this.ensureInitialized();
3096
+ return aggregate2(this.backend, queryString, params, options);
3097
+ }
3098
+ async getCollectionStats(collection) {
3099
+ this.ensureInitialized();
3100
+ return getCollectionStats2(this.backend, collection);
3101
+ }
3102
+ async analyzeCollection(collection) {
3103
+ this.ensureInitialized();
3104
+ return analyzeCollection2(this.backend, collection);
3105
+ }
3106
+ async getCollectionConfig(collection) {
3107
+ this.ensureInitialized();
3108
+ return getCollectionConfig2(this.backend, collection);
2012
3109
  }
2013
3110
  // ========================================================================
2014
3111
  // Index Management (EPIC-009)
2015
3112
  // ========================================================================
2016
- /**
2017
- * Create a property index for O(1) equality lookups or O(log n) range queries
2018
- *
2019
- * @param collection - Collection name
2020
- * @param options - Index configuration (label, property, indexType)
2021
- *
2022
- * @example
2023
- * ```typescript
2024
- * // Create hash index for fast email lookups
2025
- * await db.createIndex('users', { label: 'Person', property: 'email' });
2026
- *
2027
- * // Create range index for timestamp queries
2028
- * await db.createIndex('events', { label: 'Event', property: 'timestamp', indexType: 'range' });
2029
- * ```
2030
- */
2031
3113
  async createIndex(collection, options) {
2032
3114
  this.ensureInitialized();
2033
3115
  if (!options.label || !options.property) {
@@ -2035,208 +3117,89 @@ var VelesDB = class {
2035
3117
  }
2036
3118
  await this.backend.createIndex(collection, options);
2037
3119
  }
2038
- /**
2039
- * List all indexes on a collection
2040
- *
2041
- * @param collection - Collection name
2042
- * @returns Array of index information
2043
- */
2044
3120
  async listIndexes(collection) {
2045
3121
  this.ensureInitialized();
2046
3122
  return this.backend.listIndexes(collection);
2047
3123
  }
2048
- /**
2049
- * Check if an index exists
2050
- *
2051
- * @param collection - Collection name
2052
- * @param label - Node label
2053
- * @param property - Property name
2054
- * @returns true if index exists
2055
- */
2056
3124
  async hasIndex(collection, label, property) {
2057
3125
  this.ensureInitialized();
2058
3126
  return this.backend.hasIndex(collection, label, property);
2059
3127
  }
2060
- /**
2061
- * Drop an index
2062
- *
2063
- * @param collection - Collection name
2064
- * @param label - Node label
2065
- * @param property - Property name
2066
- * @returns true if index was dropped, false if it didn't exist
2067
- */
2068
3128
  async dropIndex(collection, label, property) {
2069
3129
  this.ensureInitialized();
2070
3130
  return this.backend.dropIndex(collection, label, property);
2071
3131
  }
2072
3132
  // ========================================================================
2073
- // Knowledge Graph (EPIC-016 US-041)
3133
+ // Knowledge Graph -- delegates to client/graph-methods.ts
2074
3134
  // ========================================================================
2075
- /**
2076
- * Add an edge to the collection's knowledge graph
2077
- *
2078
- * @param collection - Collection name
2079
- * @param edge - Edge to add (id, source, target, label, properties)
2080
- *
2081
- * @example
2082
- * ```typescript
2083
- * await db.addEdge('social', {
2084
- * id: 1,
2085
- * source: 100,
2086
- * target: 200,
2087
- * label: 'FOLLOWS',
2088
- * properties: { since: '2024-01-01' }
2089
- * });
2090
- * ```
2091
- */
2092
3135
  async addEdge(collection, edge) {
2093
3136
  this.ensureInitialized();
2094
- if (!edge.label || typeof edge.label !== "string") {
2095
- throw new ValidationError("Edge label is required and must be a string");
2096
- }
2097
- if (typeof edge.source !== "number" || typeof edge.target !== "number") {
2098
- throw new ValidationError("Edge source and target must be numbers");
2099
- }
2100
- await this.backend.addEdge(collection, edge);
3137
+ return addEdge2(this.backend, collection, edge);
2101
3138
  }
2102
- /**
2103
- * Get edges from the collection's knowledge graph
2104
- *
2105
- * @param collection - Collection name
2106
- * @param options - Query options (filter by label)
2107
- * @returns Array of edges
2108
- *
2109
- * @example
2110
- * ```typescript
2111
- * // Get all edges with label "FOLLOWS"
2112
- * const edges = await db.getEdges('social', { label: 'FOLLOWS' });
2113
- * ```
2114
- */
2115
3139
  async getEdges(collection, options) {
2116
3140
  this.ensureInitialized();
2117
- return this.backend.getEdges(collection, options);
3141
+ return getEdges2(this.backend, collection, options);
2118
3142
  }
2119
- // ========================================================================
2120
- // Graph Traversal (EPIC-016 US-050)
2121
- // ========================================================================
2122
- /**
2123
- * Traverse the graph using BFS or DFS from a source node
2124
- *
2125
- * @param collection - Collection name
2126
- * @param request - Traversal request options
2127
- * @returns Traversal response with results and stats
2128
- *
2129
- * @example
2130
- * ```typescript
2131
- * // BFS traversal from node 100
2132
- * const result = await db.traverseGraph('social', {
2133
- * source: 100,
2134
- * strategy: 'bfs',
2135
- * maxDepth: 3,
2136
- * limit: 100,
2137
- * relTypes: ['FOLLOWS', 'KNOWS']
2138
- * });
2139
- *
2140
- * for (const node of result.results) {
2141
- * console.log(`Reached node ${node.targetId} at depth ${node.depth}`);
2142
- * }
2143
- * ```
2144
- */
2145
- async traverseGraph(collection, request) {
3143
+ async traverseGraph(collection, request2) {
2146
3144
  this.ensureInitialized();
2147
- if (typeof request.source !== "number") {
2148
- throw new ValidationError("Source node ID must be a number");
2149
- }
2150
- if (request.strategy && !["bfs", "dfs"].includes(request.strategy)) {
2151
- throw new ValidationError("Strategy must be 'bfs' or 'dfs'");
2152
- }
2153
- return this.backend.traverseGraph(collection, request);
3145
+ return traverseGraph2(this.backend, collection, request2);
3146
+ }
3147
+ async traverseParallel(collection, request2) {
3148
+ this.ensureInitialized();
3149
+ return traverseParallel2(this.backend, collection, request2);
2154
3150
  }
2155
- /**
2156
- * Get the in-degree and out-degree of a node
2157
- *
2158
- * @param collection - Collection name
2159
- * @param nodeId - Node ID
2160
- * @returns Degree response with inDegree and outDegree
2161
- *
2162
- * @example
2163
- * ```typescript
2164
- * const degree = await db.getNodeDegree('social', 100);
2165
- * console.log(`In: ${degree.inDegree}, Out: ${degree.outDegree}`);
2166
- * ```
2167
- */
2168
3151
  async getNodeDegree(collection, nodeId) {
2169
3152
  this.ensureInitialized();
2170
- if (typeof nodeId !== "number") {
2171
- throw new ValidationError("Node ID must be a number");
2172
- }
2173
- return this.backend.getNodeDegree(collection, nodeId);
3153
+ return getNodeDegree2(this.backend, collection, nodeId);
2174
3154
  }
2175
- // ========================================================================
2176
- // Graph Collection Management (Phase 8)
2177
- // ========================================================================
2178
- /**
2179
- * Create a graph collection
2180
- *
2181
- * @param name - Collection name
2182
- * @param config - Optional graph collection configuration
2183
- */
2184
3155
  async createGraphCollection(name, config) {
2185
3156
  this.ensureInitialized();
2186
- requireNonEmptyString(name, "Collection name");
2187
- await this.backend.createGraphCollection(name, config);
3157
+ return createGraphCollection2(this.backend, name, config);
2188
3158
  }
2189
- /**
2190
- * Get collection statistics (requires prior analyze)
2191
- *
2192
- * @param collection - Collection name
2193
- * @returns Statistics or null if not yet analyzed
2194
- */
2195
- async getCollectionStats(collection) {
3159
+ async matchQuery(collection, queryString, params, options) {
2196
3160
  this.ensureInitialized();
2197
- return this.backend.getCollectionStats(collection);
3161
+ return matchQuery2(this.backend, collection, queryString, params, options);
2198
3162
  }
2199
- /**
2200
- * Analyze a collection to compute statistics
2201
- *
2202
- * @param collection - Collection name
2203
- * @returns Computed statistics
2204
- */
2205
- async analyzeCollection(collection) {
3163
+ async removeEdge(collection, edgeId) {
2206
3164
  this.ensureInitialized();
2207
- return this.backend.analyzeCollection(collection);
3165
+ return removeEdge2(this.backend, collection, edgeId);
2208
3166
  }
2209
- /**
2210
- * Get collection configuration
2211
- *
2212
- * @param collection - Collection name
2213
- * @returns Collection configuration details
2214
- */
2215
- async getCollectionConfig(collection) {
3167
+ async getEdgeCount(collection) {
2216
3168
  this.ensureInitialized();
2217
- return this.backend.getCollectionConfig(collection);
3169
+ return getEdgeCount2(this.backend, collection);
2218
3170
  }
2219
- /**
2220
- * Search returning only IDs and scores (lightweight)
2221
- *
2222
- * @param collection - Collection name
2223
- * @param query - Query vector
2224
- * @param options - Search options
2225
- * @returns Array of id/score pairs
2226
- */
2227
- async searchIds(collection, query2, options) {
3171
+ async listNodes(collection) {
3172
+ this.ensureInitialized();
3173
+ return listNodes2(this.backend, collection);
3174
+ }
3175
+ async getNodeEdges(collection, nodeId, options) {
3176
+ this.ensureInitialized();
3177
+ return getNodeEdges2(this.backend, collection, nodeId, options);
3178
+ }
3179
+ async getNodePayload(collection, nodeId) {
3180
+ this.ensureInitialized();
3181
+ return getNodePayload2(this.backend, collection, nodeId);
3182
+ }
3183
+ async upsertNodePayload(collection, nodeId, payload) {
3184
+ this.ensureInitialized();
3185
+ return upsertNodePayload2(this.backend, collection, nodeId, payload);
3186
+ }
3187
+ async graphSearch(collection, request2) {
2228
3188
  this.ensureInitialized();
2229
- return this.backend.searchIds(collection, query2, options);
3189
+ return graphSearch2(this.backend, collection, request2);
3190
+ }
3191
+ // ========================================================================
3192
+ // Capabilities & Backend Info
3193
+ // ========================================================================
3194
+ capabilities() {
3195
+ return this.backend.capabilities();
3196
+ }
3197
+ get backendType() {
3198
+ return this.config.backend;
2230
3199
  }
2231
3200
  // ========================================================================
2232
3201
  // Agent Memory (Phase 8)
2233
3202
  // ========================================================================
2234
- /**
2235
- * Create an agent memory interface
2236
- *
2237
- * @param config - Optional agent memory configuration
2238
- * @returns AgentMemoryClient instance
2239
- */
2240
3203
  agentMemory(config) {
2241
3204
  this.ensureInitialized();
2242
3205
  return new AgentMemoryClient(this.backend, config);
@@ -2336,6 +3299,16 @@ var VelesQLBuilder = class _VelesQLBuilder {
2336
3299
  *
2337
3300
  * @param condition - WHERE condition
2338
3301
  * @param params - Optional parameters
3302
+ *
3303
+ * @example
3304
+ * ```typescript
3305
+ * // Substring matching with CONTAINS_TEXT
3306
+ * velesql()
3307
+ * .match('d', 'Document')
3308
+ * .where("content CONTAINS_TEXT 'keyword'")
3309
+ * .limit(10)
3310
+ * .toVelesQL();
3311
+ * ```
2339
3312
  */
2340
3313
  where(condition, params) {
2341
3314
  const newParams = params ? { ...this.state.params, ...params } : this.state.params;
@@ -2544,16 +3517,205 @@ var VelesQLBuilder = class _VelesQLBuilder {
2544
3517
  function velesql() {
2545
3518
  return new VelesQLBuilder();
2546
3519
  }
3520
+
3521
+ // src/filter.ts
3522
+ function isTypedFilter(input) {
3523
+ if (typeof input !== "object" || input === null) {
3524
+ return false;
3525
+ }
3526
+ if (!("condition" in input)) {
3527
+ return false;
3528
+ }
3529
+ const cond = input.condition;
3530
+ return typeof cond === "object" && cond !== null;
3531
+ }
3532
+ function normalizeFilter(input) {
3533
+ if (input === void 0) {
3534
+ return void 0;
3535
+ }
3536
+ return input;
3537
+ }
3538
+ var f = {
3539
+ // --- Comparison -----------------------------------------------------------
3540
+ /** `field == value` */
3541
+ eq(field, value) {
3542
+ return { condition: { type: "eq", field, value } };
3543
+ },
3544
+ /** `field != value` */
3545
+ neq(field, value) {
3546
+ return { condition: { type: "neq", field, value } };
3547
+ },
3548
+ /** `field > value` */
3549
+ gt(field, value) {
3550
+ return { condition: { type: "gt", field, value } };
3551
+ },
3552
+ /** `field >= value` */
3553
+ gte(field, value) {
3554
+ return { condition: { type: "gte", field, value } };
3555
+ },
3556
+ /** `field < value` */
3557
+ lt(field, value) {
3558
+ return { condition: { type: "lt", field, value } };
3559
+ },
3560
+ /** `field <= value` */
3561
+ lte(field, value) {
3562
+ return { condition: { type: "lte", field, value } };
3563
+ },
3564
+ // --- Set / string / null --------------------------------------------------
3565
+ /** `field IN (values...)` — the values list is copied. */
3566
+ in(field, values) {
3567
+ return { condition: { type: "in", field, values: [...values] } };
3568
+ },
3569
+ /** Substring containment: `field LIKE '%value%'` (case-sensitive). */
3570
+ contains(field, value) {
3571
+ return { condition: { type: "contains", field, value } };
3572
+ },
3573
+ /** `field IS NULL` */
3574
+ isNull(field) {
3575
+ return { condition: { type: "is_null", field } };
3576
+ },
3577
+ /** `field IS NOT NULL` */
3578
+ isNotNull(field) {
3579
+ return { condition: { type: "is_not_null", field } };
3580
+ },
3581
+ // --- SQL patterns ---------------------------------------------------------
3582
+ /** SQL LIKE pattern matching (case-sensitive). Supports `%` and `_`. */
3583
+ like(field, pattern) {
3584
+ return { condition: { type: "like", field, pattern } };
3585
+ },
3586
+ /** SQL ILIKE pattern matching (case-insensitive). */
3587
+ ilike(field, pattern) {
3588
+ return { condition: { type: "ilike", field, pattern } };
3589
+ },
3590
+ // --- Array ----------------------------------------------------------------
3591
+ /** `value IN field` (field must be an array). */
3592
+ arrayContains(field, value) {
3593
+ return { condition: { type: "array_contains", field, value } };
3594
+ },
3595
+ /** At least one of `values` is present in the array field. */
3596
+ arrayContainsAny(field, values) {
3597
+ return { condition: { type: "array_contains_any", field, values: [...values] } };
3598
+ },
3599
+ /** Every value in `values` is present in the array field. */
3600
+ arrayContainsAll(field, values) {
3601
+ return { condition: { type: "array_contains_all", field, values: [...values] } };
3602
+ },
3603
+ // --- Geo ------------------------------------------------------------------
3604
+ /** Haversine distance comparison: `distance(field, (lat, lng)) <op> threshold`. */
3605
+ geoDistance(field, lat, lng, operator, threshold) {
3606
+ return {
3607
+ condition: { type: "geo_distance", field, lat, lng, operator, threshold }
3608
+ };
3609
+ },
3610
+ /** Bounding-box containment: point field falls inside `[lat_min, lat_max] x [lng_min, lng_max]`. */
3611
+ geoBbox(field, bounds) {
3612
+ return {
3613
+ condition: {
3614
+ type: "geo_bbox",
3615
+ field,
3616
+ lat_min: bounds.lat_min,
3617
+ lng_min: bounds.lng_min,
3618
+ lat_max: bounds.lat_max,
3619
+ lng_max: bounds.lng_max
3620
+ }
3621
+ };
3622
+ },
3623
+ // --- Convenience combinators ----------------------------------------------
3624
+ /** `field NOT IN (values...)` — shorthand for `not(in(field, values))`. */
3625
+ notIn(field, values) {
3626
+ return { condition: { type: "not", condition: { type: "in", field, values: [...values] } } };
3627
+ },
3628
+ /** `field BETWEEN low AND high` — shorthand for `and([gte(field, low), lte(field, high)])`. */
3629
+ between(field, low, high) {
3630
+ return {
3631
+ condition: {
3632
+ type: "and",
3633
+ conditions: [
3634
+ { type: "gte", field, value: low },
3635
+ { type: "lte", field, value: high }
3636
+ ]
3637
+ }
3638
+ };
3639
+ },
3640
+ // --- Logical --------------------------------------------------------------
3641
+ /** Logical AND — the filters list is copied and flattened to root conditions. */
3642
+ and(filters) {
3643
+ return {
3644
+ condition: {
3645
+ type: "and",
3646
+ conditions: filters.map((item) => item.condition)
3647
+ }
3648
+ };
3649
+ },
3650
+ /** Logical OR — the filters list is copied and flattened to root conditions. */
3651
+ or(filters) {
3652
+ return {
3653
+ condition: {
3654
+ type: "or",
3655
+ conditions: filters.map((item) => item.condition)
3656
+ }
3657
+ };
3658
+ },
3659
+ /** Logical NOT — wraps a single filter. */
3660
+ not(filter) {
3661
+ return { condition: { type: "not", condition: filter.condition } };
3662
+ }
3663
+ };
2547
3664
  export {
2548
3665
  AgentMemoryClient,
3666
+ AllocationFailedError,
2549
3667
  BackpressureError,
3668
+ CollectionExistsError,
3669
+ CollectionNotFoundError,
3670
+ ColumnStoreError,
3671
+ ConfigError,
2550
3672
  ConnectionError,
3673
+ DatabaseLockedError,
3674
+ DimensionMismatchError,
3675
+ EdgeExistsError,
3676
+ EdgeNotFoundError,
3677
+ EpochMismatchError,
3678
+ GpuError,
3679
+ GraphNotSupportedError,
3680
+ GuardRailError,
3681
+ IncompatibleSchemaVersionError,
3682
+ IndexCorruptedError,
3683
+ IndexError,
3684
+ InternalError,
3685
+ InvalidCollectionNameError,
3686
+ InvalidDimensionError,
3687
+ InvalidEdgeLabelError,
3688
+ InvalidQuantizerConfigError,
3689
+ InvalidVectorError,
3690
+ IoError,
3691
+ NodeNotFoundError,
2551
3692
  NotFoundError,
3693
+ OverflowError,
3694
+ PointNotFoundError,
3695
+ QueryError,
3696
+ REST_CAPABILITIES,
2552
3697
  RestBackend,
3698
+ SchemaValidationError,
3699
+ SearchNotSupportedError,
3700
+ SerializationError,
3701
+ SnapshotBuildFailedError,
3702
+ SparseIndexError,
3703
+ StorageError,
3704
+ TrainingFailedError,
3705
+ VELES_ERROR_CODES,
2553
3706
  ValidationError,
3707
+ VectorNotAllowedError,
3708
+ VectorRequiredError,
2554
3709
  VelesDB,
2555
3710
  VelesDBError,
3711
+ VelesError,
2556
3712
  VelesQLBuilder,
3713
+ WASM_CAPABILITIES,
2557
3714
  WasmBackend,
3715
+ f,
3716
+ isTypedFilter,
3717
+ normalizeFilter,
3718
+ parseVelesError,
3719
+ searchQualityToMode,
2558
3720
  velesql
2559
3721
  };