@soulcraft/cor 3.0.0-rc.1

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.
Files changed (87) hide show
  1. package/LICENSE +16 -0
  2. package/README.md +328 -0
  3. package/dist/aggregation/NativeAggregationEngine.d.ts +118 -0
  4. package/dist/aggregation/NativeAggregationEngine.js +186 -0
  5. package/dist/cli.d.ts +12 -0
  6. package/dist/cli.js +236 -0
  7. package/dist/graph/GraphAccelerationAdapter.d.ts +153 -0
  8. package/dist/graph/GraphAccelerationAdapter.js +326 -0
  9. package/dist/graph/NativeGraphAdjacencyIndex.d.ts +286 -0
  10. package/dist/graph/NativeGraphAdjacencyIndex.js +944 -0
  11. package/dist/hnsw/AdaptiveDiskAnnModeSelector.d.ts +187 -0
  12. package/dist/hnsw/AdaptiveDiskAnnModeSelector.js +313 -0
  13. package/dist/hnsw/NativeDiskAnnWrapper.d.ts +489 -0
  14. package/dist/hnsw/NativeDiskAnnWrapper.js +1456 -0
  15. package/dist/index.d.ts +28 -0
  16. package/dist/index.js +29 -0
  17. package/dist/legacyLayoutGuard.d.ts +93 -0
  18. package/dist/legacyLayoutGuard.js +237 -0
  19. package/dist/license/constants.d.ts +30 -0
  20. package/dist/license/constants.js +30 -0
  21. package/dist/license/onlineValidator.d.ts +43 -0
  22. package/dist/license/onlineValidator.js +225 -0
  23. package/dist/license/types.d.ts +39 -0
  24. package/dist/license/types.js +5 -0
  25. package/dist/license.d.ts +64 -0
  26. package/dist/license.js +165 -0
  27. package/dist/migration/MigrationCoordinator.d.ts +171 -0
  28. package/dist/migration/MigrationCoordinator.js +249 -0
  29. package/dist/migration/indexEpochGuard.d.ts +163 -0
  30. package/dist/migration/indexEpochGuard.js +202 -0
  31. package/dist/native/NativeEmbeddingEngine.d.ts +79 -0
  32. package/dist/native/NativeEmbeddingEngine.js +318 -0
  33. package/dist/native/NativeRoaringBitmap32.d.ts +114 -0
  34. package/dist/native/NativeRoaringBitmap32.js +221 -0
  35. package/dist/native/ffi.d.ts +20 -0
  36. package/dist/native/ffi.js +48 -0
  37. package/dist/native/idMapperTestSupport.d.ts +67 -0
  38. package/dist/native/idMapperTestSupport.js +112 -0
  39. package/dist/native/index.d.ts +49 -0
  40. package/dist/native/index.js +87 -0
  41. package/dist/native/napi.d.ts +21 -0
  42. package/dist/native/napi.js +88 -0
  43. package/dist/native/types.d.ts +1298 -0
  44. package/dist/native/types.js +16 -0
  45. package/dist/plugin.d.ts +50 -0
  46. package/dist/plugin.js +388 -0
  47. package/dist/providerContracts.d.ts +277 -0
  48. package/dist/providerContracts.js +38 -0
  49. package/dist/resource/OsMemoryProbe.d.ts +175 -0
  50. package/dist/resource/OsMemoryProbe.js +206 -0
  51. package/dist/resource/ResourceManager.d.ts +491 -0
  52. package/dist/resource/ResourceManager.js +960 -0
  53. package/dist/utils/ColumnManifest.d.ts +97 -0
  54. package/dist/utils/ColumnManifest.js +129 -0
  55. package/dist/utils/NativeColumnStore.d.ts +284 -0
  56. package/dist/utils/NativeColumnStore.js +685 -0
  57. package/dist/utils/NativeMetadataIndex.d.ts +882 -0
  58. package/dist/utils/NativeMetadataIndex.js +2631 -0
  59. package/dist/utils/NativeUnifiedCache.d.ts +87 -0
  60. package/dist/utils/NativeUnifiedCache.js +273 -0
  61. package/dist/utils/binaryIdMapperFactory.d.ts +59 -0
  62. package/dist/utils/binaryIdMapperFactory.js +94 -0
  63. package/dist/utils/collation.d.ts +30 -0
  64. package/dist/utils/collation.js +40 -0
  65. package/dist/utils/columnStoreTypes.d.ts +161 -0
  66. package/dist/utils/columnStoreTypes.js +29 -0
  67. package/dist/utils/nativeBinaryEntityIdMapper.d.ts +211 -0
  68. package/dist/utils/nativeBinaryEntityIdMapper.js +381 -0
  69. package/dist/utils/nativeEntityIdMapper.d.ts +111 -0
  70. package/dist/utils/nativeEntityIdMapper.js +170 -0
  71. package/docs/ADR-002-diskann-100-percent-rust.md +294 -0
  72. package/docs/ADR-003-semantic-time-travel.md +100 -0
  73. package/docs/aggregation.md +251 -0
  74. package/docs/comparison.md +162 -0
  75. package/docs/deployment-limits.md +87 -0
  76. package/docs/diskann.md +184 -0
  77. package/docs/migration-3.0.md +396 -0
  78. package/docs/performance-budget.md +274 -0
  79. package/docs/performance.md +117 -0
  80. package/docs/scaling.md +439 -0
  81. package/docs/snapshot-safety.md +246 -0
  82. package/docs/u64-id-space.md +214 -0
  83. package/docs/verification-report.md +670 -0
  84. package/native/brainy-native.node +0 -0
  85. package/native/index.d.ts +3916 -0
  86. package/package.json +92 -0
  87. package/scripts/migrate-cortex-2x-to-3x.mjs +970 -0
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Native Roaring Bitmap - Drop-in replacement for roaring-wasm
3
+ *
4
+ * Wraps the native Rust CRoaring module to provide the EXACT same API
5
+ * as roaring-wasm's RoaringBitmap32.
6
+ *
7
+ * CRoaring portable serialization format is binary-identical to
8
+ * roaring-wasm's portable format. Existing persisted indexes are
9
+ * readable without migration.
10
+ *
11
+ * All roaring bitmap consumers import from src/utils/roaring/index.ts —
12
+ * that module swaps the implementation to use this native wrapper.
13
+ */
14
+ import { loadNativeModule } from './index.js';
15
+ // Lazily loaded native module
16
+ let _native = null;
17
+ function getNative() {
18
+ if (!_native) {
19
+ _native = loadNativeModule();
20
+ }
21
+ return _native;
22
+ }
23
+ /**
24
+ * RoaringBitmap32 - native drop-in replacement for roaring-wasm.
25
+ *
26
+ * Same API surface:
27
+ * Instance: .size, .isEmpty, .add(u32), .delete(u32), .tryAdd(u32), .has(u32),
28
+ * .toArray(), .serialize('portable'), .deserialize(buf, 'portable'),
29
+ * .getSerializationSizeInBytes('portable'), [Symbol.iterator]
30
+ * Static: RoaringBitmap32.and(a, b), .or(a, b), .orMany(arr)
31
+ * Constructors: new RoaringBitmap32(), new RoaringBitmap32([1,2,3])
32
+ */
33
+ export class RoaringBitmap32 {
34
+ inner;
35
+ constructor(values) {
36
+ const native = getNative();
37
+ if (values) {
38
+ const arr = Array.isArray(values) ? values : Array.from(values);
39
+ this.inner = new native.NativeRoaringBitmap32(arr);
40
+ }
41
+ else {
42
+ this.inner = new native.NativeRoaringBitmap32();
43
+ }
44
+ }
45
+ /** Create from an existing native instance (internal use) */
46
+ static fromNative(inner) {
47
+ const bm = Object.create(RoaringBitmap32.prototype);
48
+ bm.inner = inner;
49
+ return bm;
50
+ }
51
+ // =========================================================================
52
+ // Instance properties
53
+ // =========================================================================
54
+ /** Number of values in the bitmap */
55
+ get size() {
56
+ return this.inner.size;
57
+ }
58
+ /** Whether the bitmap is empty */
59
+ get isEmpty() {
60
+ return this.inner.isEmpty;
61
+ }
62
+ // =========================================================================
63
+ // Instance methods
64
+ // =========================================================================
65
+ /** Add a value to the bitmap */
66
+ add(value) {
67
+ this.inner.add(value);
68
+ }
69
+ /** Remove a value from the bitmap */
70
+ delete(value) {
71
+ this.inner.delete(value);
72
+ }
73
+ /** Add a value, return true if newly added */
74
+ tryAdd(value) {
75
+ return this.inner.tryAdd(value);
76
+ }
77
+ /** Check if the bitmap contains a value */
78
+ has(value) {
79
+ return this.inner.has(value);
80
+ }
81
+ /** Convert to array of u32 values (sorted) */
82
+ toArray() {
83
+ return this.inner.toArray();
84
+ }
85
+ /**
86
+ * Serialize to portable format.
87
+ * The format parameter is accepted for roaring-wasm API compatibility
88
+ * but native always uses portable format (binary-identical).
89
+ */
90
+ serialize(_format) {
91
+ return this.inner.serialize();
92
+ }
93
+ /**
94
+ * Deserialize from portable format buffer (instance method).
95
+ * Replaces the contents of this bitmap with the deserialized data.
96
+ * Matches roaring-wasm instance method API.
97
+ */
98
+ deserialize(buffer, _format) {
99
+ const native = getNative();
100
+ const buf = Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);
101
+ this.inner = native.NativeRoaringBitmap32.deserialize(buf);
102
+ }
103
+ /**
104
+ * Get serialization size in bytes.
105
+ * The format parameter is accepted for roaring-wasm API compatibility.
106
+ */
107
+ getSerializationSizeInBytes(_format) {
108
+ return this.inner.serializationSizeInBytes();
109
+ }
110
+ /** Get minimum value (null if empty — napi maps Rust None → null, not undefined). */
111
+ minimum() {
112
+ return this.inner.minimum();
113
+ }
114
+ /** Get maximum value (null if empty — napi maps Rust None → null, not undefined). */
115
+ maximum() {
116
+ return this.inner.maximum();
117
+ }
118
+ /** Iterator support for for...of loops */
119
+ *[Symbol.iterator]() {
120
+ const arr = this.inner.toArray();
121
+ for (const v of arr) {
122
+ yield v;
123
+ }
124
+ }
125
+ // =========================================================================
126
+ // Static methods (match roaring-wasm static API)
127
+ // =========================================================================
128
+ /** Deserialize from portable format buffer */
129
+ static deserialize(buffer, _format) {
130
+ const native = getNative();
131
+ const buf = Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);
132
+ const inner = native.NativeRoaringBitmap32.deserialize(buf);
133
+ return RoaringBitmap32.fromNative(inner);
134
+ }
135
+ /** Compute intersection (AND) of two bitmaps */
136
+ static and(a, b) {
137
+ const native = getNative();
138
+ const inner = native.NativeRoaringBitmap32.and(a.inner, b.inner);
139
+ return RoaringBitmap32.fromNative(inner);
140
+ }
141
+ /** Compute union (OR) of two bitmaps */
142
+ static or(a, b) {
143
+ const native = getNative();
144
+ const inner = native.NativeRoaringBitmap32.or(a.inner, b.inner);
145
+ return RoaringBitmap32.fromNative(inner);
146
+ }
147
+ /** Compute union (OR) of multiple bitmaps */
148
+ static orMany(bitmaps) {
149
+ if (bitmaps.length === 0) {
150
+ return new RoaringBitmap32();
151
+ }
152
+ if (bitmaps.length === 1) {
153
+ return bitmaps[0];
154
+ }
155
+ const native = getNative();
156
+ const inner = native.NativeRoaringBitmap32.orMany(bitmaps.map(bm => bm.inner));
157
+ return RoaringBitmap32.fromNative(inner);
158
+ }
159
+ /** Compute difference (AND NOT) */
160
+ static andNot(a, b) {
161
+ const native = getNative();
162
+ const inner = native.NativeRoaringBitmap32.andNot(a.inner, b.inner);
163
+ return RoaringBitmap32.fromNative(inner);
164
+ }
165
+ /** Compute symmetric difference (XOR) */
166
+ static xor(a, b) {
167
+ const native = getNative();
168
+ const inner = native.NativeRoaringBitmap32.xor(a.inner, b.inner);
169
+ return RoaringBitmap32.fromNative(inner);
170
+ }
171
+ }
172
+ /**
173
+ * RoaringBitmap32Iterator - for roaring-wasm API compatibility.
174
+ * Uses the native toArray() under the hood.
175
+ */
176
+ export class RoaringBitmap32Iterator {
177
+ values;
178
+ index = 0;
179
+ constructor(bitmap) {
180
+ this.values = bitmap.toArray();
181
+ }
182
+ next() {
183
+ if (this.index < this.values.length) {
184
+ return { value: this.values[this.index++], done: false };
185
+ }
186
+ return { value: undefined, done: true };
187
+ }
188
+ [Symbol.iterator]() {
189
+ return this;
190
+ }
191
+ }
192
+ /**
193
+ * roaringLibraryInitialize - no-op for native (ready at load time).
194
+ * Kept for API compatibility with roaring-wasm.
195
+ */
196
+ export async function roaringLibraryInitialize() {
197
+ // Native module is ready at load time - no WASM compilation needed
198
+ return Promise.resolve();
199
+ }
200
+ /**
201
+ * roaringLibraryIsReady - always true for native.
202
+ * Kept for API compatibility with roaring-wasm.
203
+ */
204
+ export function roaringLibraryIsReady() {
205
+ return true;
206
+ }
207
+ /**
208
+ * Serialization format enum - for API compatibility with roaring-wasm.
209
+ */
210
+ export const SerializationFormat = {
211
+ portable: 'portable',
212
+ croaring: 'croaring',
213
+ };
214
+ /**
215
+ * Deserialization format enum - for API compatibility with roaring-wasm.
216
+ */
217
+ export const DeserializationFormat = {
218
+ portable: 'portable',
219
+ croaring: 'croaring',
220
+ };
221
+ //# sourceMappingURL=NativeRoaringBitmap32.js.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * bun:ffi bindings loader
3
+ *
4
+ * Loads the native module via bun:ffi + dlopen for bun --compile on Linux.
5
+ * The .so file is embedded in the compiled binary via static import.
6
+ *
7
+ * This is the PREFERRED production deployment path:
8
+ * bun build --compile my-app.ts --outfile my-app
9
+ *
10
+ * For development and other platforms, use napi.ts instead.
11
+ */
12
+ import type { NativeBindings } from './types.js';
13
+ /**
14
+ * Load the native module via bun:ffi.
15
+ *
16
+ * Only available on Linux with Bun.
17
+ * Falls back to napi-rs on other platforms or if FFI loading fails.
18
+ */
19
+ export declare function loadViaFFI(): NativeBindings;
20
+ //# sourceMappingURL=ffi.d.ts.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * bun:ffi bindings loader
3
+ *
4
+ * Loads the native module via bun:ffi + dlopen for bun --compile on Linux.
5
+ * The .so file is embedded in the compiled binary via static import.
6
+ *
7
+ * This is the PREFERRED production deployment path:
8
+ * bun build --compile my-app.ts --outfile my-app
9
+ *
10
+ * For development and other platforms, use napi.ts instead.
11
+ */
12
+ /**
13
+ * Load the native module via bun:ffi.
14
+ *
15
+ * Only available on Linux with Bun.
16
+ * Falls back to napi-rs on other platforms or if FFI loading fails.
17
+ */
18
+ export function loadViaFFI() {
19
+ // bun:ffi is only available in Bun
20
+ if (typeof Bun === 'undefined') {
21
+ throw new Error('bun:ffi is only available in Bun runtime');
22
+ }
23
+ if (process.platform !== 'linux') {
24
+ throw new Error('bun:ffi native loading is only supported on Linux');
25
+ }
26
+ // Dynamic import of bun:ffi — this is a Bun built-in
27
+ // The .so file path is resolved at build time for bun --compile
28
+ // For runtime Bun, it falls back to the local build path
29
+ throw new Error('bun:ffi loader not yet implemented. ' +
30
+ 'Requires native build output (libbrainy_native.so). ' +
31
+ 'Use napi-rs loader instead.');
32
+ // Future implementation:
33
+ // import nativeLib from '../../native/target/release/libbrainy_native.so' with { type: 'file' }
34
+ // import { dlopen, FFIType } from 'bun:ffi'
35
+ //
36
+ // const lib = dlopen(nativeLib, {
37
+ // brainy_engine_create: { returns: FFIType.ptr },
38
+ // brainy_engine_load: { args: [...], returns: FFIType.i32 },
39
+ // brainy_engine_embed: { args: [...], returns: FFIType.ptr },
40
+ // brainy_roaring_create: { returns: FFIType.ptr },
41
+ // brainy_roaring_add: { args: [FFIType.ptr, FFIType.u32], returns: FFIType.void },
42
+ // brainy_cosine_distance: { args: [FFIType.ptr, FFIType.ptr, FFIType.u32], returns: FFIType.f64 },
43
+ // // ... etc
44
+ // })
45
+ //
46
+ // return wrapFFIAsNativeBindings(lib)
47
+ }
48
+ //# sourceMappingURL=ffi.js.map
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @module native/idMapperTestSupport
3
+ * @description Test helpers for the #72 Phase C consolidation, where the
4
+ * metadata index's canonical UUID ↔ entity-int allocator became the shared
5
+ * mmap `BinaryIdMapper` (injected via `setIdMapper`) instead of the resident
6
+ * JSON `EntityIdMapperCore` (seeded via the deleted `loadEntityIdMapper`).
7
+ *
8
+ * Tests that drive the raw `NativeMetadataIndex` napi must now inject a real
9
+ * temp-file `BinaryIdMapper` and address entities by REAL UUIDs (the binary
10
+ * mapper is UUID-only — it parses every key into 16 bytes). These helpers
11
+ * provide both, plus a deterministic UUID generator and the UUID→Buffer
12
+ * encoding the mapper's `remove`/lookup surface takes.
13
+ *
14
+ * NOTE: the binary mapper assigns ints sequentially from 0 — there is no
15
+ * "seed the cursor to a high int" hook the way the old JSON envelope had.
16
+ * The u64-VALUE behaviour (ints above `u32::MAX`) is therefore covered at
17
+ * the diskann crate level (`binary_id_mapper` unit tests); these helpers
18
+ * exercise the metadata index's ROUTING through a u32- or u64-mode mapper.
19
+ */
20
+ import type { EntityIdMapperLike } from '../utils/columnStoreTypes.js';
21
+ /**
22
+ * Create a fresh temp-file `BinaryIdMapper` in the requested id space.
23
+ *
24
+ * @param native - The loaded native module (`loadNativeModule()`).
25
+ * @param idSpace - `'u32'` or `'u64'`.
26
+ * @returns The native mapper instance and its temp directory.
27
+ */
28
+ export declare function createTestBinaryMapper(native: any, idSpace: 'u32' | 'u64'): {
29
+ mapper: any;
30
+ dir: string;
31
+ };
32
+ /**
33
+ * Create a temp-file `BinaryIdMapper` and inject it into a raw
34
+ * `NativeMetadataIndex` as its canonical allocator.
35
+ *
36
+ * @returns The mapper (kept so a test can drive it directly, e.g. to
37
+ * tombstone mappings for the unmapped-int-window case) and its temp dir.
38
+ */
39
+ export declare function injectTestMapper(native: any, idx: any, idSpace: 'u32' | 'u64'): {
40
+ mapper: any;
41
+ dir: string;
42
+ };
43
+ /**
44
+ * Deterministic, valid v4-shaped UUID for test entity `n`. The variant /
45
+ * version nibbles are fixed; `n` is encoded into the trailing 12 hex digits,
46
+ * so distinct `n` always yield distinct UUIDs.
47
+ */
48
+ export declare function testUuid(n: number): string;
49
+ /** Encode a canonical UUID string to the 16-byte Buffer the mapper takes. */
50
+ export declare function uuidToBuffer(uuid: string): Buffer;
51
+ /**
52
+ * A pure in-memory {@link EntityIdMapperLike} for unit tests that drive a
53
+ * `NativeDiskAnnWrapper` in isolation (no brainy / no metadata index).
54
+ *
55
+ * #72 Phase A+B made the wrapper resolve `slot ↔ uuid` through the
56
+ * canonical entity-id mapper + the off-heap mmap slotmaps instead of
57
+ * resident JS maps, so a standalone wrapper now needs a mapper injected
58
+ * via its `mapperResolver` option. This stub assigns 0-based sequential
59
+ * ints (matching the production `BinaryIdMapper`'s base offset) to
60
+ * arbitrary string ids, so existing tests can keep using friendly ids
61
+ * like `id-0` without minting real UUIDs. Reuse ONE instance across a
62
+ * cold-restart (w1 → w2) to model the production mapper's mmap durability.
63
+ *
64
+ * @returns A fresh, independent mapper.
65
+ */
66
+ export declare function inMemoryEntityIdMapper(): EntityIdMapperLike;
67
+ //# sourceMappingURL=idMapperTestSupport.d.ts.map
@@ -0,0 +1,112 @@
1
+ /**
2
+ * @module native/idMapperTestSupport
3
+ * @description Test helpers for the #72 Phase C consolidation, where the
4
+ * metadata index's canonical UUID ↔ entity-int allocator became the shared
5
+ * mmap `BinaryIdMapper` (injected via `setIdMapper`) instead of the resident
6
+ * JSON `EntityIdMapperCore` (seeded via the deleted `loadEntityIdMapper`).
7
+ *
8
+ * Tests that drive the raw `NativeMetadataIndex` napi must now inject a real
9
+ * temp-file `BinaryIdMapper` and address entities by REAL UUIDs (the binary
10
+ * mapper is UUID-only — it parses every key into 16 bytes). These helpers
11
+ * provide both, plus a deterministic UUID generator and the UUID→Buffer
12
+ * encoding the mapper's `remove`/lookup surface takes.
13
+ *
14
+ * NOTE: the binary mapper assigns ints sequentially from 0 — there is no
15
+ * "seed the cursor to a high int" hook the way the old JSON envelope had.
16
+ * The u64-VALUE behaviour (ints above `u32::MAX`) is therefore covered at
17
+ * the diskann crate level (`binary_id_mapper` unit tests); these helpers
18
+ * exercise the metadata index's ROUTING through a u32- or u64-mode mapper.
19
+ */
20
+ import { mkdtempSync } from 'node:fs';
21
+ import { tmpdir } from 'node:os';
22
+ import { join } from 'node:path';
23
+ /** 64 MB sparse files — plenty for a unit-test corpus, tiny on disk. */
24
+ const TEST_FILE_SIZE = BigInt(64 * 1024 * 1024);
25
+ /**
26
+ * Create a fresh temp-file `BinaryIdMapper` in the requested id space.
27
+ *
28
+ * @param native - The loaded native module (`loadNativeModule()`).
29
+ * @param idSpace - `'u32'` or `'u64'`.
30
+ * @returns The native mapper instance and its temp directory.
31
+ */
32
+ export function createTestBinaryMapper(native, idSpace) {
33
+ const dir = mkdtempSync(join(tmpdir(), 'cor-idmap-'));
34
+ const mapper = native.NativeBinaryIdMapper.create({
35
+ uuidToIntPath: join(dir, 'uuid_to_int.mkv'),
36
+ intToUuidPath: join(dir, 'int_to_uuid.bin'),
37
+ intToUuidSize: TEST_FILE_SIZE,
38
+ uuidToIntSize: TEST_FILE_SIZE,
39
+ bucketCapacity: 16,
40
+ maxGlobalDepth: 18,
41
+ idSpace,
42
+ });
43
+ return { mapper, dir };
44
+ }
45
+ /**
46
+ * Create a temp-file `BinaryIdMapper` and inject it into a raw
47
+ * `NativeMetadataIndex` as its canonical allocator.
48
+ *
49
+ * @returns The mapper (kept so a test can drive it directly, e.g. to
50
+ * tombstone mappings for the unmapped-int-window case) and its temp dir.
51
+ */
52
+ export function injectTestMapper(native, idx, idSpace) {
53
+ const handle = createTestBinaryMapper(native, idSpace);
54
+ idx.setIdMapper(handle.mapper);
55
+ return handle;
56
+ }
57
+ /**
58
+ * Deterministic, valid v4-shaped UUID for test entity `n`. The variant /
59
+ * version nibbles are fixed; `n` is encoded into the trailing 12 hex digits,
60
+ * so distinct `n` always yield distinct UUIDs.
61
+ */
62
+ export function testUuid(n) {
63
+ const tail = n.toString(16).padStart(12, '0');
64
+ return `00000000-0000-4000-8000-${tail}`;
65
+ }
66
+ /** Encode a canonical UUID string to the 16-byte Buffer the mapper takes. */
67
+ export function uuidToBuffer(uuid) {
68
+ return Buffer.from(uuid.replace(/-/g, ''), 'hex');
69
+ }
70
+ /**
71
+ * A pure in-memory {@link EntityIdMapperLike} for unit tests that drive a
72
+ * `NativeDiskAnnWrapper` in isolation (no brainy / no metadata index).
73
+ *
74
+ * #72 Phase A+B made the wrapper resolve `slot ↔ uuid` through the
75
+ * canonical entity-id mapper + the off-heap mmap slotmaps instead of
76
+ * resident JS maps, so a standalone wrapper now needs a mapper injected
77
+ * via its `mapperResolver` option. This stub assigns 0-based sequential
78
+ * ints (matching the production `BinaryIdMapper`'s base offset) to
79
+ * arbitrary string ids, so existing tests can keep using friendly ids
80
+ * like `id-0` without minting real UUIDs. Reuse ONE instance across a
81
+ * cold-restart (w1 → w2) to model the production mapper's mmap durability.
82
+ *
83
+ * @returns A fresh, independent mapper.
84
+ */
85
+ export function inMemoryEntityIdMapper() {
86
+ const intByUuid = new Map();
87
+ const uuidByInt = new Map();
88
+ let next = 0;
89
+ return {
90
+ getUuid: (intId) => uuidByInt.get(intId),
91
+ getInt: (uuid) => intByUuid.get(uuid),
92
+ getOrAssign: (uuid) => {
93
+ let i = intByUuid.get(uuid);
94
+ if (i === undefined) {
95
+ i = next++;
96
+ intByUuid.set(uuid, i);
97
+ uuidByInt.set(i, uuid);
98
+ }
99
+ return i;
100
+ },
101
+ intsIterableToUuids: (ints) => {
102
+ const out = [];
103
+ for (const i of ints) {
104
+ const u = uuidByInt.get(i);
105
+ if (u !== undefined)
106
+ out.push(u);
107
+ }
108
+ return out;
109
+ },
110
+ };
111
+ }
112
+ //# sourceMappingURL=idMapperTestSupport.js.map
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Native Module - Public API
3
+ *
4
+ * Auto-detects the best loading strategy:
5
+ * 1. Bun --compile on Linux: bun:ffi with embedded .so (fastest)
6
+ * 2. All platforms: napi-rs .node file (universal)
7
+ *
8
+ * Exports the unified NativeBindings interface that all consumers use.
9
+ */
10
+ import type { NativeBindings } from './types.js';
11
+ /**
12
+ * Open-file-limit raise result, captured once when the native module
13
+ * first loads. `null` until then (or if the platform/loader doesn't
14
+ * expose the call).
15
+ */
16
+ export interface OpenFileLimitInfo {
17
+ softBefore: number;
18
+ softAfter: number;
19
+ hard: number;
20
+ raised: boolean;
21
+ /** Linux `vm.max_map_count` (0 if unavailable). A process can't raise
22
+ * this — the deployment must (docker `--sysctl` / host sysctl). */
23
+ vmMaxMapCount: number;
24
+ }
25
+ /**
26
+ * Diagnostic accessor for the startup open-file-limit raise. Returns
27
+ * `null` until the native module has loaded.
28
+ */
29
+ export declare function getOpenFileLimitInfo(): OpenFileLimitInfo | null;
30
+ /**
31
+ * Load the native module using the best available strategy.
32
+ *
33
+ * Returns a cached reference on subsequent calls.
34
+ *
35
+ * Loading priority:
36
+ * 1. Bun --compile on Linux → bun:ffi + embedded .so
37
+ * 2. All platforms → napi-rs .node file
38
+ */
39
+ export declare function loadNativeModule(): NativeBindings;
40
+ /**
41
+ * Check if the native module is available.
42
+ * Does not throw - returns false if loading fails.
43
+ */
44
+ export declare function isNativeAvailable(): boolean;
45
+ export type { NativeBindings, NativeEmbeddingEngineInstance, NativeRoaringBitmap32Instance, EmbeddingResult, EngineStats, DeviceInfo, } from './types.js';
46
+ export { MODEL_CONSTANTS } from './types.js';
47
+ export { NativeEmbeddingEngine, nativeEmbeddingEngine, cosineSimilarity, } from './NativeEmbeddingEngine.js';
48
+ export { RoaringBitmap32, RoaringBitmap32Iterator, roaringLibraryInitialize, roaringLibraryIsReady, SerializationFormat, DeserializationFormat, } from './NativeRoaringBitmap32.js';
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Native Module - Public API
3
+ *
4
+ * Auto-detects the best loading strategy:
5
+ * 1. Bun --compile on Linux: bun:ffi with embedded .so (fastest)
6
+ * 2. All platforms: napi-rs .node file (universal)
7
+ *
8
+ * Exports the unified NativeBindings interface that all consumers use.
9
+ */
10
+ import { loadViaNapi } from './napi.js';
11
+ import { loadViaFFI } from './ffi.js';
12
+ // Cached module reference
13
+ let cachedModule = null;
14
+ let fileLimitInfo = null;
15
+ /**
16
+ * Raise the process's soft open-file limit toward its hard cap, once.
17
+ * A per-tenant brain pool runs many brains in one process; the default
18
+ * Linux soft `RLIMIT_NOFILE` (often 1024) caps tenants long before RAM.
19
+ * Raising soft→hard needs no privilege and is safe. Best-effort — never
20
+ * blocks module load; the hard cap + `vm.max_map_count` still need the
21
+ * deployment to set them (see ADR-004).
22
+ */
23
+ function raiseFileLimitOnce(mod) {
24
+ if (fileLimitInfo !== null)
25
+ return;
26
+ try {
27
+ const fn = mod.raiseOpenFileLimit;
28
+ fileLimitInfo = typeof fn === 'function' ? fn() : null;
29
+ }
30
+ catch {
31
+ fileLimitInfo = null;
32
+ }
33
+ }
34
+ /**
35
+ * Diagnostic accessor for the startup open-file-limit raise. Returns
36
+ * `null` until the native module has loaded.
37
+ */
38
+ export function getOpenFileLimitInfo() {
39
+ return fileLimitInfo;
40
+ }
41
+ /**
42
+ * Load the native module using the best available strategy.
43
+ *
44
+ * Returns a cached reference on subsequent calls.
45
+ *
46
+ * Loading priority:
47
+ * 1. Bun --compile on Linux → bun:ffi + embedded .so
48
+ * 2. All platforms → napi-rs .node file
49
+ */
50
+ export function loadNativeModule() {
51
+ if (cachedModule) {
52
+ return cachedModule;
53
+ }
54
+ // Strategy 1: Bun --compile on Linux (bun:ffi)
55
+ if (process.platform === 'linux' && typeof Bun !== 'undefined') {
56
+ try {
57
+ cachedModule = loadViaFFI();
58
+ raiseFileLimitOnce(cachedModule);
59
+ return cachedModule;
60
+ }
61
+ catch {
62
+ // Fall through to napi-rs (Bun runtime, not compiled binary)
63
+ }
64
+ }
65
+ // Strategy 2: All platforms (napi-rs)
66
+ cachedModule = loadViaNapi();
67
+ raiseFileLimitOnce(cachedModule);
68
+ return cachedModule;
69
+ }
70
+ /**
71
+ * Check if the native module is available.
72
+ * Does not throw - returns false if loading fails.
73
+ */
74
+ export function isNativeAvailable() {
75
+ try {
76
+ loadNativeModule();
77
+ return true;
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ }
83
+ export { MODEL_CONSTANTS } from './types.js';
84
+ // Re-export engine and roaring wrappers
85
+ export { NativeEmbeddingEngine, nativeEmbeddingEngine, cosineSimilarity, } from './NativeEmbeddingEngine.js';
86
+ export { RoaringBitmap32, RoaringBitmap32Iterator, roaringLibraryInitialize, roaringLibraryIsReady, SerializationFormat, DeserializationFormat, } from './NativeRoaringBitmap32.js';
87
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * napi-rs bindings loader
3
+ *
4
+ * Loads the native module via napi-rs .node files.
5
+ * Works with: Node.js, Bun runtime, Bun --compile (all platforms).
6
+ *
7
+ * Resolution order:
8
+ * 1. Bundled platform binary: native/brainy-native.{platform-key}.node (shipped in npm package)
9
+ * 2. Local dev build: native/brainy-native.node (for development, no platform suffix)
10
+ * 3. Clear error with supported platforms list
11
+ */
12
+ import type { NativeBindings } from './types.js';
13
+ /**
14
+ * Load the native module via napi-rs.
15
+ *
16
+ * Tries multiple resolution strategies:
17
+ * 1. Bundled platform binary (native/brainy-native.{platform-key}.node)
18
+ * 2. Local dev build (native/brainy-native.node)
19
+ */
20
+ export declare function loadViaNapi(): NativeBindings;
21
+ //# sourceMappingURL=napi.d.ts.map