@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.
- package/LICENSE +16 -0
- package/README.md +328 -0
- package/dist/aggregation/NativeAggregationEngine.d.ts +118 -0
- package/dist/aggregation/NativeAggregationEngine.js +186 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.js +236 -0
- package/dist/graph/GraphAccelerationAdapter.d.ts +153 -0
- package/dist/graph/GraphAccelerationAdapter.js +326 -0
- package/dist/graph/NativeGraphAdjacencyIndex.d.ts +286 -0
- package/dist/graph/NativeGraphAdjacencyIndex.js +944 -0
- package/dist/hnsw/AdaptiveDiskAnnModeSelector.d.ts +187 -0
- package/dist/hnsw/AdaptiveDiskAnnModeSelector.js +313 -0
- package/dist/hnsw/NativeDiskAnnWrapper.d.ts +489 -0
- package/dist/hnsw/NativeDiskAnnWrapper.js +1456 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +29 -0
- package/dist/legacyLayoutGuard.d.ts +93 -0
- package/dist/legacyLayoutGuard.js +237 -0
- package/dist/license/constants.d.ts +30 -0
- package/dist/license/constants.js +30 -0
- package/dist/license/onlineValidator.d.ts +43 -0
- package/dist/license/onlineValidator.js +225 -0
- package/dist/license/types.d.ts +39 -0
- package/dist/license/types.js +5 -0
- package/dist/license.d.ts +64 -0
- package/dist/license.js +165 -0
- package/dist/migration/MigrationCoordinator.d.ts +171 -0
- package/dist/migration/MigrationCoordinator.js +249 -0
- package/dist/migration/indexEpochGuard.d.ts +163 -0
- package/dist/migration/indexEpochGuard.js +202 -0
- package/dist/native/NativeEmbeddingEngine.d.ts +79 -0
- package/dist/native/NativeEmbeddingEngine.js +318 -0
- package/dist/native/NativeRoaringBitmap32.d.ts +114 -0
- package/dist/native/NativeRoaringBitmap32.js +221 -0
- package/dist/native/ffi.d.ts +20 -0
- package/dist/native/ffi.js +48 -0
- package/dist/native/idMapperTestSupport.d.ts +67 -0
- package/dist/native/idMapperTestSupport.js +112 -0
- package/dist/native/index.d.ts +49 -0
- package/dist/native/index.js +87 -0
- package/dist/native/napi.d.ts +21 -0
- package/dist/native/napi.js +88 -0
- package/dist/native/types.d.ts +1298 -0
- package/dist/native/types.js +16 -0
- package/dist/plugin.d.ts +50 -0
- package/dist/plugin.js +388 -0
- package/dist/providerContracts.d.ts +277 -0
- package/dist/providerContracts.js +38 -0
- package/dist/resource/OsMemoryProbe.d.ts +175 -0
- package/dist/resource/OsMemoryProbe.js +206 -0
- package/dist/resource/ResourceManager.d.ts +491 -0
- package/dist/resource/ResourceManager.js +960 -0
- package/dist/utils/ColumnManifest.d.ts +97 -0
- package/dist/utils/ColumnManifest.js +129 -0
- package/dist/utils/NativeColumnStore.d.ts +284 -0
- package/dist/utils/NativeColumnStore.js +685 -0
- package/dist/utils/NativeMetadataIndex.d.ts +882 -0
- package/dist/utils/NativeMetadataIndex.js +2631 -0
- package/dist/utils/NativeUnifiedCache.d.ts +87 -0
- package/dist/utils/NativeUnifiedCache.js +273 -0
- package/dist/utils/binaryIdMapperFactory.d.ts +59 -0
- package/dist/utils/binaryIdMapperFactory.js +94 -0
- package/dist/utils/collation.d.ts +30 -0
- package/dist/utils/collation.js +40 -0
- package/dist/utils/columnStoreTypes.d.ts +161 -0
- package/dist/utils/columnStoreTypes.js +29 -0
- package/dist/utils/nativeBinaryEntityIdMapper.d.ts +211 -0
- package/dist/utils/nativeBinaryEntityIdMapper.js +381 -0
- package/dist/utils/nativeEntityIdMapper.d.ts +111 -0
- package/dist/utils/nativeEntityIdMapper.js +170 -0
- package/docs/ADR-002-diskann-100-percent-rust.md +294 -0
- package/docs/ADR-003-semantic-time-travel.md +100 -0
- package/docs/aggregation.md +251 -0
- package/docs/comparison.md +162 -0
- package/docs/deployment-limits.md +87 -0
- package/docs/diskann.md +184 -0
- package/docs/migration-3.0.md +396 -0
- package/docs/performance-budget.md +274 -0
- package/docs/performance.md +117 -0
- package/docs/scaling.md +439 -0
- package/docs/snapshot-safety.md +246 -0
- package/docs/u64-id-space.md +214 -0
- package/docs/verification-report.md +670 -0
- package/native/brainy-native.node +0 -0
- package/native/index.d.ts +3916 -0
- package/package.json +92 -0
- package/scripts/migrate-cortex-2x-to-3x.mjs +970 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Embedding Engine
|
|
3
|
+
*
|
|
4
|
+
* TypeScript wrapper matching the CandleEmbeddingEngine / WASMEmbeddingEngine API.
|
|
5
|
+
* Uses the native Rust module (napi-rs or bun:ffi) instead of WASM.
|
|
6
|
+
*
|
|
7
|
+
* Drop-in replacement: same singleton pattern, same method signatures,
|
|
8
|
+
* same model loading flow. Consumers don't need to change.
|
|
9
|
+
*/
|
|
10
|
+
import type { EmbeddingResult, EngineStats } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Native embedding engine using Rust (Candle) via napi-rs.
|
|
13
|
+
*
|
|
14
|
+
* Replaces WASMEmbeddingEngine and CandleEmbeddingEngine.
|
|
15
|
+
* Same API surface for backward compatibility.
|
|
16
|
+
*/
|
|
17
|
+
export declare class NativeEmbeddingEngine {
|
|
18
|
+
private engine;
|
|
19
|
+
private initialized;
|
|
20
|
+
private embedCount;
|
|
21
|
+
private totalProcessingTimeMs;
|
|
22
|
+
private constructor();
|
|
23
|
+
/**
|
|
24
|
+
* Get the singleton instance
|
|
25
|
+
*/
|
|
26
|
+
static getInstance(): NativeEmbeddingEngine;
|
|
27
|
+
/**
|
|
28
|
+
* Initialize the embedding engine
|
|
29
|
+
*/
|
|
30
|
+
initialize(): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Perform actual initialization.
|
|
33
|
+
*
|
|
34
|
+
* Loads the native module and model assets.
|
|
35
|
+
* Native module loads in <100ms (vs 3-5s for WASM compilation).
|
|
36
|
+
*/
|
|
37
|
+
private performInit;
|
|
38
|
+
/**
|
|
39
|
+
* Load model assets from filesystem.
|
|
40
|
+
* Same resolution logic as the WASM modelLoader.ts.
|
|
41
|
+
*/
|
|
42
|
+
private loadModelAssets;
|
|
43
|
+
private loadBunAssets;
|
|
44
|
+
private loadNodeAssets;
|
|
45
|
+
/**
|
|
46
|
+
* Generate embedding for text
|
|
47
|
+
*/
|
|
48
|
+
embed(text: string): Promise<number[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Generate embedding with metadata
|
|
51
|
+
*/
|
|
52
|
+
embedWithMetadata(text: string): Promise<EmbeddingResult>;
|
|
53
|
+
/**
|
|
54
|
+
* Batch embed multiple texts
|
|
55
|
+
*/
|
|
56
|
+
embedBatch(texts: string[]): Promise<number[][]>;
|
|
57
|
+
/**
|
|
58
|
+
* Check if initialized
|
|
59
|
+
*/
|
|
60
|
+
isInitialized(): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Get engine statistics
|
|
63
|
+
*/
|
|
64
|
+
getStats(): EngineStats;
|
|
65
|
+
/**
|
|
66
|
+
* Dispose and free resources
|
|
67
|
+
*/
|
|
68
|
+
dispose(): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Reset singleton (for testing)
|
|
71
|
+
*/
|
|
72
|
+
static resetInstance(): void;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Calculate cosine similarity between two embeddings (native)
|
|
76
|
+
*/
|
|
77
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
78
|
+
export declare const nativeEmbeddingEngine: NativeEmbeddingEngine;
|
|
79
|
+
//# sourceMappingURL=NativeEmbeddingEngine.d.ts.map
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Embedding Engine
|
|
3
|
+
*
|
|
4
|
+
* TypeScript wrapper matching the CandleEmbeddingEngine / WASMEmbeddingEngine API.
|
|
5
|
+
* Uses the native Rust module (napi-rs or bun:ffi) instead of WASM.
|
|
6
|
+
*
|
|
7
|
+
* Drop-in replacement: same singleton pattern, same method signatures,
|
|
8
|
+
* same model loading flow. Consumers don't need to change.
|
|
9
|
+
*/
|
|
10
|
+
import { MODEL_CONSTANTS } from './types.js';
|
|
11
|
+
import { loadNativeModule } from './index.js';
|
|
12
|
+
// Global singleton
|
|
13
|
+
let globalInstance = null;
|
|
14
|
+
let globalInitPromise = null;
|
|
15
|
+
/**
|
|
16
|
+
* Native embedding engine using Rust (Candle) via napi-rs.
|
|
17
|
+
*
|
|
18
|
+
* Replaces WASMEmbeddingEngine and CandleEmbeddingEngine.
|
|
19
|
+
* Same API surface for backward compatibility.
|
|
20
|
+
*/
|
|
21
|
+
export class NativeEmbeddingEngine {
|
|
22
|
+
engine = null;
|
|
23
|
+
initialized = false;
|
|
24
|
+
embedCount = 0;
|
|
25
|
+
totalProcessingTimeMs = 0;
|
|
26
|
+
constructor() {
|
|
27
|
+
// Private constructor for singleton
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get the singleton instance
|
|
31
|
+
*/
|
|
32
|
+
static getInstance() {
|
|
33
|
+
if (!globalInstance) {
|
|
34
|
+
globalInstance = new NativeEmbeddingEngine();
|
|
35
|
+
}
|
|
36
|
+
return globalInstance;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Initialize the embedding engine
|
|
40
|
+
*/
|
|
41
|
+
async initialize() {
|
|
42
|
+
if (this.initialized) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (globalInitPromise) {
|
|
46
|
+
await globalInitPromise;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
globalInitPromise = this.performInit();
|
|
50
|
+
try {
|
|
51
|
+
await globalInitPromise;
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
globalInitPromise = null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Perform actual initialization.
|
|
59
|
+
*
|
|
60
|
+
* Loads the native module and model assets.
|
|
61
|
+
* Native module loads in <100ms (vs 3-5s for WASM compilation).
|
|
62
|
+
*/
|
|
63
|
+
async performInit() {
|
|
64
|
+
const startTime = Date.now();
|
|
65
|
+
console.log('Initializing Native Embedding Engine...');
|
|
66
|
+
try {
|
|
67
|
+
// 1. Load native module
|
|
68
|
+
console.log('Loading native module...');
|
|
69
|
+
const native = loadNativeModule();
|
|
70
|
+
this.engine = new native.NativeEmbeddingEngine();
|
|
71
|
+
const nativeTime = Date.now() - startTime;
|
|
72
|
+
console.log(` Native module loaded in ${nativeTime}ms`);
|
|
73
|
+
// 2. Load model assets (same flow as WASM version)
|
|
74
|
+
console.log('Loading model assets (~88MB)...');
|
|
75
|
+
const modelStartTime = Date.now();
|
|
76
|
+
const assets = await this.loadModelAssets();
|
|
77
|
+
const modelTime = Date.now() - modelStartTime;
|
|
78
|
+
console.log(` Model loaded in ${modelTime}ms`);
|
|
79
|
+
// 3. Initialize engine with model
|
|
80
|
+
console.log('Initializing embedding engine...');
|
|
81
|
+
this.engine.load(assets.model, assets.tokenizer, assets.config);
|
|
82
|
+
if (!this.engine.isReady()) {
|
|
83
|
+
throw new Error('Engine failed to initialize');
|
|
84
|
+
}
|
|
85
|
+
this.initialized = true;
|
|
86
|
+
const initTime = Date.now() - startTime;
|
|
87
|
+
console.log(`Native Embedding Engine ready in ${initTime}ms`);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
this.initialized = false;
|
|
91
|
+
this.engine = null;
|
|
92
|
+
throw new Error(`Failed to initialize Native Embedding Engine: ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Load model assets from filesystem.
|
|
97
|
+
* Same resolution logic as the WASM modelLoader.ts.
|
|
98
|
+
*/
|
|
99
|
+
async loadModelAssets() {
|
|
100
|
+
const isBun = typeof Bun !== 'undefined';
|
|
101
|
+
if (isBun) {
|
|
102
|
+
return this.loadBunAssets();
|
|
103
|
+
}
|
|
104
|
+
return this.loadNodeAssets();
|
|
105
|
+
}
|
|
106
|
+
async loadBunAssets() {
|
|
107
|
+
const pathsToTry = [];
|
|
108
|
+
// Strategy 1: URL-resolved paths (works in Bun runtime)
|
|
109
|
+
try {
|
|
110
|
+
const modelPath = new URL('../../assets/models/all-MiniLM-L6-v2/model.safetensors', import.meta.url).pathname;
|
|
111
|
+
const tokenizerPath = new URL('../../assets/models/all-MiniLM-L6-v2/tokenizer.json', import.meta.url).pathname;
|
|
112
|
+
const configPath = new URL('../../assets/models/all-MiniLM-L6-v2/config.json', import.meta.url).pathname;
|
|
113
|
+
pathsToTry.push([modelPath, tokenizerPath, configPath]);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// skip
|
|
117
|
+
}
|
|
118
|
+
// Strategy 2: node_modules path (installed packages)
|
|
119
|
+
const nmPath = './node_modules/@soulcraft/brainy/assets/models/all-MiniLM-L6-v2';
|
|
120
|
+
pathsToTry.push([
|
|
121
|
+
`${nmPath}/model.safetensors`,
|
|
122
|
+
`${nmPath}/tokenizer.json`,
|
|
123
|
+
`${nmPath}/config.json`,
|
|
124
|
+
]);
|
|
125
|
+
// Strategy 3: assets folder relative to CWD (local development)
|
|
126
|
+
pathsToTry.push([
|
|
127
|
+
'./assets/models/all-MiniLM-L6-v2/model.safetensors',
|
|
128
|
+
'./assets/models/all-MiniLM-L6-v2/tokenizer.json',
|
|
129
|
+
'./assets/models/all-MiniLM-L6-v2/config.json',
|
|
130
|
+
]);
|
|
131
|
+
for (const [modelPath, tokenizerPath, configPath] of pathsToTry) {
|
|
132
|
+
try {
|
|
133
|
+
const [model, tokenizer, config] = await Promise.all([
|
|
134
|
+
Bun.file(modelPath).arrayBuffer(),
|
|
135
|
+
Bun.file(tokenizerPath).arrayBuffer(),
|
|
136
|
+
Bun.file(configPath).arrayBuffer(),
|
|
137
|
+
]);
|
|
138
|
+
if (model.byteLength > 0 && tokenizer.byteLength > 0 && config.byteLength > 0) {
|
|
139
|
+
return {
|
|
140
|
+
model: Buffer.from(model),
|
|
141
|
+
tokenizer: Buffer.from(tokenizer),
|
|
142
|
+
config: Buffer.from(config),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
throw new Error('Could not load model assets. Ensure model files are accessible:\n' +
|
|
151
|
+
' Option 1: npm install @soulcraft/brainy (includes assets)\n' +
|
|
152
|
+
' Option 2: Copy assets/ folder to your working directory\n' +
|
|
153
|
+
' Option 3: For bun --compile, use --asset flag');
|
|
154
|
+
}
|
|
155
|
+
async loadNodeAssets() {
|
|
156
|
+
const fs = await import('node:fs');
|
|
157
|
+
const nodePath = await import('node:path');
|
|
158
|
+
const { fileURLToPath } = await import('node:url');
|
|
159
|
+
const thisDir = nodePath.dirname(fileURLToPath(import.meta.url));
|
|
160
|
+
// Try multiple paths (same strategy order as Bun):
|
|
161
|
+
// 1. Relative to source file (works when running from brainy's own repo)
|
|
162
|
+
// 2. node_modules/@soulcraft/brainy (works when cor is installed as dependency)
|
|
163
|
+
// 3. CWD-relative assets/ (local development / symlinked)
|
|
164
|
+
const pathsToTry = [
|
|
165
|
+
nodePath.resolve(thisDir, '../../assets/models/all-MiniLM-L6-v2'),
|
|
166
|
+
nodePath.resolve(process.cwd(), 'node_modules/@soulcraft/brainy/assets/models/all-MiniLM-L6-v2'),
|
|
167
|
+
nodePath.resolve(process.cwd(), 'assets/models/all-MiniLM-L6-v2'),
|
|
168
|
+
];
|
|
169
|
+
for (const assetsDir of pathsToTry) {
|
|
170
|
+
if (!fs.existsSync(assetsDir))
|
|
171
|
+
continue;
|
|
172
|
+
try {
|
|
173
|
+
const [model, tokenizer, config] = await Promise.all([
|
|
174
|
+
fs.promises.readFile(nodePath.join(assetsDir, 'model.safetensors')),
|
|
175
|
+
fs.promises.readFile(nodePath.join(assetsDir, 'tokenizer.json')),
|
|
176
|
+
fs.promises.readFile(nodePath.join(assetsDir, 'config.json')),
|
|
177
|
+
]);
|
|
178
|
+
return {
|
|
179
|
+
model: Buffer.from(model),
|
|
180
|
+
tokenizer: Buffer.from(tokenizer),
|
|
181
|
+
config: Buffer.from(config),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
throw new Error(`Model assets not found. Tried:\n` +
|
|
189
|
+
pathsToTry.map(p => ` - ${p}`).join('\n') + '\n' +
|
|
190
|
+
`Ensure @soulcraft/brainy is installed correctly.`);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Generate embedding for text
|
|
194
|
+
*/
|
|
195
|
+
async embed(text) {
|
|
196
|
+
const result = await this.embedWithMetadata(text);
|
|
197
|
+
return result.embedding;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Generate embedding with metadata
|
|
201
|
+
*/
|
|
202
|
+
async embedWithMetadata(text) {
|
|
203
|
+
if (!this.initialized) {
|
|
204
|
+
await this.initialize();
|
|
205
|
+
}
|
|
206
|
+
if (!this.engine) {
|
|
207
|
+
throw new Error('Engine not properly initialized');
|
|
208
|
+
}
|
|
209
|
+
try {
|
|
210
|
+
const startTime = Date.now();
|
|
211
|
+
const embedding = this.engine.embed(text);
|
|
212
|
+
const processingTimeMs = Date.now() - startTime;
|
|
213
|
+
this.embedCount++;
|
|
214
|
+
this.totalProcessingTimeMs += processingTimeMs;
|
|
215
|
+
return {
|
|
216
|
+
embedding,
|
|
217
|
+
tokenCount: 0, // Candle handles tokenization internally
|
|
218
|
+
processingTimeMs,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
console.error('Native embed failed, marking engine for re-initialization:', error);
|
|
223
|
+
this.initialized = false;
|
|
224
|
+
this.engine = null;
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Batch embed multiple texts
|
|
230
|
+
*/
|
|
231
|
+
async embedBatch(texts) {
|
|
232
|
+
if (!this.initialized) {
|
|
233
|
+
await this.initialize();
|
|
234
|
+
}
|
|
235
|
+
if (!this.engine) {
|
|
236
|
+
throw new Error('Engine not properly initialized');
|
|
237
|
+
}
|
|
238
|
+
if (texts.length === 0) {
|
|
239
|
+
return [];
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
const embeddings = this.engine.embedBatch(texts);
|
|
243
|
+
this.embedCount += texts.length;
|
|
244
|
+
return embeddings;
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
console.error('Native embedBatch failed, marking engine for re-initialization:', error);
|
|
248
|
+
this.initialized = false;
|
|
249
|
+
this.engine = null;
|
|
250
|
+
throw error;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Check if initialized
|
|
255
|
+
*/
|
|
256
|
+
isInitialized() {
|
|
257
|
+
return this.initialized;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Get engine statistics
|
|
261
|
+
*/
|
|
262
|
+
getStats() {
|
|
263
|
+
if (this.engine) {
|
|
264
|
+
return this.engine.getStats();
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
initialized: this.initialized,
|
|
268
|
+
embedCount: this.embedCount,
|
|
269
|
+
totalProcessingTimeMs: this.totalProcessingTimeMs,
|
|
270
|
+
avgProcessingTimeMs: this.embedCount > 0 ? this.totalProcessingTimeMs / this.embedCount : 0,
|
|
271
|
+
modelName: MODEL_CONSTANTS.MODEL_NAME,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Dispose and free resources
|
|
276
|
+
*/
|
|
277
|
+
async dispose() {
|
|
278
|
+
// napi-rs handles cleanup via GC; just clear references
|
|
279
|
+
this.engine = null;
|
|
280
|
+
this.initialized = false;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Reset singleton (for testing)
|
|
284
|
+
*/
|
|
285
|
+
static resetInstance() {
|
|
286
|
+
if (globalInstance) {
|
|
287
|
+
globalInstance.dispose();
|
|
288
|
+
}
|
|
289
|
+
globalInstance = null;
|
|
290
|
+
globalInitPromise = null;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Calculate cosine similarity between two embeddings (native)
|
|
295
|
+
*/
|
|
296
|
+
export function cosineSimilarity(a, b) {
|
|
297
|
+
try {
|
|
298
|
+
const native = loadNativeModule();
|
|
299
|
+
return native.cosineSimilarity(a, b);
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
// Fallback to JS implementation
|
|
303
|
+
if (a.length !== b.length || a.length === 0)
|
|
304
|
+
return 0;
|
|
305
|
+
let dot = 0, normA = 0, normB = 0;
|
|
306
|
+
for (let i = 0; i < a.length; i++) {
|
|
307
|
+
dot += a[i] * b[i];
|
|
308
|
+
normA += a[i] * a[i];
|
|
309
|
+
normB += b[i] * b[i];
|
|
310
|
+
}
|
|
311
|
+
if (normA === 0 || normB === 0)
|
|
312
|
+
return 0;
|
|
313
|
+
return dot / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// Export singleton access
|
|
317
|
+
export const nativeEmbeddingEngine = NativeEmbeddingEngine.getInstance();
|
|
318
|
+
//# sourceMappingURL=NativeEmbeddingEngine.js.map
|
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
/**
|
|
15
|
+
* RoaringBitmap32 - native drop-in replacement for roaring-wasm.
|
|
16
|
+
*
|
|
17
|
+
* Same API surface:
|
|
18
|
+
* Instance: .size, .isEmpty, .add(u32), .delete(u32), .tryAdd(u32), .has(u32),
|
|
19
|
+
* .toArray(), .serialize('portable'), .deserialize(buf, 'portable'),
|
|
20
|
+
* .getSerializationSizeInBytes('portable'), [Symbol.iterator]
|
|
21
|
+
* Static: RoaringBitmap32.and(a, b), .or(a, b), .orMany(arr)
|
|
22
|
+
* Constructors: new RoaringBitmap32(), new RoaringBitmap32([1,2,3])
|
|
23
|
+
*/
|
|
24
|
+
export declare class RoaringBitmap32 {
|
|
25
|
+
private inner;
|
|
26
|
+
constructor(values?: Iterable<number>);
|
|
27
|
+
/** Create from an existing native instance (internal use) */
|
|
28
|
+
private static fromNative;
|
|
29
|
+
/** Number of values in the bitmap */
|
|
30
|
+
get size(): number;
|
|
31
|
+
/** Whether the bitmap is empty */
|
|
32
|
+
get isEmpty(): boolean;
|
|
33
|
+
/** Add a value to the bitmap */
|
|
34
|
+
add(value: number): void;
|
|
35
|
+
/** Remove a value from the bitmap */
|
|
36
|
+
delete(value: number): void;
|
|
37
|
+
/** Add a value, return true if newly added */
|
|
38
|
+
tryAdd(value: number): boolean;
|
|
39
|
+
/** Check if the bitmap contains a value */
|
|
40
|
+
has(value: number): boolean;
|
|
41
|
+
/** Convert to array of u32 values (sorted) */
|
|
42
|
+
toArray(): number[];
|
|
43
|
+
/**
|
|
44
|
+
* Serialize to portable format.
|
|
45
|
+
* The format parameter is accepted for roaring-wasm API compatibility
|
|
46
|
+
* but native always uses portable format (binary-identical).
|
|
47
|
+
*/
|
|
48
|
+
serialize(_format?: 'portable' | boolean): Buffer;
|
|
49
|
+
/**
|
|
50
|
+
* Deserialize from portable format buffer (instance method).
|
|
51
|
+
* Replaces the contents of this bitmap with the deserialized data.
|
|
52
|
+
* Matches roaring-wasm instance method API.
|
|
53
|
+
*/
|
|
54
|
+
deserialize(buffer: Buffer | Uint8Array, _format?: 'portable' | boolean): void;
|
|
55
|
+
/**
|
|
56
|
+
* Get serialization size in bytes.
|
|
57
|
+
* The format parameter is accepted for roaring-wasm API compatibility.
|
|
58
|
+
*/
|
|
59
|
+
getSerializationSizeInBytes(_format?: 'portable' | boolean): number;
|
|
60
|
+
/** Get minimum value (null if empty — napi maps Rust None → null, not undefined). */
|
|
61
|
+
minimum(): number | null;
|
|
62
|
+
/** Get maximum value (null if empty — napi maps Rust None → null, not undefined). */
|
|
63
|
+
maximum(): number | null;
|
|
64
|
+
/** Iterator support for for...of loops */
|
|
65
|
+
[Symbol.iterator](): IterableIterator<number>;
|
|
66
|
+
/** Deserialize from portable format buffer */
|
|
67
|
+
static deserialize(buffer: Buffer | Uint8Array, _format?: 'portable' | boolean): RoaringBitmap32;
|
|
68
|
+
/** Compute intersection (AND) of two bitmaps */
|
|
69
|
+
static and(a: RoaringBitmap32, b: RoaringBitmap32): RoaringBitmap32;
|
|
70
|
+
/** Compute union (OR) of two bitmaps */
|
|
71
|
+
static or(a: RoaringBitmap32, b: RoaringBitmap32): RoaringBitmap32;
|
|
72
|
+
/** Compute union (OR) of multiple bitmaps */
|
|
73
|
+
static orMany(bitmaps: RoaringBitmap32[]): RoaringBitmap32;
|
|
74
|
+
/** Compute difference (AND NOT) */
|
|
75
|
+
static andNot(a: RoaringBitmap32, b: RoaringBitmap32): RoaringBitmap32;
|
|
76
|
+
/** Compute symmetric difference (XOR) */
|
|
77
|
+
static xor(a: RoaringBitmap32, b: RoaringBitmap32): RoaringBitmap32;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* RoaringBitmap32Iterator - for roaring-wasm API compatibility.
|
|
81
|
+
* Uses the native toArray() under the hood.
|
|
82
|
+
*/
|
|
83
|
+
export declare class RoaringBitmap32Iterator implements IterableIterator<number> {
|
|
84
|
+
private values;
|
|
85
|
+
private index;
|
|
86
|
+
constructor(bitmap: RoaringBitmap32);
|
|
87
|
+
next(): IteratorResult<number>;
|
|
88
|
+
[Symbol.iterator](): IterableIterator<number>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* roaringLibraryInitialize - no-op for native (ready at load time).
|
|
92
|
+
* Kept for API compatibility with roaring-wasm.
|
|
93
|
+
*/
|
|
94
|
+
export declare function roaringLibraryInitialize(): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* roaringLibraryIsReady - always true for native.
|
|
97
|
+
* Kept for API compatibility with roaring-wasm.
|
|
98
|
+
*/
|
|
99
|
+
export declare function roaringLibraryIsReady(): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Serialization format enum - for API compatibility with roaring-wasm.
|
|
102
|
+
*/
|
|
103
|
+
export declare const SerializationFormat: {
|
|
104
|
+
readonly portable: "portable";
|
|
105
|
+
readonly croaring: "croaring";
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Deserialization format enum - for API compatibility with roaring-wasm.
|
|
109
|
+
*/
|
|
110
|
+
export declare const DeserializationFormat: {
|
|
111
|
+
readonly portable: "portable";
|
|
112
|
+
readonly croaring: "croaring";
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=NativeRoaringBitmap32.d.ts.map
|