@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.
|
|
1139
|
-
|
|
1140
|
-
|
|
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.
|
|
2029
|
-
|
|
2030
|
-
|
|
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
|
-
//
|
|
339
|
-
//
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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
|
-
//
|
|
402
|
-
|
|
403
|
-
|
|
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.
|
|
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",
|