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