@soulcraft/brainy 3.20.3 → 3.20.4
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.
|
@@ -897,26 +897,32 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
897
897
|
const limit = options.limit || 100;
|
|
898
898
|
const startIndex = options.cursor ? parseInt(options.cursor, 10) : 0;
|
|
899
899
|
try {
|
|
900
|
-
//
|
|
901
|
-
const
|
|
900
|
+
// Get actual verb files first (critical for accuracy)
|
|
901
|
+
const verbFiles = await this.getAllShardedFiles(this.verbsDir);
|
|
902
|
+
verbFiles.sort(); // Consistent ordering for pagination
|
|
903
|
+
// Use actual file count - don't trust cached totalVerbCount
|
|
904
|
+
// This prevents accessing undefined array elements
|
|
905
|
+
const actualFileCount = verbFiles.length;
|
|
902
906
|
// For large datasets, warn about performance
|
|
903
|
-
if (
|
|
904
|
-
console.warn(`Very large verb dataset detected (${
|
|
907
|
+
if (actualFileCount > 1000000) {
|
|
908
|
+
console.warn(`Very large verb dataset detected (${actualFileCount} verbs). Performance may be degraded. Consider database storage for optimal performance.`);
|
|
905
909
|
}
|
|
906
|
-
// Calculate pagination bounds
|
|
907
|
-
const endIndex = Math.min(startIndex + limit, totalCount);
|
|
908
|
-
const hasMore = endIndex < totalCount;
|
|
909
910
|
// For production-scale datasets, use streaming approach
|
|
910
|
-
if (
|
|
911
|
+
if (actualFileCount > 50000) {
|
|
911
912
|
return await this.getVerbsWithPaginationStreaming(options, startIndex, limit);
|
|
912
913
|
}
|
|
913
|
-
//
|
|
914
|
-
const
|
|
915
|
-
verbFiles.sort(); // This is still acceptable for <50k files
|
|
914
|
+
// Calculate pagination bounds using ACTUAL file count
|
|
915
|
+
const endIndex = Math.min(startIndex + limit, actualFileCount);
|
|
916
916
|
// Load the requested page of verbs
|
|
917
917
|
const verbs = [];
|
|
918
|
+
let successfullyLoaded = 0;
|
|
918
919
|
for (let i = startIndex; i < endIndex; i++) {
|
|
919
920
|
const file = verbFiles[i];
|
|
921
|
+
// CRITICAL: Null-safety check for undefined array elements
|
|
922
|
+
if (!file) {
|
|
923
|
+
console.warn(`Unexpected undefined file at index ${i}, skipping`);
|
|
924
|
+
continue;
|
|
925
|
+
}
|
|
920
926
|
const id = file.replace('.json', '');
|
|
921
927
|
try {
|
|
922
928
|
// Read the verb data (HNSWVerb stored as edge) - use sharded path
|
|
@@ -1003,14 +1009,18 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
1003
1009
|
}
|
|
1004
1010
|
}
|
|
1005
1011
|
verbs.push(verb);
|
|
1012
|
+
successfullyLoaded++;
|
|
1006
1013
|
}
|
|
1007
1014
|
catch (error) {
|
|
1008
1015
|
console.warn(`Failed to read verb ${id}:`, error);
|
|
1009
1016
|
}
|
|
1010
1017
|
}
|
|
1018
|
+
// CRITICAL FIX: hasMore based on actual file count, not cached totalVerbCount
|
|
1019
|
+
// Also verify we successfully loaded items (prevents infinite loops on corrupted storage)
|
|
1020
|
+
const hasMore = (endIndex < actualFileCount) && (successfullyLoaded > 0 || startIndex === 0);
|
|
1011
1021
|
return {
|
|
1012
1022
|
items: verbs,
|
|
1013
|
-
totalCount,
|
|
1023
|
+
totalCount: actualFileCount, // Return actual count, not cached value
|
|
1014
1024
|
hasMore,
|
|
1015
1025
|
nextCursor: hasMore ? String(endIndex) : undefined
|
|
1016
1026
|
};
|
|
@@ -1587,14 +1597,14 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
1587
1597
|
*/
|
|
1588
1598
|
async getVerbsWithPaginationStreaming(options, startIndex, limit) {
|
|
1589
1599
|
const verbs = [];
|
|
1590
|
-
const totalCount = this.totalVerbCount || 0;
|
|
1591
1600
|
let processedCount = 0;
|
|
1592
1601
|
let skippedCount = 0;
|
|
1593
1602
|
let resultCount = 0;
|
|
1594
1603
|
const depth = this.cachedShardingDepth ?? this.getOptimalShardingDepth();
|
|
1595
1604
|
try {
|
|
1596
1605
|
// Stream through sharded directories efficiently
|
|
1597
|
-
|
|
1606
|
+
// hasMore=false means we reached the end of files, hasMore=true means streaming stopped early
|
|
1607
|
+
const streamingHasMore = await this.streamShardedFiles(this.verbsDir, depth, async (filename, filePath) => {
|
|
1598
1608
|
// Skip files until we reach start index
|
|
1599
1609
|
if (skippedCount < startIndex) {
|
|
1600
1610
|
skippedCount++;
|
|
@@ -1602,7 +1612,7 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
1602
1612
|
}
|
|
1603
1613
|
// Stop if we have enough results
|
|
1604
1614
|
if (resultCount >= limit) {
|
|
1605
|
-
return false; // stop streaming
|
|
1615
|
+
return false; // stop streaming - more files exist
|
|
1606
1616
|
}
|
|
1607
1617
|
try {
|
|
1608
1618
|
const id = filename.replace('.json', '');
|
|
@@ -1666,10 +1676,13 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
1666
1676
|
return true; // continue
|
|
1667
1677
|
}
|
|
1668
1678
|
});
|
|
1669
|
-
|
|
1679
|
+
// CRITICAL FIX: Use streaming result for hasMore, not cached totalVerbCount
|
|
1680
|
+
// streamingHasMore=false means we exhausted all files
|
|
1681
|
+
// Also verify we loaded items to prevent infinite loops
|
|
1682
|
+
const finalHasMore = streamingHasMore && (resultCount > 0 || startIndex === 0);
|
|
1670
1683
|
return {
|
|
1671
1684
|
items: verbs,
|
|
1672
|
-
totalCount,
|
|
1685
|
+
totalCount: this.totalVerbCount || undefined, // Return cached count as hint only
|
|
1673
1686
|
hasMore: finalHasMore,
|
|
1674
1687
|
nextCursor: finalHasMore ? String(startIndex + resultCount) : undefined
|
|
1675
1688
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soulcraft/brainy",
|
|
3
|
-
"version": "3.20.
|
|
3
|
+
"version": "3.20.4",
|
|
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",
|