@soulcraft/brainy 5.12.0 → 6.0.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.
@@ -165,7 +165,8 @@ export class GcsStorage extends BaseStorage {
165
165
  this.nounCacheManager.clear();
166
166
  this.verbCacheManager.clear();
167
167
  prodLog.info('✅ Cache cleared - starting fresh');
168
- this.isInitialized = true;
168
+ // v6.0.0: Initialize GraphAdjacencyIndex and type statistics
169
+ await super.init();
169
170
  }
170
171
  catch (error) {
171
172
  this.logger.error('Failed to initialize GCS storage:', error);
@@ -107,8 +107,8 @@ export class HistoricalStorageAdapter extends BaseStorage {
107
107
  if (!commit) {
108
108
  throw new Error(`Commit not found: ${this.commitId}`);
109
109
  }
110
- // Mark as initialized
111
- this.isInitialized = true;
110
+ // v6.0.0: Initialize GraphAdjacencyIndex and type statistics
111
+ await super.init();
112
112
  }
113
113
  // ============= Abstract Method Implementations =============
114
114
  /**
@@ -30,7 +30,7 @@ export declare class MemoryStorage extends BaseStorage {
30
30
  getBatchConfig(): StorageBatchConfig;
31
31
  /**
32
32
  * Initialize the storage adapter
33
- * Nothing to initialize for in-memory storage
33
+ * v6.0.0: Calls super.init() to initialize GraphAdjacencyIndex and type statistics
34
34
  */
35
35
  init(): Promise<void>;
36
36
  /**
@@ -55,10 +55,10 @@ export class MemoryStorage extends BaseStorage {
55
55
  }
56
56
  /**
57
57
  * Initialize the storage adapter
58
- * Nothing to initialize for in-memory storage
58
+ * v6.0.0: Calls super.init() to initialize GraphAdjacencyIndex and type statistics
59
59
  */
60
60
  async init() {
61
- this.isInitialized = true;
61
+ await super.init();
62
62
  }
63
63
  // v5.4.0: Removed saveNoun_internal and getNoun_internal - using BaseStorage's type-first implementation
64
64
  /**
@@ -248,25 +248,23 @@ export class MemoryStorage extends BaseStorage {
248
248
  * Initialize counts from in-memory storage - O(1) operation (v4.0.0)
249
249
  */
250
250
  async initializeCounts() {
251
- // v5.4.0: Scan objectStore paths (type-first structure) to count entities
251
+ // v6.0.0: Scan objectStore paths (ID-first structure) to count entities
252
252
  this.entityCounts.clear();
253
253
  this.verbCounts.clear();
254
254
  let totalNouns = 0;
255
255
  let totalVerbs = 0;
256
256
  // Scan all paths in objectStore
257
257
  for (const path of this.objectStore.keys()) {
258
- // Count nouns by type (entities/nouns/{type}/vectors/{shard}/{id}.json)
259
- const nounMatch = path.match(/^entities\/nouns\/([^/]+)\/vectors\//);
258
+ // Count nouns (entities/nouns/{shard}/{id}/vectors.json)
259
+ const nounMatch = path.match(/^entities\/nouns\/[0-9a-f]{2}\/[^/]+\/vectors\.json$/);
260
260
  if (nounMatch) {
261
- const type = nounMatch[1];
262
- this.entityCounts.set(type, (this.entityCounts.get(type) || 0) + 1);
261
+ // v6.0.0: Type is in metadata, not path - just count total
263
262
  totalNouns++;
264
263
  }
265
- // Count verbs by type (entities/verbs/{type}/vectors/{shard}/{id}.json)
266
- const verbMatch = path.match(/^entities\/verbs\/([^/]+)\/vectors\//);
264
+ // Count verbs (entities/verbs/{shard}/{id}/vectors.json)
265
+ const verbMatch = path.match(/^entities\/verbs\/[0-9a-f]{2}\/[^/]+\/vectors\.json$/);
267
266
  if (verbMatch) {
268
- const type = verbMatch[1];
269
- this.verbCounts.set(type, (this.verbCounts.get(type) || 0) + 1);
267
+ // v6.0.0: Type is in metadata, not path - just count total
270
268
  totalVerbs++;
271
269
  }
272
270
  }
@@ -131,7 +131,8 @@ export class OPFSStorage extends BaseStorage {
131
131
  });
132
132
  // Initialize counts from storage
133
133
  await this.initializeCounts();
134
- this.isInitialized = true;
134
+ // v6.0.0: Initialize GraphAdjacencyIndex and type statistics
135
+ await super.init();
135
136
  }
136
137
  catch (error) {
137
138
  console.error('Failed to initialize OPFS storage:', error);
@@ -232,7 +232,8 @@ export class R2Storage extends BaseStorage {
232
232
  prodLog.info('🧹 R2: Clearing cache from previous run');
233
233
  this.nounCacheManager.clear();
234
234
  this.verbCacheManager.clear();
235
- this.isInitialized = true;
235
+ // v6.0.0: Initialize GraphAdjacencyIndex and type statistics
236
+ await super.init();
236
237
  }
237
238
  catch (error) {
238
239
  this.logger.error('Failed to initialize R2 storage:', error);
@@ -345,7 +345,8 @@ export class S3CompatibleStorage extends BaseStorage {
345
345
  else {
346
346
  prodLog.info('🧹 Node cache is empty - starting fresh');
347
347
  }
348
- this.isInitialized = true;
348
+ // v6.0.0: Initialize GraphAdjacencyIndex and type statistics
349
+ await super.init();
349
350
  this.logger.info(`Initialized ${this.serviceType} storage with bucket ${this.bucketName}`);
350
351
  }
351
352
  catch (error) {
@@ -60,8 +60,6 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
60
60
  currentBranch: string;
61
61
  protected nounCountsByType: Uint32Array<ArrayBuffer>;
62
62
  protected verbCountsByType: Uint32Array<ArrayBuffer>;
63
- protected nounTypeCache: Map<string, NounType>;
64
- protected verbTypeCache: Map<string, VerbType>;
65
63
  private typeCountsRebuilt;
66
64
  /**
67
65
  * Analyze a storage key to determine its routing and path
@@ -78,6 +76,12 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
78
76
  * IMPORTANT: If your adapter overrides init(), call await super.init() first!
79
77
  */
80
78
  init(): Promise<void>;
79
+ /**
80
+ * Rebuild GraphAdjacencyIndex from existing verbs (v6.0.0)
81
+ * Call this manually if you have existing verb data that needs to be indexed
82
+ * @public
83
+ */
84
+ rebuildGraphIndex(): Promise<void>;
81
85
  /**
82
86
  * Ensure the storage adapter is initialized
83
87
  */
@@ -406,6 +410,17 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
406
410
  /**
407
411
  * Get noun metadata from storage (METADATA-ONLY, NO VECTORS)
408
412
  *
413
+ * **Performance (v6.0.0)**: Direct O(1) ID-first lookup - NO type search needed!
414
+ * - **All lookups**: 1 read, ~500ms on cloud (consistent performance)
415
+ * - **No cache needed**: Type is in the metadata, not the path
416
+ * - **No type search**: ID-first paths eliminate 42-type search entirely
417
+ *
418
+ * **Clean architecture (v6.0.0)**:
419
+ * - Path: `entities/nouns/{SHARD}/{ID}/metadata.json`
420
+ * - Type is just a field in metadata (`noun: "document"`)
421
+ * - MetadataIndex handles type queries (no path scanning needed)
422
+ * - Scales to billions without any overhead
423
+ *
409
424
  * **Performance (v5.11.1)**: Fast path for metadata-only reads
410
425
  * - **Speed**: 10ms vs 43ms (76-81% faster than getNoun)
411
426
  * - **Bandwidth**: 300 bytes vs 6KB (95% less)
@@ -435,13 +450,15 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
435
450
  * @returns Metadata or null if not found
436
451
  *
437
452
  * @performance
438
- * - Type cache O(1) lookup for cached entities
439
- * - Type scan O(N_types) for cache misses (typically <100ms)
440
- * - Uses readWithInheritance() for COW branch support
453
+ * - O(1) direct ID lookup - always 1 read (~500ms on cloud, ~10ms local)
454
+ * - No caching complexity
455
+ * - No type search fallbacks
456
+ * - Works in distributed systems without sync issues
441
457
  *
442
458
  * @since v4.0.0
443
- * @since v5.4.0 - Type-first paths
459
+ * @since v5.4.0 - Type-first paths (removed in v6.0.0)
444
460
  * @since v5.11.1 - Promoted to fast path for brain.get() optimization
461
+ * @since v6.0.0 - CLEAN FIX: ID-first paths eliminate all type-search complexity
445
462
  */
446
463
  getNounMetadata(id: string): Promise<NounMetadata | null>;
447
464
  /**
@@ -525,8 +542,7 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
525
542
  */
526
543
  getBatchConfig(): StorageBatchConfig;
527
544
  /**
528
- * Delete noun metadata from storage
529
- * v5.4.0: Uses type-first paths (must match saveNounMetadata_internal)
545
+ * Delete noun metadata from storage (v6.0.0: ID-first, O(1) delete)
530
546
  */
531
547
  deleteNounMetadata(id: string): Promise<void>;
532
548
  /**
@@ -536,7 +552,7 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
536
552
  saveVerbMetadata(id: string, metadata: VerbMetadata): Promise<void>;
537
553
  /**
538
554
  * Internal method for saving verb metadata (v4.0.0: now typed)
539
- * v5.4.0: Uses type-first paths (must match getVerbMetadata)
555
+ * v5.4.0: Uses ID-first paths (must match getVerbMetadata)
540
556
  *
541
557
  * CRITICAL (v4.1.2): Count synchronization happens here
542
558
  * This ensures verb counts are updated AFTER metadata exists, fixing the race condition
@@ -549,12 +565,11 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
549
565
  protected saveVerbMetadata_internal(id: string, metadata: VerbMetadata): Promise<void>;
550
566
  /**
551
567
  * Get verb metadata from storage (v4.0.0: now typed)
552
- * v5.4.0: Uses type-first paths (must match saveVerbMetadata_internal)
568
+ * v5.4.0: Uses ID-first paths (must match saveVerbMetadata_internal)
553
569
  */
554
570
  getVerbMetadata(id: string): Promise<VerbMetadata | null>;
555
571
  /**
556
- * Delete verb metadata from storage
557
- * v5.4.0: Uses type-first paths (must match saveVerbMetadata_internal)
572
+ * Delete verb metadata from storage (v6.0.0: ID-first, O(1) delete)
558
573
  */
559
574
  deleteVerbMetadata(id: string): Promise<void>;
560
575
  /**
@@ -574,8 +589,9 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
574
589
  */
575
590
  protected rebuildTypeCounts(): Promise<void>;
576
591
  /**
577
- * Get noun type from cache or metadata
578
- * Relies on nounTypeCache populated during metadata saves
592
+ * Get noun type (v6.0.0: type no longer needed for paths!)
593
+ * With ID-first paths, this is only used for internal statistics tracking.
594
+ * The actual type is stored in metadata and indexed by MetadataIndexManager.
579
595
  */
580
596
  protected getNounType(noun: HNSWNoun): NounType;
581
597
  /**
@@ -608,32 +624,32 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
608
624
  */
609
625
  protected deserializeVerb(data: any): HNSWVerb;
610
626
  /**
611
- * Save a noun to storage (type-first path)
627
+ * Save a noun to storage (ID-first path)
612
628
  */
613
629
  protected saveNoun_internal(noun: HNSWNoun): Promise<void>;
614
630
  /**
615
- * Get a noun from storage (type-first path)
631
+ * Get a noun from storage (ID-first path)
616
632
  */
617
633
  protected getNoun_internal(id: string): Promise<HNSWNoun | null>;
618
634
  /**
619
- * Get nouns by noun type (O(1) with type-first paths!)
635
+ * Get nouns by noun type (v6.0.0: Shard-based iteration!)
620
636
  */
621
637
  protected getNounsByNounType_internal(nounType: string): Promise<HNSWNoun[]>;
622
638
  /**
623
- * Delete a noun from storage (type-first path)
639
+ * Delete a noun from storage (v6.0.0: ID-first, O(1) delete)
624
640
  */
625
641
  protected deleteNoun_internal(id: string): Promise<void>;
626
642
  /**
627
- * Save a verb to storage (type-first path)
643
+ * Save a verb to storage (ID-first path)
628
644
  */
629
645
  protected saveVerb_internal(verb: HNSWVerb): Promise<void>;
630
646
  /**
631
- * Get a verb from storage (type-first path)
647
+ * Get a verb from storage (ID-first path)
632
648
  */
633
649
  protected getVerb_internal(id: string): Promise<HNSWVerb | null>;
634
650
  /**
635
- * Get verbs by source (COW-aware implementation)
636
- * v5.4.0: Fixed to directly list verb files instead of directories
651
+ * Get verbs by source (v6.0.0: Uses GraphAdjacencyIndex when available)
652
+ * Falls back to shard iteration during initialization to avoid circular dependency
637
653
  */
638
654
  protected getVerbsBySource_internal(sourceId: string): Promise<HNSWVerbWithMetadata[]>;
639
655
  /**
@@ -676,11 +692,11 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
676
692
  */
677
693
  protected getVerbsByTarget_internal(targetId: string): Promise<HNSWVerbWithMetadata[]>;
678
694
  /**
679
- * Get verbs by type (O(1) with type-first paths!)
695
+ * Get verbs by type (v6.0.0: Shard iteration with type filtering)
680
696
  */
681
697
  protected getVerbsByType_internal(verbType: string): Promise<HNSWVerbWithMetadata[]>;
682
698
  /**
683
- * Delete a verb from storage (type-first path)
699
+ * Delete a verb from storage (v6.0.0: ID-first, O(1) delete)
684
700
  */
685
701
  protected deleteVerb_internal(id: string): Promise<void>;
686
702
  /**