@dreamlake/dreamdb 0.1.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.cjs ADDED
@@ -0,0 +1,2271 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Dataset: () => Dataset,
24
+ MULTIHASH_BYTES: () => MULTIHASH_BYTES,
25
+ MemoryBackend: () => MemoryBackend,
26
+ S3Backend: () => S3Backend,
27
+ SCALAR_ENCODING_MAP: () => SCALAR_ENCODING_MAP,
28
+ Schema: () => Schema,
29
+ Space: () => Space,
30
+ base32ToBytes: () => base32ToBytes,
31
+ bitsFromProjections: () => bitsFromProjections,
32
+ bitsToBase2: () => bitsToBase2,
33
+ buildPqCosineDecoder: () => buildPqCosineDecoder,
34
+ buildRabitqCosineDecoder: () => buildRabitqCosineDecoder,
35
+ bytesToBase32: () => bytesToBase32,
36
+ chacha20Stream: () => chacha20Stream,
37
+ decodeBucketAnchorsOnly: () => decodeBucketAnchorsOnly,
38
+ decodeBucketRecords: () => decodeBucketRecords,
39
+ decodeCbor: () => decodeCbor,
40
+ deriveHyperplanesLshCosine: () => deriveHyperplanesLshCosine,
41
+ deriveRotationMatrix: () => deriveRotationMatrix,
42
+ dotF32: () => dotF32,
43
+ dotL2Normalized: () => dotL2Normalized,
44
+ encodeCbor: () => encodeCbor,
45
+ modalityForField: () => modalityForField,
46
+ multiProbeKeys: () => multiProbeKeys,
47
+ normalizeL2: () => normalizeL2,
48
+ normalizeL2F32: () => normalizeL2F32,
49
+ parseSpaceUri: () => parseSpaceUri,
50
+ peekBucketHeader: () => peekBucketHeader,
51
+ projectionsLshCosine: () => projectionsLshCosine,
52
+ scalarModalityFragment: () => scalarModalityFragment
53
+ });
54
+ module.exports = __toCommonJS(index_exports);
55
+
56
+ // src/cbor.ts
57
+ function decodeCbor(bytes) {
58
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
59
+ const r = { off: 0 };
60
+ return readValue(view, bytes, r);
61
+ }
62
+ function encodeCbor(value) {
63
+ const parts = [];
64
+ encodeValue(value, parts);
65
+ let totalLen = 0;
66
+ for (const p of parts) totalLen += p.length;
67
+ const out = new Uint8Array(totalLen);
68
+ let off = 0;
69
+ for (const p of parts) {
70
+ out.set(p, off);
71
+ off += p.length;
72
+ }
73
+ return out;
74
+ }
75
+ function encodeValue(value, parts) {
76
+ if (value === null) {
77
+ parts.push(new Uint8Array([246]));
78
+ return;
79
+ }
80
+ if (value === void 0) {
81
+ parts.push(new Uint8Array([247]));
82
+ return;
83
+ }
84
+ if (value === true) {
85
+ parts.push(new Uint8Array([245]));
86
+ return;
87
+ }
88
+ if (value === false) {
89
+ parts.push(new Uint8Array([244]));
90
+ return;
91
+ }
92
+ if (typeof value === "number") {
93
+ if (Number.isInteger(value) && value >= 0 && value <= Number.MAX_SAFE_INTEGER) {
94
+ encodeUint(0, value, parts);
95
+ } else if (Number.isInteger(value) && value < 0 && value >= -Number.MAX_SAFE_INTEGER) {
96
+ encodeUint(1, -1 - value, parts);
97
+ } else {
98
+ const buf = new Uint8Array(9);
99
+ buf[0] = 251;
100
+ const dv = new DataView(buf.buffer);
101
+ dv.setFloat64(1, value);
102
+ parts.push(buf);
103
+ }
104
+ return;
105
+ }
106
+ if (typeof value === "bigint") {
107
+ if (value >= 0n) {
108
+ encodeUint64(0, value, parts);
109
+ } else {
110
+ encodeUint64(1, -1n - value, parts);
111
+ }
112
+ return;
113
+ }
114
+ if (typeof value === "string") {
115
+ const encoded = new TextEncoder().encode(value);
116
+ encodeUint(3, encoded.length, parts);
117
+ parts.push(encoded);
118
+ return;
119
+ }
120
+ if (value instanceof Uint8Array) {
121
+ encodeUint(2, value.length, parts);
122
+ parts.push(new Uint8Array(value));
123
+ return;
124
+ }
125
+ if (Array.isArray(value)) {
126
+ encodeUint(4, value.length, parts);
127
+ for (const item of value) {
128
+ encodeValue(item, parts);
129
+ }
130
+ return;
131
+ }
132
+ if (typeof value === "object") {
133
+ const keys = Object.keys(value);
134
+ encodeUint(5, keys.length, parts);
135
+ for (const k of keys) {
136
+ encodeValue(k, parts);
137
+ encodeValue(value[k], parts);
138
+ }
139
+ return;
140
+ }
141
+ }
142
+ function encodeUint(majorType, n, parts) {
143
+ const mt = majorType << 5;
144
+ if (n < 24) {
145
+ parts.push(new Uint8Array([mt | n]));
146
+ } else if (n < 256) {
147
+ parts.push(new Uint8Array([mt | 24, n]));
148
+ } else if (n < 65536) {
149
+ const buf = new Uint8Array(3);
150
+ buf[0] = mt | 25;
151
+ buf[1] = n >> 8 & 255;
152
+ buf[2] = n & 255;
153
+ parts.push(buf);
154
+ } else if (n < 4294967296) {
155
+ const buf = new Uint8Array(5);
156
+ buf[0] = mt | 26;
157
+ const dv = new DataView(buf.buffer);
158
+ dv.setUint32(1, n);
159
+ parts.push(buf);
160
+ } else {
161
+ encodeUint64(majorType, BigInt(n), parts);
162
+ }
163
+ }
164
+ function encodeUint64(majorType, n, parts) {
165
+ const mt = majorType << 5;
166
+ const buf = new Uint8Array(9);
167
+ buf[0] = mt | 27;
168
+ const dv = new DataView(buf.buffer);
169
+ dv.setBigUint64(1, n);
170
+ parts.push(buf);
171
+ }
172
+ function readValue(view, bytes, r) {
173
+ const ib = bytes[r.off++];
174
+ const mt = ib >> 5;
175
+ const ai = ib & 31;
176
+ const arg = readArg(view, bytes, r, ai);
177
+ switch (mt) {
178
+ case 0:
179
+ return typeof arg === "bigint" ? arg <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(arg) : arg : arg;
180
+ case 1:
181
+ if (typeof arg === "bigint") {
182
+ const val = -1n - arg;
183
+ return val >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(val) : val;
184
+ }
185
+ return -1 - Number(arg);
186
+ case 2: {
187
+ const len = Number(arg);
188
+ const out = bytes.slice(r.off, r.off + len);
189
+ r.off += len;
190
+ return out;
191
+ }
192
+ case 3: {
193
+ const len = Number(arg);
194
+ const sl = bytes.subarray(r.off, r.off + len);
195
+ r.off += len;
196
+ return new TextDecoder().decode(sl);
197
+ }
198
+ case 4: {
199
+ const len = Number(arg);
200
+ const arr = [];
201
+ for (let i = 0; i < len; i++) arr.push(readValue(view, bytes, r));
202
+ return arr;
203
+ }
204
+ case 5: {
205
+ const len = Number(arg);
206
+ const obj = {};
207
+ for (let i = 0; i < len; i++) {
208
+ const k = readValue(view, bytes, r);
209
+ const v = readValue(view, bytes, r);
210
+ obj[String(k)] = v;
211
+ }
212
+ return obj;
213
+ }
214
+ case 7: {
215
+ if (ai === 20) return false;
216
+ if (ai === 21) return true;
217
+ if (ai === 22) return null;
218
+ if (ai === 23) return void 0;
219
+ if (ai === 26) return view.getFloat32(r.off - 4);
220
+ if (ai === 27) return view.getFloat64(r.off - 8);
221
+ if (ai === 25) {
222
+ const raw = Number(arg);
223
+ const sign = raw >> 15 & 1;
224
+ const exp = raw >> 10 & 31;
225
+ const frac = raw & 1023;
226
+ let val;
227
+ if (exp === 0) {
228
+ val = frac === 0 ? 0 : Math.pow(2, -24) * frac;
229
+ } else if (exp === 31) {
230
+ val = frac === 0 ? Infinity : NaN;
231
+ } else {
232
+ val = Math.pow(2, exp - 25) * (1024 + frac);
233
+ }
234
+ return sign ? -val : val;
235
+ }
236
+ throw new Error(`CBOR simple ${ai} not supported`);
237
+ }
238
+ default:
239
+ throw new Error(`CBOR major type ${mt} not supported`);
240
+ }
241
+ }
242
+ function readArg(view, bytes, r, ai) {
243
+ if (ai < 24) return ai;
244
+ if (ai === 24) return bytes[r.off++];
245
+ if (ai === 25) {
246
+ const v = view.getUint16(r.off);
247
+ r.off += 2;
248
+ return v;
249
+ }
250
+ if (ai === 26) {
251
+ const v = view.getUint32(r.off);
252
+ r.off += 4;
253
+ return v;
254
+ }
255
+ if (ai === 27) {
256
+ const v = view.getBigUint64(r.off);
257
+ r.off += 8;
258
+ return v;
259
+ }
260
+ throw new Error(`CBOR additional-info ${ai} not supported`);
261
+ }
262
+
263
+ // src/uri.ts
264
+ var MULTIHASH_BYTES = 33;
265
+ var BASE32_ALPHABET = "abcdefghijklmnopqrstuvwxyz234567";
266
+ var BASE32_DECODE_MAP = /* @__PURE__ */ new Map();
267
+ for (let i = 0; i < BASE32_ALPHABET.length; i++) {
268
+ BASE32_DECODE_MAP.set(BASE32_ALPHABET[i], i);
269
+ }
270
+ function bytesToBase32(bytes) {
271
+ let bits = 0;
272
+ let value = 0;
273
+ let out = "";
274
+ for (const b of bytes) {
275
+ value = value << 8 | b;
276
+ bits += 8;
277
+ while (bits >= 5) {
278
+ bits -= 5;
279
+ out += BASE32_ALPHABET[value >> bits & 31];
280
+ }
281
+ }
282
+ if (bits > 0) out += BASE32_ALPHABET[value << 5 - bits & 31];
283
+ return out;
284
+ }
285
+ function base32ToBytes(str) {
286
+ const lower = str.toLowerCase();
287
+ let bits = 0;
288
+ let value = 0;
289
+ const out = [];
290
+ for (const ch of lower) {
291
+ const v = BASE32_DECODE_MAP.get(ch);
292
+ if (v === void 0) throw new Error(`Invalid base32 character: '${ch}'`);
293
+ value = value << 5 | v;
294
+ bits += 5;
295
+ while (bits >= 8) {
296
+ bits -= 8;
297
+ out.push(value >> bits & 255);
298
+ }
299
+ }
300
+ return new Uint8Array(out);
301
+ }
302
+ function parseSpaceUri(uri) {
303
+ const u = new URL(uri);
304
+ const parts = u.pathname.replace(/^\/+/, "").split("/");
305
+ if (parts.length < 2) {
306
+ throw new Error(
307
+ `Space URI missing /refs/<name> or /manifests/<hash> suffix: ${uri}`
308
+ );
309
+ }
310
+ const id = parts.pop();
311
+ const marker = parts.pop();
312
+ let kind;
313
+ if (marker === "refs") kind = "ref";
314
+ else if (marker === "manifests") kind = "manifest";
315
+ else
316
+ throw new Error(
317
+ `Space URI: expected /refs/ or /manifests/, got /${marker}/: ${uri}`
318
+ );
319
+ const connectorBase = `${u.origin}/${parts.join("/")}`.replace(/\/$/, "");
320
+ return { connectorBase, kind, id };
321
+ }
322
+ function scalarModalityFragment(valueType) {
323
+ const map = {
324
+ categorical: "cat",
325
+ bool: "bool",
326
+ int: "i64",
327
+ float: "f64",
328
+ string: "str",
329
+ timestamp: "ts"
330
+ };
331
+ return map[valueType.toLowerCase()] || "str";
332
+ }
333
+ function modalityForField(field) {
334
+ if (field.kind === "image") return `image.${field.mime}`;
335
+ if (field.kind === "video") return `video.${field.mime}`;
336
+ if (field.kind === "audio") return `audio.${field.mime}`;
337
+ if (field.kind === "embedding") return `embedding.f32.dim=${field.dim}.bucketed`;
338
+ if (field.kind === "scalar") {
339
+ const vt = field.value_type || field.valueType || "str";
340
+ const enc = scalarModalityFragment(vt);
341
+ return `scalar.${enc}.field=${field.name}`;
342
+ }
343
+ return null;
344
+ }
345
+
346
+ // src/backend.ts
347
+ var S3Backend = class {
348
+ baseUrl;
349
+ constructor(baseUrl) {
350
+ this.baseUrl = baseUrl.replace(/\/+$/, "");
351
+ }
352
+ async get(path, opts) {
353
+ const url = `${this.baseUrl}/${path}`;
354
+ const fetchOpts = {};
355
+ if (opts?.noCache) {
356
+ fetchOpts.cache = "no-store";
357
+ }
358
+ const r = await fetch(url, fetchOpts);
359
+ if (!r.ok) throw new Error(`GET ${url}: HTTP ${r.status}`);
360
+ return new Uint8Array(await r.arrayBuffer());
361
+ }
362
+ async put(path, data, opts) {
363
+ const url = `${this.baseUrl}/${path}`;
364
+ const headers = {};
365
+ if (opts?.contentType) {
366
+ headers["Content-Type"] = opts.contentType;
367
+ } else {
368
+ headers["Content-Type"] = "application/octet-stream";
369
+ }
370
+ const r = await fetch(url, {
371
+ method: "PUT",
372
+ headers,
373
+ body: data
374
+ });
375
+ if (!r.ok) throw new Error(`PUT ${url}: HTTP ${r.status}`);
376
+ return path;
377
+ }
378
+ async list(prefix) {
379
+ const url = `${this.baseUrl}?list-type=2&prefix=${encodeURIComponent(prefix)}`;
380
+ const r = await fetch(url);
381
+ if (!r.ok) throw new Error(`LIST ${url}: HTTP ${r.status}`);
382
+ const text = await r.text();
383
+ const keys = [];
384
+ const regex = /<Key>([^<]+)<\/Key>/g;
385
+ let match;
386
+ while ((match = regex.exec(text)) !== null) {
387
+ keys.push(match[1]);
388
+ }
389
+ return keys;
390
+ }
391
+ async delete(path) {
392
+ const url = `${this.baseUrl}/${path}`;
393
+ const r = await fetch(url, { method: "DELETE" });
394
+ if (!r.ok) throw new Error(`DELETE ${url}: HTTP ${r.status}`);
395
+ }
396
+ };
397
+ var MemoryBackend = class {
398
+ store = /* @__PURE__ */ new Map();
399
+ async get(path, _opts) {
400
+ const data = this.store.get(path);
401
+ if (!data) throw new Error(`MemoryBackend: key not found: ${path}`);
402
+ return data;
403
+ }
404
+ async put(path, data, _opts) {
405
+ this.store.set(path, new Uint8Array(data));
406
+ return path;
407
+ }
408
+ async list(prefix) {
409
+ const keys = [];
410
+ for (const k of this.store.keys()) {
411
+ if (k.startsWith(prefix)) keys.push(k);
412
+ }
413
+ return keys.sort();
414
+ }
415
+ async delete(path) {
416
+ this.store.delete(path);
417
+ }
418
+ /** Check whether a key exists. */
419
+ has(path) {
420
+ return this.store.has(path);
421
+ }
422
+ /** Get the number of stored objects. */
423
+ get size() {
424
+ return this.store.size;
425
+ }
426
+ /** Clear all stored objects. */
427
+ clear() {
428
+ this.store.clear();
429
+ }
430
+ };
431
+
432
+ // src/query.ts
433
+ function rotl(a, b) {
434
+ return (a << b | a >>> 32 - b) >>> 0;
435
+ }
436
+ function add32(a, b) {
437
+ return a + b >>> 0;
438
+ }
439
+ function quarterRound(s, ai, bi, ci, di) {
440
+ s[ai] = add32(s[ai], s[bi]);
441
+ s[di] = rotl(s[di] ^ s[ai], 16);
442
+ s[ci] = add32(s[ci], s[di]);
443
+ s[bi] = rotl(s[bi] ^ s[ci], 12);
444
+ s[ai] = add32(s[ai], s[bi]);
445
+ s[di] = rotl(s[di] ^ s[ai], 8);
446
+ s[ci] = add32(s[ci], s[di]);
447
+ s[bi] = rotl(s[bi] ^ s[ci], 7);
448
+ }
449
+ function chacha20Block(keyU32, nonceU32, counter) {
450
+ const s = new Uint32Array(16);
451
+ s[0] = 1634760805;
452
+ s[1] = 857760878;
453
+ s[2] = 2036477234;
454
+ s[3] = 1797285236;
455
+ for (let i = 0; i < 8; i++) s[4 + i] = keyU32[i];
456
+ s[12] = counter >>> 0;
457
+ s[13] = nonceU32[0];
458
+ s[14] = nonceU32[1];
459
+ s[15] = nonceU32[2];
460
+ const ws = new Uint32Array(s);
461
+ for (let i = 0; i < 10; i++) {
462
+ quarterRound(ws, 0, 4, 8, 12);
463
+ quarterRound(ws, 1, 5, 9, 13);
464
+ quarterRound(ws, 2, 6, 10, 14);
465
+ quarterRound(ws, 3, 7, 11, 15);
466
+ quarterRound(ws, 0, 5, 10, 15);
467
+ quarterRound(ws, 1, 6, 11, 12);
468
+ quarterRound(ws, 2, 7, 8, 13);
469
+ quarterRound(ws, 3, 4, 9, 14);
470
+ }
471
+ const out = new Uint8Array(64);
472
+ for (let i = 0; i < 16; i++) {
473
+ const w = add32(ws[i], s[i]);
474
+ out[i * 4 + 0] = w & 255;
475
+ out[i * 4 + 1] = w >>> 8 & 255;
476
+ out[i * 4 + 2] = w >>> 16 & 255;
477
+ out[i * 4 + 3] = w >>> 24 & 255;
478
+ }
479
+ return out;
480
+ }
481
+ function chacha20Stream(seedBytes32) {
482
+ if (seedBytes32.length !== 32) throw new Error("ChaCha20 seed must be 32 bytes");
483
+ const keyU32 = new Uint32Array(8);
484
+ for (let i = 0; i < 8; i++) {
485
+ keyU32[i] = seedBytes32[i * 4] | seedBytes32[i * 4 + 1] << 8 | seedBytes32[i * 4 + 2] << 16 | seedBytes32[i * 4 + 3] << 24;
486
+ keyU32[i] = keyU32[i] >>> 0;
487
+ }
488
+ const nonceU32 = new Uint32Array(3);
489
+ let counter = 0;
490
+ let block = null;
491
+ let pos = 64;
492
+ return {
493
+ fill(out) {
494
+ let written = 0;
495
+ while (written < out.length) {
496
+ if (pos >= 64) {
497
+ block = chacha20Block(keyU32, nonceU32, counter++);
498
+ pos = 0;
499
+ }
500
+ const take = Math.min(out.length - written, 64 - pos);
501
+ for (let i = 0; i < take; i++) out[written + i] = block[pos + i];
502
+ written += take;
503
+ pos += take;
504
+ }
505
+ }
506
+ };
507
+ }
508
+ function normalizeL2F32(v) {
509
+ let sumSq = 0;
510
+ for (let i = 0; i < v.length; i++) {
511
+ const x = Math.fround(v[i]);
512
+ sumSq = Math.fround(sumSq + Math.fround(x * x));
513
+ }
514
+ if (!isFinite(sumSq) || sumSq === 0) return null;
515
+ const norm = Math.fround(Math.sqrt(sumSq));
516
+ const out = new Float32Array(v.length);
517
+ for (let i = 0; i < v.length; i++) out[i] = Math.fround(v[i] / norm);
518
+ return out;
519
+ }
520
+ function normalizeL2(v) {
521
+ let sum = 0;
522
+ for (let i = 0; i < v.length; i++) sum += v[i] * v[i];
523
+ const n = Math.sqrt(sum);
524
+ if (n === 0) {
525
+ const out2 = new Float32Array(v.length);
526
+ for (let i = 0; i < v.length; i++) out2[i] = v[i];
527
+ return out2;
528
+ }
529
+ const out = new Float32Array(v.length);
530
+ for (let i = 0; i < v.length; i++) out[i] = v[i] / n;
531
+ return out;
532
+ }
533
+ function dotF32(a, b) {
534
+ let acc = 0;
535
+ for (let i = 0; i < a.length; i++) {
536
+ const prod = Math.fround(Math.fround(a[i]) * Math.fround(b[i]));
537
+ acc = Math.fround(acc + prod);
538
+ }
539
+ return acc;
540
+ }
541
+ function dotL2Normalized(a, b) {
542
+ let sum = 0;
543
+ for (let i = 0; i < a.length; i++) sum += a[i] * b[i];
544
+ return sum;
545
+ }
546
+ function deriveHyperplanesLshCosine(seedBytes32, dim, bits) {
547
+ const stream = chacha20Stream(seedBytes32);
548
+ const out = new Float32Array(dim * bits);
549
+ const buf = new Uint8Array(dim * 4);
550
+ for (let plane = 0; plane < bits; plane++) {
551
+ let attempts = 0;
552
+ while (attempts < 1024) {
553
+ stream.fill(buf);
554
+ const g = new Float32Array(dim);
555
+ const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
556
+ for (let i = 0; i < dim; i++) {
557
+ const n = view.getInt32(i * 4, true);
558
+ g[i] = Math.fround(n / 2147483648);
559
+ }
560
+ const h = normalizeL2F32(g);
561
+ if (h) {
562
+ for (let i = 0; i < dim; i++) out[plane * dim + i] = h[i];
563
+ break;
564
+ }
565
+ attempts++;
566
+ }
567
+ if (attempts >= 1024) throw new Error(`hyperplane ${plane} ChaCha20 retry exhausted`);
568
+ }
569
+ return out;
570
+ }
571
+ function projectionsLshCosine(qNormalized, hyperplanes, dim, bits) {
572
+ const projections = new Float32Array(bits);
573
+ for (let b = 0; b < bits; b++) {
574
+ const plane = hyperplanes.subarray(b * dim, (b + 1) * dim);
575
+ projections[b] = dotF32(qNormalized, plane);
576
+ }
577
+ return projections;
578
+ }
579
+ function bitsFromProjections(projections) {
580
+ const bits = new Array(projections.length);
581
+ for (let i = 0; i < projections.length; i++) bits[i] = projections[i] >= 0;
582
+ return bits;
583
+ }
584
+ function bitsToBase2(bits) {
585
+ let s = "";
586
+ for (const b of bits) s += b ? "1" : "0";
587
+ return s;
588
+ }
589
+ function flippedKey(bits, flipIdxs) {
590
+ const copy = bits.slice();
591
+ for (const i of flipIdxs) copy[i] = !copy[i];
592
+ return bitsToBase2(copy);
593
+ }
594
+ function multiProbeKeys(projections, probeCount, maxHamming) {
595
+ const n = projections.length;
596
+ const absP = new Float32Array(n);
597
+ for (let i = 0; i < n; i++) absP[i] = Math.abs(projections[i]);
598
+ const primary = bitsFromProjections(projections);
599
+ const primaryKey = bitsToBase2(primary);
600
+ if (probeCount <= 1) return [primaryKey];
601
+ const candidates = [];
602
+ for (let i = 0; i < n; i++) candidates.push({ score: absP[i], flips: [i] });
603
+ if (maxHamming >= 2) {
604
+ for (let i = 0; i < n; i++)
605
+ for (let j = i + 1; j < n; j++)
606
+ candidates.push({ score: absP[i] + absP[j], flips: [i, j] });
607
+ }
608
+ if (maxHamming >= 3) {
609
+ for (let i = 0; i < n; i++)
610
+ for (let j = i + 1; j < n; j++)
611
+ for (let k = j + 1; k < n; k++)
612
+ candidates.push({ score: absP[i] + absP[j] + absP[k], flips: [i, j, k] });
613
+ }
614
+ if (maxHamming >= 4) {
615
+ for (let i = 0; i < n; i++)
616
+ for (let j = i + 1; j < n; j++)
617
+ for (let k = j + 1; k < n; k++)
618
+ for (let l = k + 1; l < n; l++)
619
+ candidates.push({
620
+ score: absP[i] + absP[j] + absP[k] + absP[l],
621
+ flips: [i, j, k, l]
622
+ });
623
+ }
624
+ candidates.sort((a, b) => a.score - b.score);
625
+ const keys = [primaryKey];
626
+ for (const c of candidates) {
627
+ if (keys.length >= probeCount) break;
628
+ keys.push(flippedKey(primary, c.flips));
629
+ }
630
+ return keys;
631
+ }
632
+ function deriveRotationMatrix(seedBytes32, dim) {
633
+ const stream = chacha20Stream(seedBytes32);
634
+ const m = new Float32Array(dim * dim);
635
+ const buf = new Uint8Array(dim * dim * 4);
636
+ stream.fill(buf);
637
+ const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
638
+ for (let i = 0; i < dim * dim; i++) {
639
+ const n = view.getInt32(i * 4, true);
640
+ m[i] = Math.fround(n / 2147483648);
641
+ }
642
+ for (let j = 0; j < dim; j++) {
643
+ for (let i = 0; i < j; i++) {
644
+ let coeff = 0;
645
+ for (let kk = 0; kk < dim; kk++) {
646
+ coeff = Math.fround(coeff + Math.fround(m[j * dim + kk] * m[i * dim + kk]));
647
+ }
648
+ for (let kk = 0; kk < dim; kk++) {
649
+ m[j * dim + kk] = Math.fround(m[j * dim + kk] - Math.fround(coeff * m[i * dim + kk]));
650
+ }
651
+ }
652
+ let sq = 0;
653
+ for (let kk = 0; kk < dim; kk++) {
654
+ sq = Math.fround(sq + Math.fround(m[j * dim + kk] * m[j * dim + kk]));
655
+ }
656
+ if (sq > 0) {
657
+ const inv = Math.fround(1 / Math.fround(Math.sqrt(sq)));
658
+ for (let kk = 0; kk < dim; kk++) {
659
+ m[j * dim + kk] = Math.fround(m[j * dim + kk] * inv);
660
+ }
661
+ } else {
662
+ m[j * dim + j] = 1;
663
+ }
664
+ }
665
+ return m;
666
+ }
667
+ function buildPqCosineDecoder(vcCborBytes) {
668
+ const obj = decodeCbor(vcCborBytes);
669
+ if (!obj || obj.algorithm !== "dreamdb.pq-cosine") {
670
+ throw new Error(`expected dreamdb.pq-cosine, got ${obj && obj.algorithm}`);
671
+ }
672
+ const dim = Number(obj.dim);
673
+ const params = obj.params;
674
+ if (!params || !(params.codebooks instanceof Uint8Array)) {
675
+ throw new Error("pq-cosine params missing codebooks bytes");
676
+ }
677
+ const m = Number(params.m);
678
+ const k = Number(params.k);
679
+ const codebookBytes = params.codebooks;
680
+ const dsub = dim / m;
681
+ if (dsub !== Math.floor(dsub)) {
682
+ throw new Error(`dim=${dim} not divisible by m=${m}`);
683
+ }
684
+ if (codebookBytes.length !== m * k * dsub * 4) {
685
+ throw new Error(
686
+ `codebook bytes ${codebookBytes.length} != m(${m}) * k(${k}) * dsub(${dsub}) * 4`
687
+ );
688
+ }
689
+ const codebooksAligned = new Uint8Array(codebookBytes.length);
690
+ codebooksAligned.set(codebookBytes);
691
+ const codebookF32 = new Float32Array(codebooksAligned.buffer);
692
+ return {
693
+ algorithm: "dreamdb.pq-cosine",
694
+ dim,
695
+ recordCodeBytes: m,
696
+ decode(codes) {
697
+ if (codes.length !== m) {
698
+ throw new Error(`codes length ${codes.length} != m=${m}`);
699
+ }
700
+ const out = new Float32Array(dim);
701
+ for (let s = 0; s < m; s++) {
702
+ const codeByte = codes[s];
703
+ const srcOff = s * k * dsub + codeByte * dsub;
704
+ const dstOff = s * dsub;
705
+ for (let d = 0; d < dsub; d++) {
706
+ out[dstOff + d] = codebookF32[srcOff + d];
707
+ }
708
+ }
709
+ return out;
710
+ }
711
+ };
712
+ }
713
+ function buildRabitqCosineDecoder(vcCborBytes) {
714
+ const obj = decodeCbor(vcCborBytes);
715
+ if (!obj || obj.algorithm !== "dreamdb.rabitq-cosine") {
716
+ throw new Error(`expected dreamdb.rabitq-cosine, got ${obj && obj.algorithm}`);
717
+ }
718
+ const dim = Number(obj.dim);
719
+ const params = obj.params;
720
+ if (!params || !(params.rotation_seed instanceof Uint8Array)) {
721
+ throw new Error("rabitq-cosine params missing rotation_seed bytes");
722
+ }
723
+ if (params.rotation_seed.length !== 32) {
724
+ throw new Error(`rotation_seed must be 32 bytes; got ${params.rotation_seed.length}`);
725
+ }
726
+ const bitsPerDim = Number(params.bits_per_dim || 1);
727
+ if (bitsPerDim !== 1) {
728
+ throw new Error(`rabitq-cosine bits_per_dim=${bitsPerDim} not supported (v0 ships 1 only)`);
729
+ }
730
+ const withCorrection = params.with_correction_factors === true;
731
+ const payloadBytes = Math.ceil(dim / 8);
732
+ const codeBytesExpected = withCorrection ? payloadBytes + 4 : payloadBytes;
733
+ const rotation = deriveRotationMatrix(params.rotation_seed, dim);
734
+ const constScale = 1 / Math.sqrt(dim);
735
+ function readPerRecordScale(codeBytes) {
736
+ const off = codeBytes.byteOffset + payloadBytes;
737
+ const dv = new DataView(codeBytes.buffer, off, 4);
738
+ return dv.getFloat32(0, true);
739
+ }
740
+ return {
741
+ algorithm: "dreamdb.rabitq-cosine",
742
+ dim,
743
+ recordCodeBytes: codeBytesExpected,
744
+ rotateQuery(qNorm) {
745
+ const out = new Float32Array(dim);
746
+ for (let i = 0; i < dim; i++) {
747
+ let acc = 0;
748
+ const base = i * dim;
749
+ for (let k = 0; k < dim; k++) {
750
+ acc = Math.fround(acc + Math.fround(rotation[base + k] * qNorm[k]));
751
+ }
752
+ out[i] = acc;
753
+ }
754
+ return out;
755
+ },
756
+ adcScore(rotatedQuery, codeBytes) {
757
+ let sum = 0;
758
+ for (let i = 0; i < dim; i++) {
759
+ const bit = codeBytes[i >>> 3] >>> (i & 7) & 1;
760
+ const signed = bit === 1 ? rotatedQuery[i] : -rotatedQuery[i];
761
+ sum = Math.fround(sum + signed);
762
+ }
763
+ const scale = withCorrection ? readPerRecordScale(codeBytes) : constScale;
764
+ return Math.fround(sum * scale);
765
+ },
766
+ decode(codeBytes) {
767
+ if (codeBytes.length !== codeBytesExpected) {
768
+ throw new Error(
769
+ `rabitq codes len ${codeBytes.length} != expected ${codeBytesExpected}`
770
+ );
771
+ }
772
+ const scale = withCorrection ? readPerRecordScale(codeBytes) : constScale;
773
+ const uhat = new Float32Array(dim);
774
+ for (let i = 0; i < dim; i++) {
775
+ const bit = codeBytes[i >>> 3] >>> (i & 7) & 1;
776
+ uhat[i] = bit === 1 ? scale : -scale;
777
+ }
778
+ const out = new Float32Array(dim);
779
+ for (let j = 0; j < dim; j++) {
780
+ let acc = 0;
781
+ for (let i = 0; i < dim; i++) {
782
+ acc = Math.fround(acc + Math.fround(rotation[i * dim + j] * uhat[i]));
783
+ }
784
+ out[j] = acc;
785
+ }
786
+ return out;
787
+ }
788
+ };
789
+ }
790
+ function decodeBucketRecords(bytes, expectRecordSize, dim) {
791
+ if (bytes.length < 160) throw new Error("bucket too small for header");
792
+ if (bytes[0] !== 86 || bytes[1] !== 66 || bytes[2] !== 85 || bytes[3] !== 85) {
793
+ throw new Error("bucket bad magic");
794
+ }
795
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
796
+ const recordSize = view.getUint32(8, false);
797
+ const recordCount = view.getUint32(12, false);
798
+ const headerSize = view.getUint32(16, false);
799
+ if (headerSize !== 160 && headerSize !== 200) {
800
+ throw new Error(`bucket header_size=${headerSize} unsupported (expect 160 or 200)`);
801
+ }
802
+ if (recordSize !== expectRecordSize) {
803
+ throw new Error(`bucket record_size=${recordSize} != expected ${expectRecordSize}`);
804
+ }
805
+ const isCompressed = headerSize === 200;
806
+ const out = [];
807
+ for (let i = 0; i < recordCount; i++) {
808
+ const off = headerSize + i * recordSize;
809
+ const hi = view.getUint32(off, false);
810
+ const lo = view.getUint32(off + 4, false);
811
+ const anchor = Number(BigInt(hi) << 32n | BigInt(lo));
812
+ const recordPayload = bytes.subarray(off + 8, off + recordSize);
813
+ if (isCompressed) {
814
+ out.push({ anchor, ordinal: i, codes: new Uint8Array(recordPayload) });
815
+ } else {
816
+ const vec = new Float32Array(dim);
817
+ const vecView = new DataView(
818
+ recordPayload.buffer,
819
+ recordPayload.byteOffset,
820
+ recordPayload.byteLength
821
+ );
822
+ for (let j = 0; j < dim; j++) vec[j] = vecView.getFloat32(j * 4, true);
823
+ out.push({ anchor, ordinal: i, vec });
824
+ }
825
+ }
826
+ return out;
827
+ }
828
+ function decodeBucketAnchorsOnly(bytes) {
829
+ if (bytes.length < 160) throw new Error("bucket too small for header");
830
+ if (bytes[0] !== 86 || bytes[1] !== 66 || bytes[2] !== 85 || bytes[3] !== 85) {
831
+ throw new Error("bucket bad magic");
832
+ }
833
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
834
+ const recordSize = view.getUint32(8, false);
835
+ const recordCount = view.getUint32(12, false);
836
+ const headerSize = view.getUint32(16, false);
837
+ if (headerSize !== 160 && headerSize !== 200) {
838
+ throw new Error(`bucket header_size=${headerSize} unsupported (expect 160 or 200)`);
839
+ }
840
+ const out = [];
841
+ for (let i = 0; i < recordCount; i++) {
842
+ const off = headerSize + i * recordSize;
843
+ const hi = view.getUint32(off, false);
844
+ const lo = view.getUint32(off + 4, false);
845
+ out.push(Number(BigInt(hi) << 32n | BigInt(lo)));
846
+ }
847
+ return out;
848
+ }
849
+ function peekBucketHeader(bytes) {
850
+ if (bytes.length < 160) throw new Error("bucket too small for header");
851
+ if (bytes[0] !== 86 || bytes[1] !== 66 || bytes[2] !== 85 || bytes[3] !== 85) {
852
+ throw new Error("bucket bad magic");
853
+ }
854
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
855
+ const recordSize = view.getUint32(8, false);
856
+ const recordCount = view.getUint32(12, false);
857
+ const headerSize = view.getUint32(16, false);
858
+ return {
859
+ recordSize,
860
+ recordCount,
861
+ headerSize,
862
+ isCompressed: headerSize === 200,
863
+ vectorCompressorHash: headerSize === 200 && bytes.length >= 86 + 33 ? bytes.subarray(86, 86 + 33) : null
864
+ };
865
+ }
866
+
867
+ // src/space.ts
868
+ var Space = class _Space {
869
+ connectorBase;
870
+ manifestHash;
871
+ manifest;
872
+ refName;
873
+ backend;
874
+ // Caches
875
+ _siCache = /* @__PURE__ */ new Map();
876
+ _vcCache = /* @__PURE__ */ new Map();
877
+ _lastQueryStats = null;
878
+ constructor(opts) {
879
+ this.connectorBase = opts.connectorBase;
880
+ this.manifestHash = opts.manifestHash;
881
+ this.manifest = opts.manifest;
882
+ this.refName = opts.refName;
883
+ this.backend = opts.backend || null;
884
+ }
885
+ /**
886
+ * Open a Space from a space URI.
887
+ * If a Backend is provided, it is used; otherwise fetch-based HTTP access.
888
+ */
889
+ static async fromUri(uri, backend) {
890
+ const u = new URL(uri);
891
+ const parts = u.pathname.replace(/^\/+/, "").split("/");
892
+ if (parts.length < 2) {
893
+ throw new Error(`Space URI missing /refs/<name> or /manifests/<hash> suffix: ${uri}`);
894
+ }
895
+ const id = parts.pop();
896
+ const marker = parts.pop();
897
+ let kind;
898
+ if (marker === "refs") kind = "ref";
899
+ else if (marker === "manifests") kind = "manifest";
900
+ else throw new Error(`Space URI: expected /refs/ or /manifests/, got /${marker}/: ${uri}`);
901
+ const connectorBase = `${u.origin}/${parts.join("/")}`.replace(/\/$/, "");
902
+ let manifestHash;
903
+ let refName = null;
904
+ const fetchFn = async (path, noCache = false) => {
905
+ if (backend) return backend.get(path, { noCache });
906
+ const url = `${connectorBase}/${path}`;
907
+ const fetchOpts = noCache ? { cache: "no-store" } : {};
908
+ const r = await fetch(url, fetchOpts);
909
+ if (!r.ok) throw new Error(`GET ${url}: HTTP ${r.status}`);
910
+ return new Uint8Array(await r.arrayBuffer());
911
+ };
912
+ if (kind === "ref") {
913
+ refName = id;
914
+ const refBytes = await fetchFn(`refs/${id}`, true);
915
+ if (refBytes.length !== MULTIHASH_BYTES) {
916
+ throw new Error(`ref body not ${MULTIHASH_BYTES} bytes: got ${refBytes.length}`);
917
+ }
918
+ manifestHash = bytesToBase32(refBytes);
919
+ } else {
920
+ manifestHash = id;
921
+ }
922
+ const manifestBytes = await fetchFn(`manifests/${manifestHash}`);
923
+ const manifest = decodeCbor(manifestBytes);
924
+ return new _Space({ connectorBase, manifestHash, manifest, refName, backend });
925
+ }
926
+ /** Get the timeline ID (base32 hash of the first timeline entry). */
927
+ timelineId() {
928
+ const t = this.manifest.timelines;
929
+ if (!t || !Array.isArray(t) || t.length === 0) {
930
+ throw new Error("Manifest has no timelines[]");
931
+ }
932
+ return bytesToBase32(t[0]);
933
+ }
934
+ /**
935
+ * Map each Manifest Track to the Schema-declared field name.
936
+ * Returns a parallel array to manifest.tracks.
937
+ */
938
+ _fieldNamesForTracks() {
939
+ const tracks = this.manifest.tracks;
940
+ if (!Array.isArray(tracks)) return [];
941
+ const out = new Array(tracks.length).fill(null);
942
+ const registry = this.manifest.registry;
943
+ const sch = registry?.["dreamdb.schema"];
944
+ const fields = sch && Array.isArray(sch.fields) ? sch.fields : null;
945
+ if (!fields) return out;
946
+ const expectedModalityFor = (f) => {
947
+ return modalityForField({
948
+ kind: f.kind,
949
+ mime: f.mime,
950
+ dim: f.dim ? Number(f.dim) : void 0,
951
+ name: f.name,
952
+ value_type: f.value_type
953
+ });
954
+ };
955
+ const queues = /* @__PURE__ */ new Map();
956
+ for (let i = 0; i < tracks.length; i++) {
957
+ const m = tracks[i].modality;
958
+ if (!queues.has(m)) queues.set(m, []);
959
+ queues.get(m).push(i);
960
+ }
961
+ for (const f of fields) {
962
+ const want = expectedModalityFor(f);
963
+ if (!want) continue;
964
+ const q = queues.get(want);
965
+ if (!q || q.length === 0) continue;
966
+ const idx = q.shift();
967
+ out[idx] = f.name;
968
+ }
969
+ return out;
970
+ }
971
+ /** List resolved tracks from this Manifest. */
972
+ tracks() {
973
+ const out = [];
974
+ const ts = this.manifest.tracks;
975
+ if (!Array.isArray(ts)) return out;
976
+ const fieldNames = this._fieldNamesForTracks();
977
+ for (let i = 0; i < ts.length; i++) {
978
+ const t = ts[i];
979
+ const field = fieldNames[i] || null;
980
+ out.push({
981
+ modality: t.modality,
982
+ field,
983
+ key: field || t.modality,
984
+ kind: t.kind,
985
+ role: t.role,
986
+ address: bytesToBase32(t.address),
987
+ timeline: bytesToBase32(t.timeline),
988
+ coverage: t.coverage
989
+ });
990
+ }
991
+ return out;
992
+ }
993
+ /** Find a Track by key (field name or modality). */
994
+ trackFor(keyOrModality) {
995
+ return this.tracks().find(
996
+ (t) => t.key === keyOrModality || t.modality === keyOrModality
997
+ );
998
+ }
999
+ /** Walk the Manifest DAG and return history entries. */
1000
+ async history(maxDepth = 50) {
1001
+ const out = [];
1002
+ let curHash = this.manifestHash;
1003
+ let cur = this.manifest;
1004
+ while (curHash && out.length < maxDepth) {
1005
+ out.push({
1006
+ manifestHash: curHash,
1007
+ ts: typeof cur.ts === "bigint" ? Number(cur.ts) : Number(cur.ts || 0),
1008
+ writer: cur.writer || "(unknown)",
1009
+ tracks: Array.isArray(cur.tracks) ? cur.tracks.map((t) => ({
1010
+ modality: t.modality,
1011
+ address: bytesToBase32(t.address)
1012
+ })) : [],
1013
+ parents: Array.isArray(cur.parents) ? cur.parents.length : 0
1014
+ });
1015
+ const parents = cur.parents || [];
1016
+ if (parents.length === 0) break;
1017
+ const parentHash = bytesToBase32(parents[0]);
1018
+ try {
1019
+ const parentBytes = await this._fetchBytes(`manifests/${parentHash}`);
1020
+ cur = decodeCbor(parentBytes);
1021
+ curHash = parentHash;
1022
+ } catch (e) {
1023
+ out[out.length - 1].truncatedAt = e.message;
1024
+ break;
1025
+ }
1026
+ }
1027
+ return out;
1028
+ }
1029
+ /** Get the last query's statistics. */
1030
+ get lastQueryStats() {
1031
+ return this._lastQueryStats;
1032
+ }
1033
+ // ---- Vector query ----
1034
+ async queryVector(field, queryVec, opts = {}) {
1035
+ const topK = typeof opts === "number" ? opts : opts.topK || 10;
1036
+ const probeCountOverride = typeof opts === "object" && opts.probeCount ? opts.probeCount : null;
1037
+ const maxHamming = typeof opts === "object" && opts.maxHamming ? opts.maxHamming : 2;
1038
+ const track = this._embeddingTrackFor(field);
1039
+ if (!track) throw new Error(`no embedding Track found for field "${field}"`);
1040
+ const dimMatch = /\.dim=(\d+)\./.exec(track.modality);
1041
+ if (!dimMatch) throw new Error(`embedding Track modality lacks dim=N: ${track.modality}`);
1042
+ const dim = parseInt(dimMatch[1], 10);
1043
+ if (queryVec.length !== dim) {
1044
+ throw new Error(`query vec dim ${queryVec.length} != Track dim ${dim}`);
1045
+ }
1046
+ const compressorDecoder = await this._fetchVectorCompressor(track.modality);
1047
+ const recordSize = compressorDecoder ? 8 + compressorDecoder.recordCodeBytes : 8 + dim * 4;
1048
+ const trackBytes = await this._fetchBytes(
1049
+ `${track.timeline}/${track.modality}/track/${track.address}`
1050
+ );
1051
+ const trackObj = decodeCbor(trackBytes);
1052
+ const objIndex = trackObj.object_index;
1053
+ if (!Array.isArray(objIndex)) {
1054
+ throw new Error("queryVector: paged Track index not supported in TS yet");
1055
+ }
1056
+ const dispatcher = await this._fetchSpatialDispatcher(track.modality);
1057
+ let probeCount = probeCountOverride;
1058
+ if (probeCount == null) {
1059
+ if (dispatcher && dispatcher.algorithm === "dreamdb.ivf-cosine") {
1060
+ probeCount = Math.max(8, Math.ceil(dispatcher.k / 16));
1061
+ } else {
1062
+ probeCount = 64;
1063
+ }
1064
+ }
1065
+ let probeKeySet = null;
1066
+ if (dispatcher) {
1067
+ const qNormForDispatch = normalizeL2F32(
1068
+ queryVec instanceof Float32Array ? queryVec : new Float32Array(queryVec)
1069
+ );
1070
+ if (!qNormForDispatch)
1071
+ throw new Error("queryVector: query vector has zero norm");
1072
+ const probeKeys = dispatcher.probeKeys(
1073
+ qNormForDispatch,
1074
+ probeCount,
1075
+ maxHamming
1076
+ );
1077
+ probeKeySet = new Set(probeKeys);
1078
+ }
1079
+ let entriesToFetch = probeKeySet ? objIndex.filter(
1080
+ (e) => probeKeySet.has(e[0])
1081
+ ) : objIndex;
1082
+ const dispatchedCount = entriesToFetch.length;
1083
+ if (probeKeySet && entriesToFetch.length === 0) {
1084
+ entriesToFetch = objIndex;
1085
+ }
1086
+ this._lastQueryStats = {
1087
+ bucketsTotal: objIndex.length,
1088
+ bucketsProbed: dispatchedCount,
1089
+ fellBackToBruteForce: probeKeySet !== null && dispatchedCount === 0
1090
+ };
1091
+ const qNorm = normalizeL2(
1092
+ queryVec instanceof Float32Array ? queryVec : new Float32Array(queryVec)
1093
+ );
1094
+ let rotatedQuery = null;
1095
+ if (compressorDecoder && compressorDecoder.algorithm === "dreamdb.rabitq-cosine" && compressorDecoder.rotateQuery) {
1096
+ rotatedQuery = compressorDecoder.rotateQuery(qNorm);
1097
+ }
1098
+ const candidates = [];
1099
+ for (const e of entriesToFetch) {
1100
+ const entry = e;
1101
+ const spatialKey = entry[0];
1102
+ const bucketAddr = bytesToBase32(entry[4]);
1103
+ let vsHashB32 = null;
1104
+ if (entry.length >= 7 && entry[6] instanceof Uint8Array) {
1105
+ vsHashB32 = bytesToBase32(entry[6]);
1106
+ }
1107
+ const body = await this._fetchBytes(
1108
+ `${track.timeline}/${track.modality}/${spatialKey}/${bucketAddr}`
1109
+ );
1110
+ for (const rec of decodeBucketRecords(body, recordSize, dim)) {
1111
+ let score;
1112
+ if (rec.vec) {
1113
+ score = dotL2Normalized(qNorm, normalizeL2(rec.vec));
1114
+ } else if (rec.codes && rotatedQuery && compressorDecoder?.adcScore) {
1115
+ score = compressorDecoder.adcScore(rotatedQuery, rec.codes);
1116
+ } else if (rec.codes && compressorDecoder) {
1117
+ const candidate = compressorDecoder.decode(rec.codes);
1118
+ score = dotL2Normalized(qNorm, normalizeL2(candidate));
1119
+ } else {
1120
+ continue;
1121
+ }
1122
+ candidates.push({
1123
+ anchor: rec.anchor,
1124
+ score,
1125
+ vsHashB32,
1126
+ recordOrdinal: rec.ordinal
1127
+ });
1128
+ }
1129
+ }
1130
+ candidates.sort((a, b) => b.score - a.score);
1131
+ const T = Math.min(candidates.length, 5 * topK);
1132
+ const survivors = candidates.slice(0, T);
1133
+ const rerankableByHash = /* @__PURE__ */ new Map();
1134
+ let rerankSkippedNoHash = 0;
1135
+ for (const s of survivors) {
1136
+ if (s.vsHashB32) {
1137
+ if (!rerankableByHash.has(s.vsHashB32))
1138
+ rerankableByHash.set(s.vsHashB32, []);
1139
+ rerankableByHash.get(s.vsHashB32).push(s);
1140
+ } else {
1141
+ rerankSkippedNoHash++;
1142
+ }
1143
+ }
1144
+ const vsRecordSize = dim * 4;
1145
+ const VS_HEADER_SIZE = 128;
1146
+ for (const [vsHashB32, group] of rerankableByHash) {
1147
+ let vsBytes;
1148
+ try {
1149
+ vsBytes = await this._fetchBytes(
1150
+ `${track.timeline}/${track.modality}/vectors/${vsHashB32}`
1151
+ );
1152
+ } catch {
1153
+ rerankSkippedNoHash += group.length;
1154
+ continue;
1155
+ }
1156
+ const vsView = new DataView(
1157
+ vsBytes.buffer,
1158
+ vsBytes.byteOffset,
1159
+ vsBytes.byteLength
1160
+ );
1161
+ for (const s of group) {
1162
+ const off = VS_HEADER_SIZE + s.recordOrdinal * vsRecordSize;
1163
+ if (off + vsRecordSize > vsBytes.length) {
1164
+ rerankSkippedNoHash++;
1165
+ continue;
1166
+ }
1167
+ const rawVec = new Float32Array(dim);
1168
+ for (let j = 0; j < dim; j++) {
1169
+ rawVec[j] = vsView.getFloat32(off + j * 4, true);
1170
+ }
1171
+ s.score = dotL2Normalized(qNorm, normalizeL2(rawVec));
1172
+ }
1173
+ }
1174
+ survivors.sort((a, b) => b.score - a.score);
1175
+ const finalTop = survivors.slice(0, topK).map((s) => ({
1176
+ anchor: s.anchor,
1177
+ score: s.score
1178
+ }));
1179
+ this._lastQueryStats = {
1180
+ ...this._lastQueryStats,
1181
+ candidatesScored: candidates.length,
1182
+ topT: T,
1183
+ rerankFetchCount: rerankableByHash.size,
1184
+ rerankSkippedNoHash
1185
+ };
1186
+ return finalTop;
1187
+ }
1188
+ // ---- Internal helpers ----
1189
+ _embeddingTrackFor(field) {
1190
+ const tracks = this.tracks().filter(
1191
+ (t) => t.modality.startsWith("embedding.")
1192
+ );
1193
+ if (tracks.length === 0) return null;
1194
+ if (tracks.length === 1) return tracks[0];
1195
+ return tracks.find((t) => t.key === field || t.modality.includes(field)) || tracks[0];
1196
+ }
1197
+ async _fetchBytes(path) {
1198
+ if (this.backend) {
1199
+ return this.backend.get(path);
1200
+ }
1201
+ const url = `${this.connectorBase}/${path}`;
1202
+ const r = await fetch(url);
1203
+ if (!r.ok) throw new Error(`GET ${url}: HTTP ${r.status}`);
1204
+ return new Uint8Array(await r.arrayBuffer());
1205
+ }
1206
+ async _fetchSpatialDispatcher(modality) {
1207
+ if (this._siCache.has(modality)) return this._siCache.get(modality);
1208
+ const registry = this.manifest.registry;
1209
+ if (!registry || typeof registry !== "object") {
1210
+ this._siCache.set(modality, null);
1211
+ return null;
1212
+ }
1213
+ const regEntry = registry[modality];
1214
+ if (!regEntry || typeof regEntry !== "object") {
1215
+ this._siCache.set(modality, null);
1216
+ return null;
1217
+ }
1218
+ const hashesArr = regEntry.spatial_index || regEntry.spatial_index_hashes;
1219
+ if (!Array.isArray(hashesArr) || hashesArr.length === 0) {
1220
+ this._siCache.set(modality, null);
1221
+ return null;
1222
+ }
1223
+ const siHashBytes = hashesArr[0];
1224
+ const siHashB32 = bytesToBase32(siHashBytes);
1225
+ let siBytes;
1226
+ try {
1227
+ siBytes = await this._fetchBytes(`spatial-index/${siHashB32}`);
1228
+ } catch {
1229
+ this._siCache.set(modality, null);
1230
+ return null;
1231
+ }
1232
+ const siObj = decodeCbor(siBytes);
1233
+ const dim = Number(siObj.dim);
1234
+ const bits = Number(siObj.bits);
1235
+ let dispatcher = null;
1236
+ if (siObj.algorithm === "dreamdb.lsh-cosine") {
1237
+ const params = siObj.params;
1238
+ let hyperplanes;
1239
+ if (params.explicit_hyperplanes) {
1240
+ const hpBytes = params.explicit_hyperplanes;
1241
+ const view = new DataView(
1242
+ hpBytes.buffer,
1243
+ hpBytes.byteOffset,
1244
+ hpBytes.byteLength
1245
+ );
1246
+ hyperplanes = new Float32Array(dim * bits);
1247
+ for (let i = 0; i < dim * bits; i++)
1248
+ hyperplanes[i] = view.getFloat32(i * 4, true);
1249
+ } else if (params.seed) {
1250
+ hyperplanes = deriveHyperplanesLshCosine(
1251
+ params.seed,
1252
+ dim,
1253
+ bits
1254
+ );
1255
+ } else {
1256
+ this._siCache.set(modality, null);
1257
+ return null;
1258
+ }
1259
+ dispatcher = {
1260
+ algorithm: "dreamdb.lsh-cosine",
1261
+ dim,
1262
+ bits,
1263
+ probeKeys(qNorm, probeCount, maxHamming) {
1264
+ const projections = projectionsLshCosine(
1265
+ qNorm,
1266
+ hyperplanes,
1267
+ dim,
1268
+ bits
1269
+ );
1270
+ return multiProbeKeys(projections, probeCount, maxHamming);
1271
+ }
1272
+ };
1273
+ } else if (siObj.algorithm === "dreamdb.ivf-cosine") {
1274
+ const k = Number(siObj.params.k);
1275
+ const centroidBytes = siObj.params.centroids;
1276
+ if (!(centroidBytes instanceof Uint8Array) || centroidBytes.length !== k * dim * 4) {
1277
+ this._siCache.set(modality, null);
1278
+ return null;
1279
+ }
1280
+ const aligned = new Uint8Array(centroidBytes.length);
1281
+ aligned.set(centroidBytes);
1282
+ const centroidsF32 = new Float32Array(aligned.buffer);
1283
+ dispatcher = {
1284
+ algorithm: "dreamdb.ivf-cosine",
1285
+ dim,
1286
+ bits,
1287
+ k,
1288
+ probeKeys(qNorm, probeCount, _maxHamming) {
1289
+ const nprobe = Math.min(probeCount, k);
1290
+ const scores = new Array(k);
1291
+ for (let i = 0; i < k; i++) {
1292
+ let acc = 0;
1293
+ const base = i * dim;
1294
+ for (let d = 0; d < dim; d++) {
1295
+ acc = Math.fround(
1296
+ acc + Math.fround(qNorm[d] * centroidsF32[base + d])
1297
+ );
1298
+ }
1299
+ scores[i] = [acc, i];
1300
+ }
1301
+ scores.sort((a, b) => b[0] - a[0]);
1302
+ const out = [];
1303
+ for (let i = 0; i < nprobe; i++) {
1304
+ const id = scores[i][1];
1305
+ let key = "";
1306
+ for (let b = bits - 1; b >= 0; b--) {
1307
+ key += id >> b & 1 ? "1" : "0";
1308
+ }
1309
+ out.push(key);
1310
+ }
1311
+ return out;
1312
+ }
1313
+ };
1314
+ }
1315
+ this._siCache.set(modality, dispatcher);
1316
+ return dispatcher;
1317
+ }
1318
+ async _fetchVectorCompressor(modality) {
1319
+ if (this._vcCache.has(modality)) return this._vcCache.get(modality);
1320
+ const registry = this.manifest.registry;
1321
+ if (!registry || typeof registry !== "object") {
1322
+ this._vcCache.set(modality, null);
1323
+ return null;
1324
+ }
1325
+ const regEntry = registry[modality];
1326
+ if (!regEntry || typeof regEntry !== "object") {
1327
+ this._vcCache.set(modality, null);
1328
+ return null;
1329
+ }
1330
+ const vcHashBytes = regEntry.vector_compressor;
1331
+ if (!(vcHashBytes instanceof Uint8Array)) {
1332
+ this._vcCache.set(modality, null);
1333
+ return null;
1334
+ }
1335
+ const vcHashB32 = bytesToBase32(vcHashBytes);
1336
+ let vcBytes;
1337
+ try {
1338
+ vcBytes = await this._fetchBytes(`vector-compressor/${vcHashB32}`);
1339
+ } catch {
1340
+ this._vcCache.set(modality, null);
1341
+ return null;
1342
+ }
1343
+ const peek = decodeCbor(vcBytes);
1344
+ let decoder;
1345
+ if (peek && peek.algorithm === "dreamdb.pq-cosine") {
1346
+ decoder = buildPqCosineDecoder(vcBytes);
1347
+ } else if (peek && peek.algorithm === "dreamdb.rabitq-cosine") {
1348
+ decoder = buildRabitqCosineDecoder(vcBytes);
1349
+ } else {
1350
+ this._vcCache.set(modality, null);
1351
+ return null;
1352
+ }
1353
+ decoder.algorithm = peek.algorithm || decoder.algorithm;
1354
+ if (peek.algorithm === "dreamdb.pq-cosine") {
1355
+ decoder.recordCodeBytes = Number(
1356
+ peek.params.m
1357
+ );
1358
+ } else {
1359
+ const payload = Math.ceil(Number(peek.dim) / 8);
1360
+ const corrected = peek.params && peek.params.with_correction_factors === true;
1361
+ decoder.recordCodeBytes = corrected ? payload + 4 : payload;
1362
+ }
1363
+ this._vcCache.set(modality, decoder);
1364
+ return decoder;
1365
+ }
1366
+ };
1367
+
1368
+ // src/dataset.ts
1369
+ var Schema = class {
1370
+ fields = [];
1371
+ addImage(name, opts = {}) {
1372
+ this.fields.push({
1373
+ kind: "image",
1374
+ name,
1375
+ mime: opts.mime || "jpeg",
1376
+ required: opts.required !== false,
1377
+ chunkSize: opts.chunkSize,
1378
+ packItems: opts.packItems
1379
+ });
1380
+ return this;
1381
+ }
1382
+ addAudio(name, opts = {}) {
1383
+ this.fields.push({
1384
+ kind: "audio",
1385
+ name,
1386
+ mime: opts.mime || "wav",
1387
+ required: opts.required !== false,
1388
+ chunkSize: opts.chunkSize,
1389
+ packItems: opts.packItems
1390
+ });
1391
+ return this;
1392
+ }
1393
+ addVideo(name, opts = {}) {
1394
+ this.fields.push({
1395
+ kind: "video",
1396
+ name,
1397
+ mime: opts.mime || "mp4",
1398
+ required: opts.required !== false,
1399
+ chunkSize: opts.chunkSize,
1400
+ packItems: opts.packItems
1401
+ });
1402
+ return this;
1403
+ }
1404
+ addEmbedding(name, opts) {
1405
+ this.fields.push({
1406
+ kind: "embedding",
1407
+ name,
1408
+ dim: opts.dim,
1409
+ algorithm: opts.algorithm || "dreamdb.lsh-cosine",
1410
+ required: opts.required !== false,
1411
+ lshBits: opts.lshBits,
1412
+ compressor: opts.compressor,
1413
+ spatialIndex: opts.spatialIndex,
1414
+ rerank: opts.rerank || false
1415
+ });
1416
+ return this;
1417
+ }
1418
+ addScalarCategorical(name, opts = {}) {
1419
+ this.fields.push({
1420
+ kind: "scalar",
1421
+ name,
1422
+ valueType: "categorical",
1423
+ required: opts.required !== false
1424
+ });
1425
+ return this;
1426
+ }
1427
+ addScalarBool(name, opts = {}) {
1428
+ this.fields.push({
1429
+ kind: "scalar",
1430
+ name,
1431
+ valueType: "bool",
1432
+ required: opts.required !== false
1433
+ });
1434
+ return this;
1435
+ }
1436
+ addScalarInt(name, opts = {}) {
1437
+ this.fields.push({
1438
+ kind: "scalar",
1439
+ name,
1440
+ valueType: "int",
1441
+ required: opts.required !== false
1442
+ });
1443
+ return this;
1444
+ }
1445
+ addScalarFloat(name, opts = {}) {
1446
+ this.fields.push({
1447
+ kind: "scalar",
1448
+ name,
1449
+ valueType: "float",
1450
+ required: opts.required !== false
1451
+ });
1452
+ return this;
1453
+ }
1454
+ addScalarString(name, opts = {}) {
1455
+ this.fields.push({
1456
+ kind: "scalar",
1457
+ name,
1458
+ valueType: "string",
1459
+ required: opts.required !== false
1460
+ });
1461
+ return this;
1462
+ }
1463
+ addScalarTimestamp(name, opts = {}) {
1464
+ this.fields.push({
1465
+ kind: "scalar",
1466
+ name,
1467
+ valueType: "timestamp",
1468
+ required: opts.required !== false
1469
+ });
1470
+ return this;
1471
+ }
1472
+ /** Serialize the schema to CBOR-encodable object. */
1473
+ toCbor() {
1474
+ const fields = this.fields.map((f) => {
1475
+ const obj = { kind: f.kind, name: f.name };
1476
+ if (f.kind === "image" || f.kind === "audio" || f.kind === "video") {
1477
+ obj.mime = f.mime;
1478
+ obj.required = f.required;
1479
+ } else if (f.kind === "embedding") {
1480
+ obj.dim = f.dim;
1481
+ obj.algorithm = f.algorithm;
1482
+ obj.required = f.required;
1483
+ obj.rerank = f.rerank;
1484
+ } else if (f.kind === "scalar") {
1485
+ obj.value_type = f.valueType;
1486
+ obj.required = f.required;
1487
+ }
1488
+ return obj;
1489
+ });
1490
+ return { fields };
1491
+ }
1492
+ };
1493
+ var Dataset = class _Dataset {
1494
+ backend;
1495
+ _refName;
1496
+ _manifestHash;
1497
+ _timelineHash;
1498
+ _schema;
1499
+ constructor(backend, refName, manifestHash, timelineHash, schema) {
1500
+ this.backend = backend;
1501
+ this._refName = refName;
1502
+ this._manifestHash = manifestHash;
1503
+ this._timelineHash = timelineHash;
1504
+ this._schema = schema;
1505
+ }
1506
+ // ---- Construction ----
1507
+ static async create(name, schema, backendUrl) {
1508
+ const backend = resolveBackend(backendUrl);
1509
+ const timelineBytes = hashFromString(`timeline:${name}`);
1510
+ const timelineHash = bytesToBase32(timelineBytes);
1511
+ const tracks = [];
1512
+ for (const field of schema.fields) {
1513
+ const modality = modalityForField({
1514
+ kind: field.kind,
1515
+ mime: field.kind === "image" || field.kind === "audio" || field.kind === "video" ? field.mime : void 0,
1516
+ dim: field.kind === "embedding" ? field.dim : void 0,
1517
+ name: field.name,
1518
+ valueType: field.kind === "scalar" ? field.valueType : void 0
1519
+ });
1520
+ if (!modality) continue;
1521
+ const emptyTrackObj = { object_index: [] };
1522
+ const trackObjBytes = encodeCbor(emptyTrackObj);
1523
+ const trackHash = contentHash(trackObjBytes);
1524
+ const trackHashB32 = bytesToBase32(trackHash);
1525
+ await backend.put(
1526
+ `${timelineHash}/${modality}/track/${trackHashB32}`,
1527
+ trackObjBytes
1528
+ );
1529
+ tracks.push({
1530
+ modality,
1531
+ kind: field.kind === "embedding" ? "spatial_bucket" : field.kind === "scalar" ? "scalar_bucket" : "fragment",
1532
+ role: "data",
1533
+ address: trackHash,
1534
+ timeline: timelineBytes,
1535
+ coverage: null
1536
+ });
1537
+ }
1538
+ const manifest = {
1539
+ timelines: [timelineBytes],
1540
+ tracks,
1541
+ ts: BigInt(Date.now()) * 1000000n,
1542
+ writer: "dreamdb-ts/0.1.0",
1543
+ registry: {
1544
+ "dreamdb.schema": schema.toCbor()
1545
+ }
1546
+ };
1547
+ const manifestBytes = encodeCbor(manifest);
1548
+ const manifestHash = contentHash(manifestBytes);
1549
+ const manifestHashB32 = bytesToBase32(manifestHash);
1550
+ await backend.put(`manifests/${manifestHashB32}`, manifestBytes);
1551
+ await backend.put(`refs/${name}`, manifestHash);
1552
+ return new _Dataset(backend, name, manifestHashB32, timelineHash, schema);
1553
+ }
1554
+ static async open(name, schema, backendUrl = "") {
1555
+ const backend = resolveBackend(backendUrl);
1556
+ const refBytes = await backend.get(`refs/${name}`);
1557
+ if (refBytes.length !== MULTIHASH_BYTES) {
1558
+ throw new Error(`ref body not ${MULTIHASH_BYTES} bytes: got ${refBytes.length}`);
1559
+ }
1560
+ const manifestHash = bytesToBase32(refBytes);
1561
+ const manifestBytes = await backend.get(`manifests/${manifestHash}`);
1562
+ const manifest = decodeCbor(manifestBytes);
1563
+ const timelines = manifest.timelines;
1564
+ if (!timelines || !Array.isArray(timelines) || timelines.length === 0) {
1565
+ throw new Error("Manifest has no timelines[]");
1566
+ }
1567
+ const timelineHash = bytesToBase32(timelines[0]);
1568
+ let resolvedSchema;
1569
+ if (schema) {
1570
+ resolvedSchema = schema;
1571
+ } else {
1572
+ const registry = manifest.registry;
1573
+ const schemaCbor = registry?.["dreamdb.schema"];
1574
+ if (schemaCbor && Array.isArray(schemaCbor.fields)) {
1575
+ resolvedSchema = schemaFromCbor(schemaCbor);
1576
+ } else {
1577
+ resolvedSchema = new Schema();
1578
+ }
1579
+ }
1580
+ return new _Dataset(backend, name, manifestHash, timelineHash, resolvedSchema);
1581
+ }
1582
+ // ---- Inspection ----
1583
+ refName() {
1584
+ return this._refName;
1585
+ }
1586
+ currentManifest() {
1587
+ return this._manifestHash;
1588
+ }
1589
+ timeline() {
1590
+ return this._timelineHash;
1591
+ }
1592
+ schema() {
1593
+ return this._schema;
1594
+ }
1595
+ async history(maxDepth = 50) {
1596
+ const out = [];
1597
+ let curHash = this._manifestHash;
1598
+ while (curHash && out.length < maxDepth) {
1599
+ let manifestBytes;
1600
+ try {
1601
+ manifestBytes = await this.backend.get(`manifests/${curHash}`);
1602
+ } catch {
1603
+ break;
1604
+ }
1605
+ const m = decodeCbor(manifestBytes);
1606
+ out.push({
1607
+ manifest: curHash,
1608
+ ts_ns: typeof m.ts === "bigint" ? Number(m.ts) : Number(m.ts || 0),
1609
+ writer: m.writer || "(unknown)",
1610
+ parents_count: Array.isArray(m.parents) ? m.parents.length : 0,
1611
+ tracks_count: Array.isArray(m.tracks) ? m.tracks.length : 0
1612
+ });
1613
+ const parents = m.parents;
1614
+ if (!parents || parents.length === 0) break;
1615
+ curHash = bytesToBase32(parents[0]);
1616
+ }
1617
+ return out;
1618
+ }
1619
+ async listRefs() {
1620
+ const keys = await this.backend.list("refs/");
1621
+ return keys.map((k) => k.replace(/^refs\//, "")).sort();
1622
+ }
1623
+ async count() {
1624
+ let n = 0;
1625
+ for await (const batch of this._iterStreamImpl(4096)) {
1626
+ n += batch._time_anchors.length;
1627
+ }
1628
+ return n;
1629
+ }
1630
+ // ---- Write path ----
1631
+ async appendMany(samples) {
1632
+ if (samples.length === 0) return 0;
1633
+ const manifestBytes = await this.backend.get(`manifests/${this._manifestHash}`);
1634
+ const manifest = decodeCbor(manifestBytes);
1635
+ const tracks = manifest.tracks;
1636
+ const hasExplicitAnchors = "_anchor" in samples[0];
1637
+ const baseUs = Date.now() * 1e3;
1638
+ const anchors = samples.map((s, i) => {
1639
+ if (hasExplicitAnchors) {
1640
+ return s._anchor;
1641
+ }
1642
+ return baseUs + i;
1643
+ });
1644
+ const newTracks = [];
1645
+ for (let ti = 0; ti < tracks.length; ti++) {
1646
+ const track = tracks[ti];
1647
+ const modality = track.modality;
1648
+ const field = this._schema.fields.find((f) => {
1649
+ const expectedMod = modalityForField({
1650
+ kind: f.kind,
1651
+ mime: f.kind === "image" || f.kind === "audio" || f.kind === "video" ? f.mime : void 0,
1652
+ dim: f.kind === "embedding" ? f.dim : void 0,
1653
+ name: f.name,
1654
+ valueType: f.kind === "scalar" ? f.valueType : void 0
1655
+ });
1656
+ return expectedMod === modality;
1657
+ });
1658
+ if (!field) {
1659
+ newTracks.push(track);
1660
+ continue;
1661
+ }
1662
+ const trackAddr = bytesToBase32(track.address);
1663
+ const trackBytes = await this.backend.get(
1664
+ `${this._timelineHash}/${modality}/track/${trackAddr}`
1665
+ );
1666
+ const trackObj = decodeCbor(trackBytes);
1667
+ const objIndex = trackObj.object_index || [];
1668
+ if (field.kind === "image" || field.kind === "audio" || field.kind === "video") {
1669
+ const newEntries = [...objIndex];
1670
+ for (let i = 0; i < samples.length; i++) {
1671
+ const value = samples[i][field.name];
1672
+ if (value === null || value === void 0) continue;
1673
+ const data = value instanceof Uint8Array ? value : new Uint8Array(value);
1674
+ const fragHash = contentHash(data);
1675
+ const fragHashB32 = bytesToBase32(fragHash);
1676
+ await this.backend.put(
1677
+ `${this._timelineHash}/${modality}/0000000000000000/${fragHashB32}`,
1678
+ data
1679
+ );
1680
+ newEntries.push([
1681
+ BigInt(anchors[i]),
1682
+ BigInt(anchors[i]),
1683
+ data.length,
1684
+ fragHash
1685
+ ]);
1686
+ }
1687
+ const newTrackObj = { object_index: newEntries };
1688
+ const newTrackBytes = encodeCbor(newTrackObj);
1689
+ const newTrackHash = contentHash(newTrackBytes);
1690
+ const newTrackHashB32 = bytesToBase32(newTrackHash);
1691
+ await this.backend.put(
1692
+ `${this._timelineHash}/${modality}/track/${newTrackHashB32}`,
1693
+ newTrackBytes
1694
+ );
1695
+ newTracks.push({ ...track, address: newTrackHash });
1696
+ } else if (field.kind === "embedding") {
1697
+ const embField = field;
1698
+ const dim = embField.dim;
1699
+ const lshBits = embField.lshBits || 12;
1700
+ const bucketGroups = /* @__PURE__ */ new Map();
1701
+ for (let i = 0; i < samples.length; i++) {
1702
+ const value = samples[i][field.name];
1703
+ if (value === null || value === void 0) continue;
1704
+ const vec = value instanceof Float32Array ? Array.from(value) : value;
1705
+ const normVec = normalizeL2(new Float32Array(vec));
1706
+ let key = "";
1707
+ for (let b = 0; b < lshBits; b++) {
1708
+ key += normVec[b % dim] >= 0 ? "1" : "0";
1709
+ }
1710
+ if (!bucketGroups.has(key)) bucketGroups.set(key, []);
1711
+ bucketGroups.get(key).push({ anchor: anchors[i], vec });
1712
+ }
1713
+ const newEntries = [...objIndex];
1714
+ for (const [spatialKey, records] of bucketGroups) {
1715
+ const recordSize = 8 + dim * 4;
1716
+ const headerSize = 160;
1717
+ const totalSize = headerSize + records.length * recordSize;
1718
+ const bucket = new Uint8Array(totalSize);
1719
+ const bucketView = new DataView(bucket.buffer);
1720
+ bucket[0] = 86;
1721
+ bucket[1] = 66;
1722
+ bucket[2] = 85;
1723
+ bucket[3] = 85;
1724
+ bucketView.setUint32(4, 1, false);
1725
+ bucketView.setUint32(8, recordSize, false);
1726
+ bucketView.setUint32(12, records.length, false);
1727
+ bucketView.setUint32(16, headerSize, false);
1728
+ for (let ri = 0; ri < records.length; ri++) {
1729
+ const off = headerSize + ri * recordSize;
1730
+ const anchor = records[ri].anchor;
1731
+ const anchorBig = BigInt(anchor);
1732
+ bucketView.setUint32(off, Number(anchorBig >> 32n), false);
1733
+ bucketView.setUint32(off + 4, Number(anchorBig & 0xffffffffn), false);
1734
+ for (let d = 0; d < dim; d++) {
1735
+ bucketView.setFloat32(off + 8 + d * 4, records[ri].vec[d], true);
1736
+ }
1737
+ }
1738
+ const bucketHash = contentHash(bucket);
1739
+ const bucketHashB32 = bytesToBase32(bucketHash);
1740
+ await this.backend.put(
1741
+ `${this._timelineHash}/${modality}/${spatialKey}/${bucketHashB32}`,
1742
+ bucket
1743
+ );
1744
+ const tAnchors = records.map((r) => r.anchor).sort((a, b) => a - b);
1745
+ newEntries.push([
1746
+ spatialKey,
1747
+ BigInt(tAnchors[0]),
1748
+ BigInt(tAnchors[tAnchors.length - 1]),
1749
+ totalSize,
1750
+ bucketHash
1751
+ ]);
1752
+ }
1753
+ const newTrackObj = { object_index: newEntries };
1754
+ const newTrackBytes = encodeCbor(newTrackObj);
1755
+ const newTrackHash = contentHash(newTrackBytes);
1756
+ const newTrackHashB32 = bytesToBase32(newTrackHash);
1757
+ await this.backend.put(
1758
+ `${this._timelineHash}/${modality}/track/${newTrackHashB32}`,
1759
+ newTrackBytes
1760
+ );
1761
+ newTracks.push({ ...track, address: newTrackHash });
1762
+ } else if (field.kind === "scalar") {
1763
+ const valGroups = /* @__PURE__ */ new Map();
1764
+ for (let i = 0; i < samples.length; i++) {
1765
+ const value = samples[i][field.name];
1766
+ if (value === null || value === void 0) continue;
1767
+ const key = String(value);
1768
+ if (!valGroups.has(key)) valGroups.set(key, []);
1769
+ valGroups.get(key).push(anchors[i]);
1770
+ }
1771
+ const newEntries = [...objIndex];
1772
+ for (const [valueStr, anchorList] of valGroups) {
1773
+ const anchorsCbor = anchorList.map((a) => BigInt(a));
1774
+ const bucketBytes = encodeCbor(anchorsCbor);
1775
+ const bucketHash = contentHash(bucketBytes);
1776
+ const bucketHashB32 = bytesToBase32(bucketHash);
1777
+ await this.backend.put(
1778
+ `${this._timelineHash}/${modality}/bucket/${bucketHashB32}`,
1779
+ bucketBytes
1780
+ );
1781
+ const valueCbor = parseScalarString(valueStr, field.valueType);
1782
+ const valueCborBytes = encodeCbor(valueCbor);
1783
+ const sortedAnchors = anchorList.sort((a, b) => a - b);
1784
+ newEntries.push([
1785
+ valueCborBytes,
1786
+ BigInt(sortedAnchors[0]),
1787
+ BigInt(sortedAnchors[sortedAnchors.length - 1]),
1788
+ bucketHash
1789
+ ]);
1790
+ }
1791
+ const newTrackObj = { object_index: newEntries };
1792
+ const newTrackBytes = encodeCbor(newTrackObj);
1793
+ const newTrackHash = contentHash(newTrackBytes);
1794
+ const newTrackHashB32 = bytesToBase32(newTrackHash);
1795
+ await this.backend.put(
1796
+ `${this._timelineHash}/${modality}/track/${newTrackHashB32}`,
1797
+ newTrackBytes
1798
+ );
1799
+ newTracks.push({ ...track, address: newTrackHash });
1800
+ } else {
1801
+ newTracks.push(track);
1802
+ }
1803
+ }
1804
+ const oldManifestHash = base32ToBytes(this._manifestHash);
1805
+ const parentBytes = new Uint8Array(MULTIHASH_BYTES);
1806
+ parentBytes.set(oldManifestHash.subarray(0, MULTIHASH_BYTES));
1807
+ const newManifest = {
1808
+ timelines: manifest.timelines,
1809
+ tracks: newTracks,
1810
+ parents: [parentBytes],
1811
+ ts: BigInt(Date.now()) * 1000000n,
1812
+ writer: "dreamdb-ts/0.1.0",
1813
+ registry: manifest.registry || {}
1814
+ };
1815
+ const newManifestBytes = encodeCbor(newManifest);
1816
+ const newManifestHash = contentHash(newManifestBytes);
1817
+ const newManifestHashB32 = bytesToBase32(newManifestHash);
1818
+ await this.backend.put(`manifests/${newManifestHashB32}`, newManifestBytes);
1819
+ await this.backend.put(`refs/${this._refName}`, newManifestHash);
1820
+ this._manifestHash = newManifestHashB32;
1821
+ return samples.length;
1822
+ }
1823
+ // ---- Read path ----
1824
+ async iterVector(field, query, topK, batchSize = 64, opts = {}) {
1825
+ const manifestBytes = await this.backend.get(`manifests/${this._manifestHash}`);
1826
+ const manifest = decodeCbor(manifestBytes);
1827
+ const tracks = manifest.tracks;
1828
+ const embField = this._schema.fields.find(
1829
+ (f) => f.kind === "embedding" && f.name === field
1830
+ );
1831
+ if (!embField) throw new Error(`no embedding field "${field}" in schema`);
1832
+ const modality = modalityForField({
1833
+ kind: embField.kind,
1834
+ dim: embField.dim,
1835
+ name: embField.name
1836
+ });
1837
+ const dim = embField.dim;
1838
+ const track = tracks.find((t) => t.modality === modality);
1839
+ if (!track) throw new Error(`no Track for modality ${modality}`);
1840
+ const trackAddr = bytesToBase32(track.address);
1841
+ const trackBytes = await this.backend.get(
1842
+ `${this._timelineHash}/${modality}/track/${trackAddr}`
1843
+ );
1844
+ const trackObj = decodeCbor(trackBytes);
1845
+ const objIndex = trackObj.object_index;
1846
+ if (!Array.isArray(objIndex) || objIndex.length === 0) return [];
1847
+ const qNorm = normalizeL2(
1848
+ query instanceof Float32Array ? query : new Float32Array(query)
1849
+ );
1850
+ const recordSize = 8 + dim * 4;
1851
+ const candidates = [];
1852
+ for (const entry of objIndex) {
1853
+ const e = entry;
1854
+ const spatialKey = e[0];
1855
+ const bucketAddr = bytesToBase32(e[4]);
1856
+ const body = await this.backend.get(
1857
+ `${this._timelineHash}/${modality}/${spatialKey}/${bucketAddr}`
1858
+ );
1859
+ const view = new DataView(body.buffer, body.byteOffset, body.byteLength);
1860
+ const headerSize = view.getUint32(16, false);
1861
+ const recordCount = view.getUint32(12, false);
1862
+ const actualRecordSize = view.getUint32(8, false);
1863
+ for (let i = 0; i < recordCount; i++) {
1864
+ const off = headerSize + i * actualRecordSize;
1865
+ const hi = view.getUint32(off, false);
1866
+ const lo = view.getUint32(off + 4, false);
1867
+ const anchor = Number(BigInt(hi) << 32n | BigInt(lo));
1868
+ const vec = new Float32Array(dim);
1869
+ for (let d = 0; d < dim; d++) {
1870
+ vec[d] = view.getFloat32(off + 8 + d * 4, true);
1871
+ }
1872
+ const normVec = normalizeL2(vec);
1873
+ const score = dotL2Normalized(qNorm, normVec);
1874
+ candidates.push({ anchor, score, vec });
1875
+ }
1876
+ }
1877
+ candidates.sort((a, b) => b.score - a.score);
1878
+ let topCandidates = candidates.slice(0, topK);
1879
+ if (opts.whereEq && Object.keys(opts.whereEq).length > 0) {
1880
+ const anchorLabels = await this._resolveScalarLabels(
1881
+ manifest,
1882
+ tracks,
1883
+ opts.whereEq
1884
+ );
1885
+ topCandidates = topCandidates.filter((c) => {
1886
+ for (const [filterField, filterValue] of Object.entries(opts.whereEq)) {
1887
+ const labelMap = anchorLabels.get(filterField);
1888
+ if (!labelMap) return false;
1889
+ const anchorVal = labelMap.get(c.anchor);
1890
+ if (anchorVal === void 0 || String(anchorVal) !== String(filterValue))
1891
+ return false;
1892
+ }
1893
+ return true;
1894
+ });
1895
+ }
1896
+ const blobFields = this._schema.fields.filter(
1897
+ (f) => f.kind === "image" || f.kind === "audio" || f.kind === "video"
1898
+ );
1899
+ const scalarFields = this._schema.fields.filter((f) => f.kind === "scalar");
1900
+ const resultAnchors = new Set(topCandidates.map((c) => c.anchor));
1901
+ const blobData = /* @__PURE__ */ new Map();
1902
+ for (const bf of blobFields) {
1903
+ const bfMod = modalityForField({
1904
+ kind: bf.kind,
1905
+ mime: bf.mime,
1906
+ name: bf.name
1907
+ });
1908
+ const bfTrack = tracks.find((t) => t.modality === bfMod);
1909
+ if (!bfTrack) continue;
1910
+ const bfAddr = bytesToBase32(bfTrack.address);
1911
+ const bfTrackBytes = await this.backend.get(
1912
+ `${this._timelineHash}/${bfMod}/track/${bfAddr}`
1913
+ );
1914
+ const bfTrackObj = decodeCbor(bfTrackBytes);
1915
+ const bfObjIndex = bfTrackObj.object_index;
1916
+ if (!Array.isArray(bfObjIndex)) continue;
1917
+ const fieldData = /* @__PURE__ */ new Map();
1918
+ for (const entry of bfObjIndex) {
1919
+ const e = entry;
1920
+ const tStart = Number(e[0]);
1921
+ if (!resultAnchors.has(tStart)) continue;
1922
+ const fragHash = bytesToBase32(e[3]);
1923
+ try {
1924
+ const fragBytes = await this.backend.get(
1925
+ `${this._timelineHash}/${bfMod}/0000000000000000/${fragHash}`
1926
+ );
1927
+ fieldData.set(tStart, fragBytes);
1928
+ } catch {
1929
+ }
1930
+ }
1931
+ blobData.set(bf.name, fieldData);
1932
+ }
1933
+ const scalarData = /* @__PURE__ */ new Map();
1934
+ for (const sf of scalarFields) {
1935
+ const sfMod = modalityForField({
1936
+ kind: sf.kind,
1937
+ name: sf.name,
1938
+ valueType: sf.valueType
1939
+ });
1940
+ const sfTrack = tracks.find((t) => t.modality === sfMod);
1941
+ if (!sfTrack) continue;
1942
+ const sfAddr = bytesToBase32(sfTrack.address);
1943
+ const sfTrackBytes = await this.backend.get(
1944
+ `${this._timelineHash}/${sfMod}/track/${sfAddr}`
1945
+ );
1946
+ const sfTrackObj = decodeCbor(sfTrackBytes);
1947
+ const sfObjIndex = sfTrackObj.object_index;
1948
+ if (!Array.isArray(sfObjIndex)) continue;
1949
+ const fieldData = /* @__PURE__ */ new Map();
1950
+ for (const entry of sfObjIndex) {
1951
+ const e = entry;
1952
+ const valueCborBytes = e[0];
1953
+ const value = decodeCbor(valueCborBytes);
1954
+ const bucketHash = bytesToBase32(e[3]);
1955
+ try {
1956
+ const bucketBytes = await this.backend.get(
1957
+ `${this._timelineHash}/${sfMod}/bucket/${bucketHash}`
1958
+ );
1959
+ const anchorArray = decodeCbor(bucketBytes);
1960
+ if (Array.isArray(anchorArray)) {
1961
+ for (const a of anchorArray) {
1962
+ const anchor = Number(a);
1963
+ if (resultAnchors.has(anchor)) {
1964
+ fieldData.set(anchor, value);
1965
+ }
1966
+ }
1967
+ }
1968
+ } catch {
1969
+ }
1970
+ }
1971
+ scalarData.set(sf.name, fieldData);
1972
+ }
1973
+ const batches = [];
1974
+ for (let i = 0; i < topCandidates.length; i += batchSize) {
1975
+ const slice = topCandidates.slice(i, i + batchSize);
1976
+ const batch = {
1977
+ _time_anchors: slice.map((c) => c.anchor),
1978
+ [field]: slice.map((c) => Array.from(c.vec))
1979
+ };
1980
+ for (const bf of blobFields) {
1981
+ const fieldMap = blobData.get(bf.name);
1982
+ batch[bf.name] = slice.map(
1983
+ (c) => fieldMap?.get(c.anchor) ?? null
1984
+ );
1985
+ }
1986
+ for (const sf of scalarFields) {
1987
+ const fieldMap = scalarData.get(sf.name);
1988
+ batch[sf.name] = slice.map(
1989
+ (c) => fieldMap?.get(c.anchor) ?? null
1990
+ );
1991
+ }
1992
+ batches.push(batch);
1993
+ }
1994
+ return batches;
1995
+ }
1996
+ // ---- Streaming iteration ----
1997
+ async *_iterStreamImpl(batchSize) {
1998
+ const manifestBytes = await this.backend.get(`manifests/${this._manifestHash}`);
1999
+ const manifest = decodeCbor(manifestBytes);
2000
+ const tracks = manifest.tracks;
2001
+ const embField = this._schema.fields.find(
2002
+ (f) => f.kind === "embedding"
2003
+ );
2004
+ if (!embField) return;
2005
+ const modality = modalityForField({
2006
+ kind: embField.kind,
2007
+ dim: embField.dim,
2008
+ name: embField.name
2009
+ });
2010
+ const dim = embField.dim;
2011
+ const track = tracks.find((t) => t.modality === modality);
2012
+ if (!track) return;
2013
+ const trackAddr = bytesToBase32(track.address);
2014
+ const trackBytes = await this.backend.get(
2015
+ `${this._timelineHash}/${modality}/track/${trackAddr}`
2016
+ );
2017
+ const trackObj = decodeCbor(trackBytes);
2018
+ const objIndex = trackObj.object_index;
2019
+ if (!Array.isArray(objIndex)) return;
2020
+ let buffer = [];
2021
+ for (const entry of objIndex) {
2022
+ const e = entry;
2023
+ const spatialKey = e[0];
2024
+ const bucketAddr = bytesToBase32(e[4]);
2025
+ const body = await this.backend.get(
2026
+ `${this._timelineHash}/${modality}/${spatialKey}/${bucketAddr}`
2027
+ );
2028
+ const view = new DataView(body.buffer, body.byteOffset, body.byteLength);
2029
+ const headerSize = view.getUint32(16, false);
2030
+ const recordCount = view.getUint32(12, false);
2031
+ const recordSize = view.getUint32(8, false);
2032
+ for (let i = 0; i < recordCount; i++) {
2033
+ const off = headerSize + i * recordSize;
2034
+ const hi = view.getUint32(off, false);
2035
+ const lo = view.getUint32(off + 4, false);
2036
+ const anchor = Number(BigInt(hi) << 32n | BigInt(lo));
2037
+ buffer.push(anchor);
2038
+ if (buffer.length >= batchSize) {
2039
+ yield { _time_anchors: buffer };
2040
+ buffer = [];
2041
+ }
2042
+ }
2043
+ }
2044
+ if (buffer.length > 0) {
2045
+ yield { _time_anchors: buffer };
2046
+ }
2047
+ }
2048
+ async iterStream(batchSize = 256) {
2049
+ const batches = [];
2050
+ for await (const batch of this._iterStreamImpl(batchSize)) {
2051
+ batches.push(batch);
2052
+ }
2053
+ return batches;
2054
+ }
2055
+ // ---- Versioning ----
2056
+ async snapshot(label) {
2057
+ const manifestHash = base32ToBytes(this._manifestHash);
2058
+ const refBytes = new Uint8Array(MULTIHASH_BYTES);
2059
+ refBytes.set(manifestHash.subarray(0, MULTIHASH_BYTES));
2060
+ await this.backend.put(`refs/${label}`, refBytes);
2061
+ return {
2062
+ label,
2063
+ manifest: this._manifestHash,
2064
+ timeline: this._timelineHash
2065
+ };
2066
+ }
2067
+ async branch(newName) {
2068
+ const manifestHash = base32ToBytes(this._manifestHash);
2069
+ const refBytes = new Uint8Array(MULTIHASH_BYTES);
2070
+ refBytes.set(manifestHash.subarray(0, MULTIHASH_BYTES));
2071
+ await this.backend.put(`refs/${newName}`, refBytes);
2072
+ return new _Dataset(
2073
+ this.backend,
2074
+ newName,
2075
+ this._manifestHash,
2076
+ this._timelineHash,
2077
+ this._schema
2078
+ );
2079
+ }
2080
+ // ---- Scalar resolution helper ----
2081
+ async _resolveScalarLabels(manifest, tracks, whereEq) {
2082
+ const result = /* @__PURE__ */ new Map();
2083
+ for (const [filterField, _filterValue] of Object.entries(whereEq)) {
2084
+ const sf = this._schema.fields.find(
2085
+ (f) => f.kind === "scalar" && f.name === filterField
2086
+ );
2087
+ if (!sf) continue;
2088
+ const sfMod = modalityForField({
2089
+ kind: sf.kind,
2090
+ name: sf.name,
2091
+ valueType: sf.valueType
2092
+ });
2093
+ const sfTrack = tracks.find((t) => t.modality === sfMod);
2094
+ if (!sfTrack) continue;
2095
+ const sfAddr = bytesToBase32(sfTrack.address);
2096
+ const sfTrackBytes = await this.backend.get(
2097
+ `${this._timelineHash}/${sfMod}/track/${sfAddr}`
2098
+ );
2099
+ const sfTrackObj = decodeCbor(sfTrackBytes);
2100
+ const sfObjIndex = sfTrackObj.object_index;
2101
+ if (!Array.isArray(sfObjIndex)) continue;
2102
+ const fieldData = /* @__PURE__ */ new Map();
2103
+ for (const entry of sfObjIndex) {
2104
+ const e = entry;
2105
+ const valueCborBytes = e[0];
2106
+ const value = decodeCbor(valueCborBytes);
2107
+ const bucketHash = bytesToBase32(e[3]);
2108
+ try {
2109
+ const bucketBytes = await this.backend.get(
2110
+ `${this._timelineHash}/${sfMod}/bucket/${bucketHash}`
2111
+ );
2112
+ const anchorArray = decodeCbor(bucketBytes);
2113
+ if (Array.isArray(anchorArray)) {
2114
+ for (const a of anchorArray) {
2115
+ fieldData.set(Number(a), value);
2116
+ }
2117
+ }
2118
+ } catch {
2119
+ }
2120
+ }
2121
+ result.set(filterField, fieldData);
2122
+ }
2123
+ return result;
2124
+ }
2125
+ };
2126
+ function resolveBackend(url) {
2127
+ if (url === "memory://" || url === "") {
2128
+ return new MemoryBackend();
2129
+ }
2130
+ if (url.startsWith("file://")) {
2131
+ throw new Error("file:// backend not supported in the TypeScript SDK (browser-first)");
2132
+ }
2133
+ return new S3Backend(url);
2134
+ }
2135
+ function contentHash(data) {
2136
+ const hash = new Uint8Array(MULTIHASH_BYTES);
2137
+ hash[0] = 30;
2138
+ hash[1] = 31;
2139
+ const FNV_OFFSET = 0xcbf29ce484222325n;
2140
+ const FNV_PRIME = 0x100000001b3n;
2141
+ let h = FNV_OFFSET;
2142
+ for (let i = 0; i < data.length; i++) {
2143
+ h = h ^ BigInt(data[i]);
2144
+ h = h * FNV_PRIME & 0xffffffffffffffffn;
2145
+ }
2146
+ const buf = new DataView(new ArrayBuffer(8));
2147
+ buf.setBigUint64(0, h);
2148
+ for (let i = 0; i < 31; i++) {
2149
+ const byteIdx = i % 8;
2150
+ const seed = new Uint8Array(new ArrayBuffer(8));
2151
+ new DataView(seed.buffer).setBigUint64(0, h);
2152
+ hash[2 + i] = seed[byteIdx] ^ i * 158 + 55 & 255;
2153
+ h = h * FNV_PRIME + BigInt(i) & 0xffffffffffffffffn;
2154
+ }
2155
+ return hash;
2156
+ }
2157
+ function hashFromString(s) {
2158
+ const encoded = new TextEncoder().encode(s);
2159
+ return contentHash(encoded);
2160
+ }
2161
+ function parseScalarString(s, valueType) {
2162
+ switch (valueType) {
2163
+ case "bool":
2164
+ return s === "true";
2165
+ case "int":
2166
+ return parseInt(s, 10);
2167
+ case "float":
2168
+ return parseFloat(s);
2169
+ default:
2170
+ return s;
2171
+ }
2172
+ }
2173
+ function schemaFromCbor(obj) {
2174
+ const schema = new Schema();
2175
+ const fields = obj.fields;
2176
+ if (!Array.isArray(fields)) return schema;
2177
+ for (const f of fields) {
2178
+ const kind = f.kind;
2179
+ const name = f.name;
2180
+ if (kind === "image") {
2181
+ schema.addImage(name, {
2182
+ mime: f.mime || "jpeg",
2183
+ required: f.required !== false
2184
+ });
2185
+ } else if (kind === "audio") {
2186
+ schema.addAudio(name, {
2187
+ mime: f.mime || "wav",
2188
+ required: f.required !== false
2189
+ });
2190
+ } else if (kind === "video") {
2191
+ schema.addVideo(name, {
2192
+ mime: f.mime || "mp4",
2193
+ required: f.required !== false
2194
+ });
2195
+ } else if (kind === "embedding") {
2196
+ schema.addEmbedding(name, {
2197
+ dim: Number(f.dim),
2198
+ algorithm: f.algorithm || "dreamdb.lsh-cosine",
2199
+ required: f.required !== false,
2200
+ rerank: f.rerank === true
2201
+ });
2202
+ } else if (kind === "scalar") {
2203
+ const vt = f.value_type || "categorical";
2204
+ switch (vt) {
2205
+ case "categorical":
2206
+ schema.addScalarCategorical(name);
2207
+ break;
2208
+ case "bool":
2209
+ schema.addScalarBool(name);
2210
+ break;
2211
+ case "int":
2212
+ schema.addScalarInt(name);
2213
+ break;
2214
+ case "float":
2215
+ schema.addScalarFloat(name);
2216
+ break;
2217
+ case "string":
2218
+ schema.addScalarString(name);
2219
+ break;
2220
+ case "timestamp":
2221
+ schema.addScalarTimestamp(name);
2222
+ break;
2223
+ }
2224
+ }
2225
+ }
2226
+ return schema;
2227
+ }
2228
+
2229
+ // src/types.ts
2230
+ var SCALAR_ENCODING_MAP = {
2231
+ categorical: "cat",
2232
+ bool: "bool",
2233
+ int: "i64",
2234
+ float: "f64",
2235
+ string: "str",
2236
+ timestamp: "ts"
2237
+ };
2238
+ // Annotate the CommonJS export names for ESM import in node:
2239
+ 0 && (module.exports = {
2240
+ Dataset,
2241
+ MULTIHASH_BYTES,
2242
+ MemoryBackend,
2243
+ S3Backend,
2244
+ SCALAR_ENCODING_MAP,
2245
+ Schema,
2246
+ Space,
2247
+ base32ToBytes,
2248
+ bitsFromProjections,
2249
+ bitsToBase2,
2250
+ buildPqCosineDecoder,
2251
+ buildRabitqCosineDecoder,
2252
+ bytesToBase32,
2253
+ chacha20Stream,
2254
+ decodeBucketAnchorsOnly,
2255
+ decodeBucketRecords,
2256
+ decodeCbor,
2257
+ deriveHyperplanesLshCosine,
2258
+ deriveRotationMatrix,
2259
+ dotF32,
2260
+ dotL2Normalized,
2261
+ encodeCbor,
2262
+ modalityForField,
2263
+ multiProbeKeys,
2264
+ normalizeL2,
2265
+ normalizeL2F32,
2266
+ parseSpaceUri,
2267
+ peekBucketHeader,
2268
+ projectionsLshCosine,
2269
+ scalarModalityFragment
2270
+ });
2271
+ //# sourceMappingURL=index.cjs.map