@soulcraft/brainy 4.8.0 → 4.8.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.
@@ -1135,11 +1135,9 @@ export class FileSystemStorage extends BaseStorage {
1135
1135
  const edge = JSON.parse(data);
1136
1136
  // Get metadata which contains the actual verb information
1137
1137
  const metadata = await this.getVerbMetadata(id);
1138
- // v4.0.0: No fallbacks - skip verbs without metadata
1139
- if (!metadata) {
1140
- console.warn(`Verb ${id} has no metadata, skipping`);
1141
- continue;
1142
- }
1138
+ // v4.8.1: Don't skip verbs without metadata - metadata is optional
1139
+ // FIX: This was the root cause of the VFS bug (11 versions)
1140
+ // Verbs can exist without metadata files (e.g., from imports/migrations)
1143
1141
  // Convert connections Map to proper format if needed
1144
1142
  let connections = edge.connections;
1145
1143
  if (connections && typeof connections === 'object' && !(connections instanceof Map)) {
@@ -1150,7 +1148,7 @@ export class FileSystemStorage extends BaseStorage {
1150
1148
  connections = connectionsMap;
1151
1149
  }
1152
1150
  // v4.8.0: Extract standard fields from metadata to top-level
1153
- const metadataObj = metadata;
1151
+ const metadataObj = (metadata || {});
1154
1152
  const { createdAt, updatedAt, confidence, weight, service, data: dataField, createdBy, ...customMetadata } = metadataObj;
1155
1153
  const verbWithMetadata = {
1156
1154
  id: edge.id,
@@ -2025,11 +2023,9 @@ export class FileSystemStorage extends BaseStorage {
2025
2023
  const data = await fs.promises.readFile(filePath, 'utf-8');
2026
2024
  const edge = JSON.parse(data);
2027
2025
  const metadata = await this.getVerbMetadata(id);
2028
- // v4.0.0: No fallbacks - skip verbs without metadata
2029
- if (!metadata) {
2030
- processedCount++;
2031
- return true; // continue, skip this verb
2032
- }
2026
+ // v4.8.1: Don't skip verbs without metadata - metadata is optional
2027
+ // FIX: This was the root cause of the VFS bug (11 versions)
2028
+ // Verbs can exist without metadata files (e.g., from imports/migrations)
2033
2029
  // Convert connections if needed
2034
2030
  let connections = edge.connections;
2035
2031
  if (connections && typeof connections === 'object' && !(connections instanceof Map)) {
@@ -2040,7 +2036,7 @@ export class FileSystemStorage extends BaseStorage {
2040
2036
  connections = connectionsMap;
2041
2037
  }
2042
2038
  // v4.8.0: Extract standard fields from metadata to top-level
2043
- const metadataObj = metadata;
2039
+ const metadataObj = (metadata || {});
2044
2040
  const { createdAt, updatedAt, confidence, weight, service, data: dataField, createdBy, ...customMetadata } = metadataObj;
2045
2041
  const verbWithMetadata = {
2046
2042
  id: edge.id,
@@ -335,125 +335,27 @@ export class TypeAwareStorageAdapter extends BaseStorage {
335
335
  * Get verbs by source
336
336
  */
337
337
  async getVerbsBySource_internal(sourceId) {
338
- // Need to search across all verb types
339
- // TODO: Optimize with metadata index in Phase 1b
340
- const verbs = [];
341
- for (let i = 0; i < VERB_TYPE_COUNT; i++) {
342
- const type = TypeUtils.getVerbFromIndex(i);
343
- const prefix = `entities/verbs/${type}/vectors/`;
344
- const paths = await this.u.listObjectsUnderPath(prefix);
345
- for (const path of paths) {
346
- try {
347
- const id = path.split('/').pop()?.replace('.json', '');
348
- if (!id)
349
- continue;
350
- // Load the HNSWVerb
351
- const hnswVerb = await this.u.readObjectFromPath(path);
352
- if (!hnswVerb)
353
- continue;
354
- // Check sourceId from HNSWVerb (v4.0.0: core fields are in HNSWVerb)
355
- if (hnswVerb.sourceId !== sourceId)
356
- continue;
357
- // Load metadata separately (optional in v4.0.0!)
358
- // FIX: Don't skip verbs without metadata - metadata is optional!
359
- // VFS relationships often have NO metadata (just verb/source/target)
360
- const metadata = await this.getVerbMetadata(id);
361
- // Create HNSWVerbWithMetadata (verbs don't have level field)
362
- // Convert connections from plain object to Map<number, Set<string>>
363
- const connectionsMap = new Map();
364
- if (hnswVerb.connections && typeof hnswVerb.connections === 'object') {
365
- for (const [level, ids] of Object.entries(hnswVerb.connections)) {
366
- connectionsMap.set(Number(level), new Set(ids));
367
- }
368
- }
369
- // v4.8.0: Extract standard fields from metadata to top-level
370
- const metadataObj = (metadata || {});
371
- const { createdAt, updatedAt, confidence, weight, service, data, createdBy, ...customMetadata } = metadataObj;
372
- const verbWithMetadata = {
373
- id: hnswVerb.id,
374
- vector: [...hnswVerb.vector],
375
- connections: connectionsMap,
376
- verb: hnswVerb.verb,
377
- sourceId: hnswVerb.sourceId,
378
- targetId: hnswVerb.targetId,
379
- createdAt: createdAt || Date.now(),
380
- updatedAt: updatedAt || Date.now(),
381
- confidence: confidence,
382
- weight: weight,
383
- service: service,
384
- data: data,
385
- createdBy,
386
- metadata: customMetadata
387
- };
388
- verbs.push(verbWithMetadata);
389
- }
390
- catch (error) {
391
- // Continue searching
392
- }
393
- }
394
- }
395
- return verbs;
338
+ // v4.8.1 PERFORMANCE FIX: Delegate to underlying storage instead of scanning all files
339
+ // Previous implementation was O(total_verbs) - scanned ALL 40 verb types and ALL verb files
340
+ // This was the root cause of the 11-version VFS bug (timeouts/zero results)
341
+ //
342
+ // Underlying storage adapters have optimized implementations:
343
+ // - FileSystemStorage: Uses getVerbsWithPagination with sourceId filter
344
+ // - GcsStorage: Uses batch queries with prefix filtering
345
+ // - S3Storage: Uses listObjects with sourceId-based filtering
346
+ //
347
+ // Phase 1b TODO: Add graph adjacency index query for O(1) lookups:
348
+ // const verbIds = await this.graphIndex?.getOutgoingEdges(sourceId) || []
349
+ // return Promise.all(verbIds.map(id => this.getVerb(id)))
350
+ return this.underlying.getVerbsBySource(sourceId);
396
351
  }
397
352
  /**
398
353
  * Get verbs by target
399
354
  */
400
355
  async getVerbsByTarget_internal(targetId) {
401
- // Similar to getVerbsBySource_internal
402
- const verbs = [];
403
- for (let i = 0; i < VERB_TYPE_COUNT; i++) {
404
- const type = TypeUtils.getVerbFromIndex(i);
405
- const prefix = `entities/verbs/${type}/vectors/`;
406
- const paths = await this.u.listObjectsUnderPath(prefix);
407
- for (const path of paths) {
408
- try {
409
- const id = path.split('/').pop()?.replace('.json', '');
410
- if (!id)
411
- continue;
412
- // Load the HNSWVerb
413
- const hnswVerb = await this.u.readObjectFromPath(path);
414
- if (!hnswVerb)
415
- continue;
416
- // Check targetId from HNSWVerb (v4.0.0: core fields are in HNSWVerb)
417
- if (hnswVerb.targetId !== targetId)
418
- continue;
419
- // Load metadata separately (optional in v4.0.0!)
420
- // FIX: Don't skip verbs without metadata - metadata is optional!
421
- const metadata = await this.getVerbMetadata(id);
422
- // Create HNSWVerbWithMetadata (verbs don't have level field)
423
- // Convert connections from plain object to Map<number, Set<string>>
424
- const connectionsMap = new Map();
425
- if (hnswVerb.connections && typeof hnswVerb.connections === 'object') {
426
- for (const [level, ids] of Object.entries(hnswVerb.connections)) {
427
- connectionsMap.set(Number(level), new Set(ids));
428
- }
429
- }
430
- // v4.8.0: Extract standard fields from metadata to top-level
431
- const metadataObj = (metadata || {});
432
- const { createdAt, updatedAt, confidence, weight, service, data, createdBy, ...customMetadata } = metadataObj;
433
- const verbWithMetadata = {
434
- id: hnswVerb.id,
435
- vector: [...hnswVerb.vector],
436
- connections: connectionsMap,
437
- verb: hnswVerb.verb,
438
- sourceId: hnswVerb.sourceId,
439
- targetId: hnswVerb.targetId,
440
- createdAt: createdAt || Date.now(),
441
- updatedAt: updatedAt || Date.now(),
442
- confidence: confidence,
443
- weight: weight,
444
- service: service,
445
- data: data,
446
- createdBy,
447
- metadata: customMetadata
448
- };
449
- verbs.push(verbWithMetadata);
450
- }
451
- catch (error) {
452
- // Continue
453
- }
454
- }
455
- }
456
- return verbs;
356
+ // v4.8.1 PERFORMANCE FIX: Delegate to underlying storage (same as getVerbsBySource fix)
357
+ // Previous implementation was O(total_verbs) - scanned ALL 40 verb types and ALL verb files
358
+ return this.underlying.getVerbsByTarget(targetId);
457
359
  }
458
360
  /**
459
361
  * Get verbs by type (O(1) with type-first paths!)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "4.8.0",
3
+ "version": "4.8.1",
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",