@soulcraft/brainy 3.37.2 → 3.37.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
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.37.3](https://github.com/soulcraftlabs/brainy/compare/v3.37.2...v3.37.3) (2025-10-10)
6
+
7
+ - fix: populate totalNodes/totalEdges in ALL storage adapters for HNSW rebuild (a21a845)
8
+
9
+
5
10
  ### [3.37.2](https://github.com/soulcraftlabs/brainy/compare/v3.37.1...v3.37.2) (2025-10-10)
6
11
 
7
12
  - fix: ensure GCS storage initialization before pagination (2565685)
@@ -1349,13 +1349,17 @@ export class FileSystemStorage extends BaseStorage {
1349
1349
  mergeStatistics(storageStats, localStats) {
1350
1350
  // Handle null cases
1351
1351
  if (!storageStats && !localStats) {
1352
+ // CRITICAL FIX (v3.37.4): Statistics files don't exist yet (first init)
1353
+ // Return minimal stats with counts instead of zeros
1354
+ // This prevents HNSW from seeing entityCount=0 during index rebuild
1352
1355
  return {
1353
1356
  nounCount: {},
1354
1357
  verbCount: {},
1355
1358
  metadataCount: {},
1356
1359
  hnswIndexSize: 0,
1357
- totalNodes: 0,
1358
- totalEdges: 0,
1360
+ totalNodes: this.totalNounCount,
1361
+ totalEdges: this.totalVerbCount,
1362
+ totalMetadata: 0,
1359
1363
  lastUpdated: new Date().toISOString()
1360
1364
  };
1361
1365
  }
@@ -1177,12 +1177,31 @@ export class GcsStorage extends BaseStorage {
1177
1177
  const [contents] = await file.download();
1178
1178
  const statistics = JSON.parse(contents.toString());
1179
1179
  this.logger.trace('Statistics retrieved successfully');
1180
- return statistics;
1180
+ // CRITICAL FIX: Populate totalNodes and totalEdges from in-memory counts
1181
+ // HNSW rebuild depends on these fields to determine entity count
1182
+ return {
1183
+ ...statistics,
1184
+ totalNodes: this.totalNounCount,
1185
+ totalEdges: this.totalVerbCount,
1186
+ lastUpdated: new Date().toISOString()
1187
+ };
1181
1188
  }
1182
1189
  catch (error) {
1183
1190
  if (error.code === 404) {
1184
- this.logger.trace('Statistics not found (creating new)');
1185
- return null;
1191
+ // CRITICAL FIX (v3.37.4): Statistics file doesn't exist yet (first restart)
1192
+ // Return minimal stats with counts instead of null
1193
+ // This prevents HNSW from seeing entityCount=0 during index rebuild
1194
+ this.logger.trace('Statistics file not found - returning minimal stats with counts');
1195
+ return {
1196
+ nounCount: {},
1197
+ verbCount: {},
1198
+ metadataCount: {},
1199
+ hnswIndexSize: 0,
1200
+ totalNodes: this.totalNounCount,
1201
+ totalEdges: this.totalVerbCount,
1202
+ totalMetadata: 0,
1203
+ lastUpdated: new Date().toISOString()
1204
+ };
1186
1205
  }
1187
1206
  this.logger.error('Failed to get statistics:', error);
1188
1207
  return null;
@@ -551,7 +551,19 @@ export class MemoryStorage extends BaseStorage {
551
551
  */
552
552
  async getStatisticsData() {
553
553
  if (!this.statistics) {
554
- return null;
554
+ // CRITICAL FIX (v3.37.4): Statistics don't exist yet (first init)
555
+ // Return minimal stats with counts instead of null
556
+ // This prevents HNSW from seeing entityCount=0 during index rebuild
557
+ return {
558
+ nounCount: {},
559
+ verbCount: {},
560
+ metadataCount: {},
561
+ hnswIndexSize: 0,
562
+ totalNodes: this.totalNounCount,
563
+ totalEdges: this.totalVerbCount,
564
+ totalMetadata: 0,
565
+ lastUpdated: new Date().toISOString()
566
+ };
555
567
  }
556
568
  // Return a deep copy to avoid reference issues
557
569
  return {
@@ -559,6 +571,10 @@ export class MemoryStorage extends BaseStorage {
559
571
  verbCount: { ...this.statistics.verbCount },
560
572
  metadataCount: { ...this.statistics.metadataCount },
561
573
  hnswIndexSize: this.statistics.hnswIndexSize,
574
+ // CRITICAL FIX: Populate totalNodes and totalEdges from in-memory counts
575
+ // HNSW rebuild depends on these fields to determine entity count
576
+ totalNodes: this.totalNounCount,
577
+ totalEdges: this.totalVerbCount,
562
578
  lastUpdated: this.statistics.lastUpdated,
563
579
  // Include serviceActivity if present
564
580
  ...(this.statistics.serviceActivity && {
@@ -1125,6 +1125,10 @@ export class OPFSStorage extends BaseStorage {
1125
1125
  verbCount: { ...this.statistics.verbCount },
1126
1126
  metadataCount: { ...this.statistics.metadataCount },
1127
1127
  hnswIndexSize: this.statistics.hnswIndexSize,
1128
+ // CRITICAL FIX: Populate totalNodes and totalEdges from in-memory counts
1129
+ // HNSW rebuild depends on these fields to determine entity count
1130
+ totalNodes: this.totalNounCount,
1131
+ totalEdges: this.totalVerbCount,
1128
1132
  lastUpdated: this.statistics.lastUpdated
1129
1133
  };
1130
1134
  }
@@ -1149,6 +1153,10 @@ export class OPFSStorage extends BaseStorage {
1149
1153
  verbCount: { ...this.statistics.verbCount },
1150
1154
  metadataCount: { ...this.statistics.metadataCount },
1151
1155
  hnswIndexSize: this.statistics.hnswIndexSize,
1156
+ // CRITICAL FIX: Populate totalNodes and totalEdges from in-memory counts
1157
+ // HNSW rebuild depends on these fields to determine entity count
1158
+ totalNodes: this.totalNounCount,
1159
+ totalEdges: this.totalVerbCount,
1152
1160
  lastUpdated: this.statistics.lastUpdated
1153
1161
  };
1154
1162
  }
@@ -1171,6 +1179,10 @@ export class OPFSStorage extends BaseStorage {
1171
1179
  verbCount: { ...this.statistics.verbCount },
1172
1180
  metadataCount: { ...this.statistics.metadataCount },
1173
1181
  hnswIndexSize: this.statistics.hnswIndexSize,
1182
+ // CRITICAL FIX: Populate totalNodes and totalEdges from in-memory counts
1183
+ // HNSW rebuild depends on these fields to determine entity count
1184
+ totalNodes: this.totalNounCount,
1185
+ totalEdges: this.totalVerbCount,
1174
1186
  lastUpdated: this.statistics.lastUpdated
1175
1187
  };
1176
1188
  }
@@ -1191,18 +1203,45 @@ export class OPFSStorage extends BaseStorage {
1191
1203
  verbCount: { ...this.statistics.verbCount },
1192
1204
  metadataCount: { ...this.statistics.metadataCount },
1193
1205
  hnswIndexSize: this.statistics.hnswIndexSize,
1206
+ // CRITICAL FIX: Populate totalNodes and totalEdges from in-memory counts
1207
+ // HNSW rebuild depends on these fields to determine entity count
1208
+ totalNodes: this.totalNounCount,
1209
+ totalEdges: this.totalVerbCount,
1194
1210
  lastUpdated: this.statistics.lastUpdated
1195
1211
  };
1196
1212
  }
1197
1213
  }
1198
1214
  catch (error) {
1199
- // If the legacy file doesn't exist either, return null
1200
- return null;
1215
+ // CRITICAL FIX (v3.37.4): No statistics files exist (first init)
1216
+ // Return minimal stats with counts instead of null
1217
+ // This prevents HNSW from seeing entityCount=0 during index rebuild
1218
+ return {
1219
+ nounCount: {},
1220
+ verbCount: {},
1221
+ metadataCount: {},
1222
+ hnswIndexSize: 0,
1223
+ totalNodes: this.totalNounCount,
1224
+ totalEdges: this.totalVerbCount,
1225
+ totalMetadata: 0,
1226
+ lastUpdated: new Date().toISOString()
1227
+ };
1201
1228
  }
1202
1229
  }
1203
1230
  }
1204
- // If we get here and statistics is null, return default statistics
1205
- return this.statistics ? this.statistics : null;
1231
+ // If we get here and statistics is null, return minimal stats with counts
1232
+ if (!this.statistics) {
1233
+ return {
1234
+ nounCount: {},
1235
+ verbCount: {},
1236
+ metadataCount: {},
1237
+ hnswIndexSize: 0,
1238
+ totalNodes: this.totalNounCount,
1239
+ totalEdges: this.totalVerbCount,
1240
+ totalMetadata: 0,
1241
+ lastUpdated: new Date().toISOString()
1242
+ };
1243
+ }
1244
+ return this.statistics;
1206
1245
  }
1207
1246
  catch (error) {
1208
1247
  console.error('Failed to get statistics data:', error);
@@ -2144,6 +2144,10 @@ export class S3CompatibleStorage extends BaseStorage {
2144
2144
  verbCount: { ...this.statisticsCache.verbCount },
2145
2145
  metadataCount: { ...this.statisticsCache.metadataCount },
2146
2146
  hnswIndexSize: this.statisticsCache.hnswIndexSize,
2147
+ // CRITICAL FIX: Populate totalNodes and totalEdges from in-memory counts
2148
+ // HNSW rebuild depends on these fields to determine entity count
2149
+ totalNodes: this.totalNounCount,
2150
+ totalEdges: this.totalVerbCount,
2147
2151
  lastUpdated: this.statisticsCache.lastUpdated
2148
2152
  };
2149
2153
  }
@@ -2186,6 +2190,26 @@ export class S3CompatibleStorage extends BaseStorage {
2186
2190
  hnswIndexSize: statistics.hnswIndexSize,
2187
2191
  lastUpdated: statistics.lastUpdated
2188
2192
  };
2193
+ // CRITICAL FIX: Add totalNodes and totalEdges from in-memory counts
2194
+ // HNSW rebuild depends on these fields to determine entity count
2195
+ return {
2196
+ ...statistics,
2197
+ totalNodes: this.totalNounCount,
2198
+ totalEdges: this.totalVerbCount
2199
+ };
2200
+ }
2201
+ // If we get here and statistics is null, return minimal stats with counts
2202
+ if (!statistics) {
2203
+ return {
2204
+ nounCount: {},
2205
+ verbCount: {},
2206
+ metadataCount: {},
2207
+ hnswIndexSize: 0,
2208
+ totalNodes: this.totalNounCount,
2209
+ totalEdges: this.totalVerbCount,
2210
+ totalMetadata: 0,
2211
+ lastUpdated: new Date().toISOString()
2212
+ };
2189
2213
  }
2190
2214
  // Successfully loaded statistics from storage
2191
2215
  return statistics;
@@ -2193,7 +2217,27 @@ export class S3CompatibleStorage extends BaseStorage {
2193
2217
  catch (error) {
2194
2218
  this.logger.warn('Error getting statistics data, returning cached or null:', error);
2195
2219
  // Return cached data if available, even if stale, rather than throwing
2196
- return this.statisticsCache || null;
2220
+ // CRITICAL FIX: Add totalNodes and totalEdges when returning cached data
2221
+ if (this.statisticsCache) {
2222
+ return {
2223
+ ...this.statisticsCache,
2224
+ totalNodes: this.totalNounCount,
2225
+ totalEdges: this.totalVerbCount
2226
+ };
2227
+ }
2228
+ // CRITICAL FIX (v3.37.4): Statistics file doesn't exist yet (first restart)
2229
+ // Return minimal stats with counts instead of null
2230
+ // This prevents HNSW from seeing entityCount=0 during index rebuild
2231
+ return {
2232
+ nounCount: {},
2233
+ verbCount: {},
2234
+ metadataCount: {},
2235
+ hnswIndexSize: 0,
2236
+ totalNodes: this.totalNounCount,
2237
+ totalEdges: this.totalVerbCount,
2238
+ totalMetadata: 0,
2239
+ lastUpdated: new Date().toISOString()
2240
+ };
2197
2241
  }
2198
2242
  }
2199
2243
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "3.37.2",
3
+ "version": "3.37.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",