@soulcraft/brainy 3.40.1 → 3.40.3

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,18 @@
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.40.3](https://github.com/soulcraftlabs/brainy/compare/v3.40.2...v3.40.3) (2025-10-13)
6
+
7
+ - fix: prevent metadata index file pollution by excluding high-cardinality fields (0c86c4f)
8
+
9
+
10
+ ### [3.40.2](https://github.com/soulcraftlabs/brainy/compare/v3.40.1...v3.40.2) (2025-10-13)
11
+
12
+
13
+ ### ⚡ Performance Improvements
14
+
15
+ * more aggressive cache fairness to prevent thrashing ([829a8a6](https://github.com/soulcraftlabs/brainy/commit/829a8a61a23688aae1384b2844f1e75b1fd773d9))
16
+
5
17
  ### [3.40.1](https://github.com/soulcraftlabs/brainy/compare/v3.40.0...v3.40.1) (2025-10-13)
6
18
 
7
19
 
@@ -39,7 +39,37 @@ export class MetadataIndexManager {
39
39
  rebuildThreshold: config.rebuildThreshold ?? 0.1,
40
40
  autoOptimize: config.autoOptimize ?? true,
41
41
  indexedFields: config.indexedFields ?? [],
42
- excludeFields: config.excludeFields ?? ['id', 'createdAt', 'updatedAt', 'embedding', 'vector', 'embeddings', 'vectors']
42
+ excludeFields: config.excludeFields ?? [
43
+ // Timestamps (nearly unique per operation - causes massive file pollution)
44
+ 'accessed',
45
+ 'modified',
46
+ 'createdAt',
47
+ 'updatedAt',
48
+ 'importedAt',
49
+ 'extractedAt',
50
+ // UUIDs (unique per entity/relationship - creates one file per entity)
51
+ 'id',
52
+ 'parent',
53
+ 'sourceId',
54
+ 'targetId',
55
+ 'source',
56
+ 'target',
57
+ 'owner',
58
+ // Paths and hashes (unique per file - creates one file per path)
59
+ 'path',
60
+ 'hash',
61
+ 'url',
62
+ // Content fields (too large/unique - unnecessary for indexing)
63
+ 'content',
64
+ 'data',
65
+ 'originalData',
66
+ '_data',
67
+ // Vectors (already excluded - keeping for backward compatibility)
68
+ 'embedding',
69
+ 'vector',
70
+ 'embeddings',
71
+ 'vectors'
72
+ ]
43
73
  };
44
74
  // Initialize metadata cache with similar config to search cache
45
75
  this.metadataCache = new MetadataIndexCache({
@@ -78,6 +78,12 @@ export declare class UnifiedCache {
78
78
  */
79
79
  private startFairnessMonitor;
80
80
  private checkFairness;
81
+ /**
82
+ * Proactive fairness check (v3.40.2)
83
+ * Called immediately when adding items to prevent imbalance formation
84
+ * Uses same thresholds as periodic check but runs on-demand
85
+ */
86
+ private checkProactiveFairness;
81
87
  /**
82
88
  * Force evict items of a specific type
83
89
  */
@@ -50,7 +50,7 @@ export class UnifiedCache {
50
50
  this.config = {
51
51
  enableRequestCoalescing: true,
52
52
  enableFairnessCheck: true,
53
- fairnessCheckInterval: 60000, // Check fairness every minute
53
+ fairnessCheckInterval: 30000, // Check fairness every 30 seconds (v3.40.2: was 60s)
54
54
  persistPatterns: true,
55
55
  enableMemoryMonitoring: true,
56
56
  memoryCheckInterval: 30000, // Check memory every 30s
@@ -149,6 +149,11 @@ export class UnifiedCache {
149
149
  this.currentSize += size;
150
150
  this.typeAccessCounts[type]++;
151
151
  this.totalAccessCount++;
152
+ // Proactive fairness check (v3.40.2): Check immediately if adding to a dominant type
153
+ // This prevents imbalance formation instead of reacting to it
154
+ if (this.config.enableFairnessCheck && this.cache.size > 10) {
155
+ this.checkProactiveFairness(type);
156
+ }
152
157
  }
153
158
  /**
154
159
  * Evict item with lowest value (access count / rebuild cost)
@@ -235,14 +240,36 @@ export class UnifiedCache {
235
240
  embedding: typeSizes.embedding / totalSize,
236
241
  other: typeSizes.other / totalSize
237
242
  };
238
- // Check for starvation (90% cache but <10% accesses)
243
+ // Check for starvation (v3.40.2: more aggressive - 70% cache with <15% accesses)
244
+ // Previous: 90% cache, <10% access (too lenient, caused thrashing)
239
245
  for (const type of ['hnsw', 'metadata', 'embedding', 'other']) {
240
- if (sizeRatios[type] > 0.9 && accessRatios[type] < 0.1) {
246
+ if (sizeRatios[type] > 0.7 && accessRatios[type] < 0.15) {
241
247
  prodLog.warn(`Type ${type} is hogging cache (${(sizeRatios[type] * 100).toFixed(1)}% size, ${(accessRatios[type] * 100).toFixed(1)}% access)`);
242
248
  this.evictType(type);
243
249
  }
244
250
  }
245
251
  }
252
+ /**
253
+ * Proactive fairness check (v3.40.2)
254
+ * Called immediately when adding items to prevent imbalance formation
255
+ * Uses same thresholds as periodic check but runs on-demand
256
+ */
257
+ checkProactiveFairness(addedType) {
258
+ // Quick check: only evaluate the type being added
259
+ let typeSize = 0;
260
+ for (const item of this.cache.values()) {
261
+ if (item.type === addedType) {
262
+ typeSize += item.size;
263
+ }
264
+ }
265
+ const sizeRatio = typeSize / (this.currentSize || 1);
266
+ const accessRatio = this.typeAccessCounts[addedType] / (this.totalAccessCount || 1);
267
+ // Same threshold as periodic check: 70% size, <15% access
268
+ if (sizeRatio > 0.7 && accessRatio < 0.15) {
269
+ prodLog.debug(`Proactive fairness: ${addedType} reaching dominance (${(sizeRatio * 100).toFixed(1)}% size, ${(accessRatio * 100).toFixed(1)}% access)`);
270
+ this.evictType(addedType);
271
+ }
272
+ }
246
273
  /**
247
274
  * Force evict items of a specific type
248
275
  */
@@ -256,8 +283,8 @@ export class UnifiedCache {
256
283
  }
257
284
  // Sort by score (lower is worse)
258
285
  candidates.sort((a, b) => a[1] - b[1]);
259
- // Evict bottom 20% of this type
260
- const evictCount = Math.max(1, Math.floor(candidates.length * 0.2));
286
+ // Evict bottom 50% of this type (v3.40.2: was 20%, too slow to prevent thrashing)
287
+ const evictCount = Math.max(1, Math.floor(candidates.length * 0.5));
261
288
  for (let i = 0; i < evictCount && i < candidates.length; i++) {
262
289
  const [key, , item] = candidates[i];
263
290
  this.currentSize -= item.size;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "3.40.1",
3
+ "version": "3.40.3",
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",