@soulcraft/brainy 3.43.0 β 3.43.2
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/CHANGELOG.md +15 -0
- package/dist/brainy.d.ts +22 -0
- package/dist/brainy.js +54 -0
- package/dist/graph/graphAdjacencyIndex.d.ts +2 -1
- package/dist/graph/graphAdjacencyIndex.js +1 -0
- package/dist/import/ImportCoordinator.js +19 -6
- package/dist/storage/adapters/fileSystemStorage.d.ts +5 -0
- package/dist/storage/adapters/fileSystemStorage.js +69 -57
- package/dist/utils/metadataIndex.js +1 -1
- package/dist/utils/metadataIndexChunking.d.ts +1 -1
- package/dist/utils/metadataIndexChunking.js +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [3.43.1](https://github.com/soulcraftlabs/brainy/compare/v3.43.0...v3.43.1) (2025-10-14)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### π Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **dependencies**: migrate from roaring (native C++) to roaring-wasm for universal compatibility ([b2afcad](https://github.com/soulcraftlabs/brainy/commit/b2afcad))
|
|
11
|
+
- Eliminates native compilation requirements (no python, make, gcc/g++ needed)
|
|
12
|
+
- Works in all environments (Node.js, browsers, serverless, Docker, Lambda, Cloud Run)
|
|
13
|
+
- Same API and performance (100% compatible RoaringBitmap32 interface)
|
|
14
|
+
- 90% memory savings maintained vs JavaScript Sets
|
|
15
|
+
- Hardware-accelerated bitmap operations unchanged
|
|
16
|
+
- WebAssembly-based for cross-platform compatibility
|
|
17
|
+
|
|
18
|
+
**Impact**: Fixes installation failures on systems without native build tools. Users can now `npm install @soulcraft/brainy` without any prerequisites.
|
|
19
|
+
|
|
5
20
|
### [3.41.1](https://github.com/soulcraftlabs/brainy/compare/v3.41.0...v3.41.1) (2025-10-13)
|
|
6
21
|
|
|
7
22
|
- test: skip failing delete test temporarily (7c47de8)
|
package/dist/brainy.d.ts
CHANGED
|
@@ -791,6 +791,28 @@ export declare class Brainy<T = any> implements BrainyInterface<T> {
|
|
|
791
791
|
services: string[];
|
|
792
792
|
density: number;
|
|
793
793
|
}>;
|
|
794
|
+
/**
|
|
795
|
+
* Flush all indexes and caches to persistent storage
|
|
796
|
+
* CRITICAL FIX (v3.43.2): Ensures data survives server restarts
|
|
797
|
+
*
|
|
798
|
+
* Flushes all 4 core indexes:
|
|
799
|
+
* 1. Storage counts (entity/verb counts by type)
|
|
800
|
+
* 2. Metadata index (field indexes + EntityIdMapper)
|
|
801
|
+
* 3. Graph adjacency index (relationship cache)
|
|
802
|
+
* 4. HNSW vector index (no flush needed - saves directly)
|
|
803
|
+
*
|
|
804
|
+
* @example
|
|
805
|
+
* // Flush after bulk operations
|
|
806
|
+
* await brain.import('./data.xlsx')
|
|
807
|
+
* await brain.flush()
|
|
808
|
+
*
|
|
809
|
+
* // Flush before shutdown
|
|
810
|
+
* process.on('SIGTERM', async () => {
|
|
811
|
+
* await brain.flush()
|
|
812
|
+
* process.exit(0)
|
|
813
|
+
* })
|
|
814
|
+
*/
|
|
815
|
+
flush(): Promise<void>;
|
|
794
816
|
/**
|
|
795
817
|
* Efficient Pagination API - Production-scale pagination using index-first approach
|
|
796
818
|
* Automatically optimizes based on query type and applies pagination at the index level
|
package/dist/brainy.js
CHANGED
|
@@ -609,6 +609,17 @@ export class Brainy {
|
|
|
609
609
|
if (!toEntity) {
|
|
610
610
|
throw new Error(`Target entity ${params.to} not found`);
|
|
611
611
|
}
|
|
612
|
+
// CRITICAL FIX (v3.43.2): Check for duplicate relationships
|
|
613
|
+
// This prevents infinite loops where same relationship is created repeatedly
|
|
614
|
+
// Bug #1 showed incrementing verb counts (7β8β9...) indicating duplicates
|
|
615
|
+
const existingVerbs = await this.storage.getVerbsBySource(params.from);
|
|
616
|
+
const duplicate = existingVerbs.find(v => v.targetId === params.to &&
|
|
617
|
+
v.type === params.type);
|
|
618
|
+
if (duplicate) {
|
|
619
|
+
// Relationship already exists - return existing ID instead of creating duplicate
|
|
620
|
+
console.log(`[DEBUG] Skipping duplicate relationship: ${params.from} β ${params.to} (${params.type})`);
|
|
621
|
+
return duplicate.id;
|
|
622
|
+
}
|
|
612
623
|
// Generate ID
|
|
613
624
|
const id = uuidv4();
|
|
614
625
|
// Compute relationship vector (average of entities)
|
|
@@ -1625,6 +1636,49 @@ export class Brainy {
|
|
|
1625
1636
|
density
|
|
1626
1637
|
};
|
|
1627
1638
|
}
|
|
1639
|
+
/**
|
|
1640
|
+
* Flush all indexes and caches to persistent storage
|
|
1641
|
+
* CRITICAL FIX (v3.43.2): Ensures data survives server restarts
|
|
1642
|
+
*
|
|
1643
|
+
* Flushes all 4 core indexes:
|
|
1644
|
+
* 1. Storage counts (entity/verb counts by type)
|
|
1645
|
+
* 2. Metadata index (field indexes + EntityIdMapper)
|
|
1646
|
+
* 3. Graph adjacency index (relationship cache)
|
|
1647
|
+
* 4. HNSW vector index (no flush needed - saves directly)
|
|
1648
|
+
*
|
|
1649
|
+
* @example
|
|
1650
|
+
* // Flush after bulk operations
|
|
1651
|
+
* await brain.import('./data.xlsx')
|
|
1652
|
+
* await brain.flush()
|
|
1653
|
+
*
|
|
1654
|
+
* // Flush before shutdown
|
|
1655
|
+
* process.on('SIGTERM', async () => {
|
|
1656
|
+
* await brain.flush()
|
|
1657
|
+
* process.exit(0)
|
|
1658
|
+
* })
|
|
1659
|
+
*/
|
|
1660
|
+
async flush() {
|
|
1661
|
+
await this.ensureInitialized();
|
|
1662
|
+
console.log('π Flushing Brainy indexes and caches to disk...');
|
|
1663
|
+
const startTime = Date.now();
|
|
1664
|
+
// Flush all components in parallel for performance
|
|
1665
|
+
await Promise.all([
|
|
1666
|
+
// 1. Flush storage adapter counts (entity/verb counts by type)
|
|
1667
|
+
(async () => {
|
|
1668
|
+
if (this.storage && typeof this.storage.flushCounts === 'function') {
|
|
1669
|
+
await this.storage.flushCounts();
|
|
1670
|
+
}
|
|
1671
|
+
})(),
|
|
1672
|
+
// 2. Flush metadata index (field indexes + EntityIdMapper)
|
|
1673
|
+
this.metadataIndex.flush(),
|
|
1674
|
+
// 3. Flush graph adjacency index (relationship cache)
|
|
1675
|
+
// Note: Graph structure is already persisted via storage.saveVerb() calls
|
|
1676
|
+
// This just flushes the in-memory cache for performance
|
|
1677
|
+
this.graphIndex.flush()
|
|
1678
|
+
]);
|
|
1679
|
+
const elapsed = Date.now() - startTime;
|
|
1680
|
+
console.log(`β
All indexes flushed to disk in ${elapsed}ms`);
|
|
1681
|
+
}
|
|
1628
1682
|
/**
|
|
1629
1683
|
* Efficient Pagination API - Production-scale pagination using index-first approach
|
|
1630
1684
|
* Automatically optimizes based on query type and applies pagination at the index level
|
|
@@ -106,8 +106,9 @@ export declare class GraphAdjacencyIndex {
|
|
|
106
106
|
private startAutoFlush;
|
|
107
107
|
/**
|
|
108
108
|
* Flush dirty entries to cache
|
|
109
|
+
* CRITICAL FIX (v3.43.2): Now public so it can be called from brain.flush()
|
|
109
110
|
*/
|
|
110
|
-
|
|
111
|
+
flush(): Promise<void>;
|
|
111
112
|
/**
|
|
112
113
|
* Clean shutdown
|
|
113
114
|
*/
|
|
@@ -299,6 +299,7 @@ export class GraphAdjacencyIndex {
|
|
|
299
299
|
}
|
|
300
300
|
/**
|
|
301
301
|
* Flush dirty entries to cache
|
|
302
|
+
* CRITICAL FIX (v3.43.2): Now public so it can be called from brain.flush()
|
|
302
303
|
*/
|
|
303
304
|
async flush() {
|
|
304
305
|
if (this.dirtySourceIds.size === 0 && this.dirtyTargetIds.size === 0) {
|
|
@@ -156,6 +156,14 @@ export class ImportCoordinator {
|
|
|
156
156
|
format: detection.format
|
|
157
157
|
}, result);
|
|
158
158
|
}
|
|
159
|
+
// CRITICAL FIX (v3.43.2): Auto-flush all indexes before returning
|
|
160
|
+
// Ensures imported data survives server restarts
|
|
161
|
+
// Bug #5: Import data was only in memory, lost on restart
|
|
162
|
+
options.onProgress?.({
|
|
163
|
+
stage: 'complete',
|
|
164
|
+
message: 'Flushing indexes to disk...'
|
|
165
|
+
});
|
|
166
|
+
await this.brain.flush();
|
|
159
167
|
return result;
|
|
160
168
|
}
|
|
161
169
|
/**
|
|
@@ -373,24 +381,28 @@ export class ImportCoordinator {
|
|
|
373
381
|
if (options.createRelationships && row.relationships) {
|
|
374
382
|
for (const rel of row.relationships) {
|
|
375
383
|
try {
|
|
376
|
-
//
|
|
384
|
+
// CRITICAL FIX (v3.43.2): Prevent infinite placeholder creation loop
|
|
385
|
+
// Find or create target entity using EXACT matching only
|
|
377
386
|
let targetEntityId;
|
|
378
|
-
// Check if target already exists in
|
|
387
|
+
// STEP 1: Check if target already exists in entities list (includes placeholders)
|
|
388
|
+
// This prevents creating duplicate placeholders - the root cause of Bug #1
|
|
379
389
|
const existingTarget = entities.find(e => e.name.toLowerCase() === rel.to.toLowerCase());
|
|
380
390
|
if (existingTarget) {
|
|
381
391
|
targetEntityId = existingTarget.id;
|
|
382
392
|
}
|
|
383
393
|
else {
|
|
384
|
-
// Try to find in
|
|
394
|
+
// STEP 2: Try to find in extraction results (rows)
|
|
395
|
+
// FIX: Use EXACT matching instead of fuzzy .includes()
|
|
396
|
+
// Fuzzy matching caused false matches (e.g., "Entity_29" matching "Entity_297")
|
|
385
397
|
for (const otherRow of rows) {
|
|
386
398
|
const otherEntity = otherRow.entity || otherRow;
|
|
387
|
-
if (
|
|
388
|
-
otherEntity.name.toLowerCase().includes(rel.to.toLowerCase())) {
|
|
399
|
+
if (otherEntity.name.toLowerCase() === rel.to.toLowerCase()) {
|
|
389
400
|
targetEntityId = otherEntity.id;
|
|
390
401
|
break;
|
|
391
402
|
}
|
|
392
403
|
}
|
|
393
|
-
// If still not found, create placeholder entity
|
|
404
|
+
// STEP 3: If still not found, create placeholder entity ONCE
|
|
405
|
+
// The placeholder is added to entities array, so future searches will find it
|
|
394
406
|
if (!targetEntityId) {
|
|
395
407
|
targetEntityId = await this.brain.add({
|
|
396
408
|
data: rel.to,
|
|
@@ -402,6 +414,7 @@ export class ImportCoordinator {
|
|
|
402
414
|
importedAt: Date.now()
|
|
403
415
|
}
|
|
404
416
|
});
|
|
417
|
+
// CRITICAL: Add to entities array so future searches find it
|
|
405
418
|
entities.push({
|
|
406
419
|
id: targetEntityId,
|
|
407
420
|
name: rel.to,
|
|
@@ -55,10 +55,13 @@ export declare class FileSystemStorage extends BaseStorage {
|
|
|
55
55
|
protected getNode(id: string): Promise<HNSWNode | null>;
|
|
56
56
|
/**
|
|
57
57
|
* Get all nodes from storage
|
|
58
|
+
* CRITICAL FIX (v3.43.2): Now scans sharded subdirectories (depth=1)
|
|
59
|
+
* Previously only scanned flat directory, causing rebuild to find 0 entities
|
|
58
60
|
*/
|
|
59
61
|
protected getAllNodes(): Promise<HNSWNode[]>;
|
|
60
62
|
/**
|
|
61
63
|
* Get nodes by noun type
|
|
64
|
+
* CRITICAL FIX (v3.43.2): Now scans sharded subdirectories (depth=1)
|
|
62
65
|
* @param nounType The noun type to filter by
|
|
63
66
|
* @returns Promise that resolves to an array of nodes of the specified noun type
|
|
64
67
|
*/
|
|
@@ -77,6 +80,8 @@ export declare class FileSystemStorage extends BaseStorage {
|
|
|
77
80
|
protected getEdge(id: string): Promise<Edge | null>;
|
|
78
81
|
/**
|
|
79
82
|
* Get all edges from storage
|
|
83
|
+
* CRITICAL FIX (v3.43.2): Now scans sharded subdirectories (depth=1)
|
|
84
|
+
* Previously only scanned flat directory, causing rebuild to find 0 relationships
|
|
80
85
|
*/
|
|
81
86
|
protected getAllEdges(): Promise<Edge[]>;
|
|
82
87
|
/**
|
|
@@ -224,29 +224,33 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
224
224
|
}
|
|
225
225
|
/**
|
|
226
226
|
* Get all nodes from storage
|
|
227
|
+
* CRITICAL FIX (v3.43.2): Now scans sharded subdirectories (depth=1)
|
|
228
|
+
* Previously only scanned flat directory, causing rebuild to find 0 entities
|
|
227
229
|
*/
|
|
228
230
|
async getAllNodes() {
|
|
229
231
|
await this.ensureInitialized();
|
|
230
232
|
const allNodes = [];
|
|
231
233
|
try {
|
|
232
|
-
|
|
234
|
+
// FIX: Use sharded file discovery instead of flat directory read
|
|
235
|
+
// This scans all 256 shard subdirectories (00-ff) to find actual files
|
|
236
|
+
const files = await this.getAllShardedFiles(this.nounsDir);
|
|
233
237
|
for (const file of files) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
allNodes.push({
|
|
244
|
-
id: parsedNode.id,
|
|
245
|
-
vector: parsedNode.vector,
|
|
246
|
-
connections,
|
|
247
|
-
level: parsedNode.level || 0
|
|
248
|
-
});
|
|
238
|
+
// Extract ID from filename and use sharded path
|
|
239
|
+
const id = file.replace('.json', '');
|
|
240
|
+
const filePath = this.getNodePath(id);
|
|
241
|
+
const data = await fs.promises.readFile(filePath, 'utf-8');
|
|
242
|
+
const parsedNode = JSON.parse(data);
|
|
243
|
+
// Convert serialized connections back to Map<number, Set<string>>
|
|
244
|
+
const connections = new Map();
|
|
245
|
+
for (const [level, nodeIds] of Object.entries(parsedNode.connections)) {
|
|
246
|
+
connections.set(Number(level), new Set(nodeIds));
|
|
249
247
|
}
|
|
248
|
+
allNodes.push({
|
|
249
|
+
id: parsedNode.id,
|
|
250
|
+
vector: parsedNode.vector,
|
|
251
|
+
connections,
|
|
252
|
+
level: parsedNode.level || 0
|
|
253
|
+
});
|
|
250
254
|
}
|
|
251
255
|
}
|
|
252
256
|
catch (error) {
|
|
@@ -258,6 +262,7 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
258
262
|
}
|
|
259
263
|
/**
|
|
260
264
|
* Get nodes by noun type
|
|
265
|
+
* CRITICAL FIX (v3.43.2): Now scans sharded subdirectories (depth=1)
|
|
261
266
|
* @param nounType The noun type to filter by
|
|
262
267
|
* @returns Promise that resolves to an array of nodes of the specified noun type
|
|
263
268
|
*/
|
|
@@ -265,28 +270,28 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
265
270
|
await this.ensureInitialized();
|
|
266
271
|
const nouns = [];
|
|
267
272
|
try {
|
|
268
|
-
|
|
273
|
+
// FIX: Use sharded file discovery instead of flat directory read
|
|
274
|
+
const files = await this.getAllShardedFiles(this.nounsDir);
|
|
269
275
|
for (const file of files) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
nouns.push({
|
|
284
|
-
id: parsedNode.id,
|
|
285
|
-
vector: parsedNode.vector,
|
|
286
|
-
connections,
|
|
287
|
-
level: parsedNode.level || 0
|
|
288
|
-
});
|
|
276
|
+
// Extract ID from filename and use sharded path
|
|
277
|
+
const nodeId = file.replace('.json', '');
|
|
278
|
+
const filePath = this.getNodePath(nodeId);
|
|
279
|
+
const data = await fs.promises.readFile(filePath, 'utf-8');
|
|
280
|
+
const parsedNode = JSON.parse(data);
|
|
281
|
+
// Filter by noun type using metadata
|
|
282
|
+
const metadata = await this.getMetadata(nodeId);
|
|
283
|
+
if (metadata && metadata.noun === nounType) {
|
|
284
|
+
// Convert serialized connections back to Map<number, Set<string>>
|
|
285
|
+
const connections = new Map();
|
|
286
|
+
for (const [level, nodeIds] of Object.entries(parsedNode.connections)) {
|
|
287
|
+
connections.set(Number(level), new Set(nodeIds));
|
|
289
288
|
}
|
|
289
|
+
nouns.push({
|
|
290
|
+
id: parsedNode.id,
|
|
291
|
+
vector: parsedNode.vector,
|
|
292
|
+
connections,
|
|
293
|
+
level: parsedNode.level || 0
|
|
294
|
+
});
|
|
290
295
|
}
|
|
291
296
|
}
|
|
292
297
|
}
|
|
@@ -385,28 +390,32 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
385
390
|
}
|
|
386
391
|
/**
|
|
387
392
|
* Get all edges from storage
|
|
393
|
+
* CRITICAL FIX (v3.43.2): Now scans sharded subdirectories (depth=1)
|
|
394
|
+
* Previously only scanned flat directory, causing rebuild to find 0 relationships
|
|
388
395
|
*/
|
|
389
396
|
async getAllEdges() {
|
|
390
397
|
await this.ensureInitialized();
|
|
391
398
|
const allEdges = [];
|
|
392
399
|
try {
|
|
393
|
-
|
|
400
|
+
// FIX: Use sharded file discovery instead of flat directory read
|
|
401
|
+
// This scans all 256 shard subdirectories (00-ff) to find actual files
|
|
402
|
+
const files = await this.getAllShardedFiles(this.verbsDir);
|
|
394
403
|
for (const file of files) {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
allEdges.push({
|
|
405
|
-
id: parsedEdge.id,
|
|
406
|
-
vector: parsedEdge.vector,
|
|
407
|
-
connections
|
|
408
|
-
});
|
|
404
|
+
// Extract ID from filename and use sharded path
|
|
405
|
+
const id = file.replace('.json', '');
|
|
406
|
+
const filePath = this.getVerbPath(id);
|
|
407
|
+
const data = await fs.promises.readFile(filePath, 'utf-8');
|
|
408
|
+
const parsedEdge = JSON.parse(data);
|
|
409
|
+
// Convert serialized connections back to Map<number, Set<string>>
|
|
410
|
+
const connections = new Map();
|
|
411
|
+
for (const [level, nodeIds] of Object.entries(parsedEdge.connections)) {
|
|
412
|
+
connections.set(Number(level), new Set(nodeIds));
|
|
409
413
|
}
|
|
414
|
+
allEdges.push({
|
|
415
|
+
id: parsedEdge.id,
|
|
416
|
+
vector: parsedEdge.vector,
|
|
417
|
+
connections
|
|
418
|
+
});
|
|
410
419
|
}
|
|
411
420
|
}
|
|
412
421
|
catch (error) {
|
|
@@ -803,13 +812,16 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
803
812
|
const metadataDirSize = await calculateSize(this.metadataDir);
|
|
804
813
|
const indexDirSize = await calculateSize(this.indexDir);
|
|
805
814
|
totalSize = nounsDirSize + verbsDirSize + metadataDirSize + indexDirSize;
|
|
806
|
-
//
|
|
807
|
-
|
|
808
|
-
const
|
|
815
|
+
// CRITICAL FIX (v3.43.2): Use persisted counts instead of directory reads
|
|
816
|
+
// This is O(1) instead of O(n), and handles sharded structure correctly
|
|
817
|
+
const nounsCount = this.totalNounCount;
|
|
818
|
+
const verbsCount = this.totalVerbCount;
|
|
819
|
+
// Count metadata files (these are NOT sharded)
|
|
809
820
|
const metadataCount = (await fs.promises.readdir(this.metadataDir)).filter((file) => file.endsWith('.json')).length;
|
|
810
|
-
//
|
|
811
|
-
const nounTypeCounts =
|
|
812
|
-
|
|
821
|
+
// Use persisted entity counts by type (O(1) instead of scanning all files)
|
|
822
|
+
const nounTypeCounts = Object.fromEntries(this.entityCounts);
|
|
823
|
+
// Skip the expensive metadata file scan since we have counts
|
|
824
|
+
const metadataFiles = []; // Empty array to skip the loop below
|
|
813
825
|
for (const file of metadataFiles) {
|
|
814
826
|
if (file.endsWith('.json')) {
|
|
815
827
|
try {
|
|
@@ -8,7 +8,7 @@ import { prodLog } from './logger.js';
|
|
|
8
8
|
import { getGlobalCache } from './unifiedCache.js';
|
|
9
9
|
import { SparseIndex, ChunkManager, AdaptiveChunkingStrategy } from './metadataIndexChunking.js';
|
|
10
10
|
import { EntityIdMapper } from './entityIdMapper.js';
|
|
11
|
-
import { RoaringBitmap32 } from 'roaring';
|
|
11
|
+
import { RoaringBitmap32 } from 'roaring-wasm';
|
|
12
12
|
export class MetadataIndexManager {
|
|
13
13
|
constructor(storage, config = {}) {
|
|
14
14
|
this.isRebuilding = false;
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* - EntityIdMapper handles UUID β integer conversion
|
|
21
21
|
*/
|
|
22
22
|
import { StorageAdapter } from '../coreTypes.js';
|
|
23
|
-
import { RoaringBitmap32 } from 'roaring';
|
|
23
|
+
import { RoaringBitmap32 } from 'roaring-wasm';
|
|
24
24
|
import type { EntityIdMapper } from './entityIdMapper.js';
|
|
25
25
|
/**
|
|
26
26
|
* Zone Map for range query optimization
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* - EntityIdMapper handles UUID β integer conversion
|
|
21
21
|
*/
|
|
22
22
|
import { prodLog } from './logger.js';
|
|
23
|
-
import { RoaringBitmap32 } from 'roaring';
|
|
23
|
+
import { RoaringBitmap32 } from 'roaring-wasm';
|
|
24
24
|
// ============================================================================
|
|
25
25
|
// BloomFilter - Production-Ready Implementation
|
|
26
26
|
// ============================================================================
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soulcraft/brainy",
|
|
3
|
-
"version": "3.43.
|
|
3
|
+
"version": "3.43.2",
|
|
4
4
|
"description": "Universal Knowledge Protocolβ’ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. 31 nouns Γ 40 verbs for infinite expressiveness.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
"ora": "^8.2.0",
|
|
173
173
|
"pdfjs-dist": "^4.0.379",
|
|
174
174
|
"prompts": "^2.4.2",
|
|
175
|
-
"roaring": "^
|
|
175
|
+
"roaring-wasm": "^1.1.0",
|
|
176
176
|
"uuid": "^9.0.1",
|
|
177
177
|
"ws": "^8.18.3",
|
|
178
178
|
"xlsx": "^0.18.5"
|