@soulcraft/brainy 6.2.0 → 6.2.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.
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Knowledge Layer Augmentation for VFS
3
+ *
4
+ * Adds intelligent features to VFS without modifying core functionality:
5
+ * - Event recording for all operations
6
+ * - Semantic versioning based on content changes
7
+ * - Entity and concept extraction
8
+ * - Git bridge for import/export
9
+ *
10
+ * This is a TRUE augmentation - VFS works perfectly without it
11
+ */
12
+ import { Brainy } from '../brainy.js';
13
+ import { BaseAugmentation } from './brainyAugmentation.js';
14
+ export declare class KnowledgeAugmentation extends BaseAugmentation {
15
+ name: string;
16
+ timing: 'after';
17
+ metadata: 'none';
18
+ operations: any;
19
+ priority: number;
20
+ constructor(config?: any);
21
+ execute<T = any>(operation: string, params: any, next: () => Promise<T>): Promise<T>;
22
+ private eventRecorder?;
23
+ private semanticVersioning?;
24
+ private entitySystem?;
25
+ private conceptSystem?;
26
+ private gitBridge?;
27
+ private originalMethods;
28
+ initialize(context: any): Promise<void>;
29
+ augment(brain: Brainy): Promise<void>;
30
+ /**
31
+ * Wrap a VFS method to add Knowledge Layer functionality
32
+ */
33
+ private wrapMethod;
34
+ /**
35
+ * Add Knowledge Layer methods to VFS
36
+ */
37
+ private addKnowledgeMethods;
38
+ private isSemanticChange;
39
+ cleanup(brain: Brainy): Promise<void>;
40
+ }
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Knowledge Layer Augmentation for VFS
3
+ *
4
+ * Adds intelligent features to VFS without modifying core functionality:
5
+ * - Event recording for all operations
6
+ * - Semantic versioning based on content changes
7
+ * - Entity and concept extraction
8
+ * - Git bridge for import/export
9
+ *
10
+ * This is a TRUE augmentation - VFS works perfectly without it
11
+ */
12
+ import { BaseAugmentation } from './brainyAugmentation.js';
13
+ import { EventRecorder } from '../vfs/EventRecorder.js';
14
+ import { SemanticVersioning } from '../vfs/SemanticVersioning.js';
15
+ import { PersistentEntitySystem } from '../vfs/PersistentEntitySystem.js';
16
+ import { ConceptSystem } from '../vfs/ConceptSystem.js';
17
+ import { GitBridge } from '../vfs/GitBridge.js';
18
+ export class KnowledgeAugmentation extends BaseAugmentation {
19
+ constructor(config = {}) {
20
+ super(config);
21
+ this.name = 'knowledge';
22
+ this.timing = 'after'; // Process after VFS operations
23
+ this.metadata = 'none'; // No metadata access needed
24
+ this.operations = []; // VFS-specific augmentation, no operation interception
25
+ this.priority = 100; // Run last
26
+ this.originalMethods = new Map();
27
+ }
28
+ async execute(operation, params, next) {
29
+ // Pass through - this augmentation works at VFS level, not operation level
30
+ return await next();
31
+ }
32
+ async initialize(context) {
33
+ await this.augment(context.brain);
34
+ }
35
+ async augment(brain) {
36
+ // Only augment if VFS exists
37
+ const vfs = brain.vfs?.();
38
+ if (!vfs) {
39
+ console.warn('KnowledgeAugmentation: VFS not found, skipping');
40
+ return;
41
+ }
42
+ // Initialize Knowledge Layer components
43
+ this.eventRecorder = new EventRecorder(brain);
44
+ this.semanticVersioning = new SemanticVersioning(brain);
45
+ this.entitySystem = new PersistentEntitySystem(brain);
46
+ this.conceptSystem = new ConceptSystem(brain);
47
+ this.gitBridge = new GitBridge(vfs, brain);
48
+ // Wrap VFS methods to add intelligence WITHOUT slowing them down
49
+ this.wrapMethod(vfs, 'writeFile', async (original, path, data, options) => {
50
+ // Call original first (stays fast)
51
+ const result = await original.call(vfs, path, data, options);
52
+ // Knowledge processing in background (non-blocking)
53
+ setImmediate(async () => {
54
+ try {
55
+ // Record event
56
+ if (this.eventRecorder) {
57
+ await this.eventRecorder.recordEvent({
58
+ type: 'write',
59
+ path,
60
+ content: data,
61
+ size: data.length,
62
+ author: options?.author || 'system'
63
+ });
64
+ }
65
+ // Check for semantic versioning
66
+ if (this.semanticVersioning) {
67
+ const existingContent = await vfs.readFile(path).catch(() => null);
68
+ const shouldVersion = existingContent && this.isSemanticChange(existingContent, data);
69
+ if (shouldVersion) {
70
+ await this.semanticVersioning.createVersion(path, data, {
71
+ message: 'Automatic semantic version'
72
+ });
73
+ }
74
+ }
75
+ // Extract concepts
76
+ if (this.conceptSystem && options?.extractConcepts !== false) {
77
+ await this.conceptSystem.extractAndLinkConcepts(path, data);
78
+ }
79
+ // Extract entities
80
+ if (this.entitySystem && options?.extractEntities !== false) {
81
+ await this.entitySystem.extractEntities(data.toString('utf8'), data);
82
+ }
83
+ }
84
+ catch (error) {
85
+ // Knowledge Layer errors should not affect VFS operations
86
+ console.debug('KnowledgeLayer background processing error:', error);
87
+ }
88
+ });
89
+ return result;
90
+ });
91
+ this.wrapMethod(vfs, 'unlink', async (original, path) => {
92
+ const result = await original.call(vfs, path);
93
+ // Record deletion event
94
+ setImmediate(async () => {
95
+ if (this.eventRecorder) {
96
+ await this.eventRecorder.recordEvent({
97
+ type: 'delete',
98
+ path,
99
+ author: 'system'
100
+ });
101
+ }
102
+ });
103
+ return result;
104
+ });
105
+ this.wrapMethod(vfs, 'rename', async (original, oldPath, newPath) => {
106
+ const result = await original.call(vfs, oldPath, newPath);
107
+ // Record rename event
108
+ setImmediate(async () => {
109
+ if (this.eventRecorder) {
110
+ await this.eventRecorder.recordEvent({
111
+ type: 'rename',
112
+ path: oldPath,
113
+ metadata: { newPath },
114
+ author: 'system'
115
+ });
116
+ }
117
+ });
118
+ return result;
119
+ });
120
+ // Add Knowledge Layer methods to VFS
121
+ this.addKnowledgeMethods(vfs);
122
+ console.log('✨ Knowledge Layer augmentation enabled');
123
+ }
124
+ /**
125
+ * Wrap a VFS method to add Knowledge Layer functionality
126
+ */
127
+ wrapMethod(vfs, methodName, wrapper) {
128
+ const original = vfs[methodName];
129
+ if (!original)
130
+ return;
131
+ // Store original for cleanup
132
+ this.originalMethods.set(methodName, original);
133
+ // Replace with wrapped version
134
+ vfs[methodName] = async (...args) => {
135
+ return await wrapper(original, ...args);
136
+ };
137
+ }
138
+ /**
139
+ * Add Knowledge Layer methods to VFS
140
+ */
141
+ addKnowledgeMethods(vfs) {
142
+ // Event history
143
+ vfs.getHistory = async (path, options) => {
144
+ if (!this.eventRecorder)
145
+ throw new Error('Knowledge Layer not initialized');
146
+ return await this.eventRecorder.getHistory(path, options);
147
+ };
148
+ vfs.reconstructAtTime = async (path, timestamp) => {
149
+ if (!this.eventRecorder)
150
+ throw new Error('Knowledge Layer not initialized');
151
+ return await this.eventRecorder.reconstructFileAtTime(path, timestamp);
152
+ };
153
+ // Semantic versioning
154
+ vfs.getVersions = async (path) => {
155
+ if (!this.semanticVersioning)
156
+ throw new Error('Knowledge Layer not initialized');
157
+ return await this.semanticVersioning.getVersions(path);
158
+ };
159
+ vfs.restoreVersion = async (path, versionId) => {
160
+ if (!this.semanticVersioning)
161
+ throw new Error('Knowledge Layer not initialized');
162
+ const version = await this.semanticVersioning.getVersion(path, versionId);
163
+ if (version) {
164
+ await vfs.writeFile(path, version);
165
+ }
166
+ };
167
+ // Entities
168
+ vfs.findEntity = async (query) => {
169
+ if (!this.entitySystem)
170
+ throw new Error('Knowledge Layer not initialized');
171
+ return await this.entitySystem.findEntity(query);
172
+ };
173
+ vfs.getEntityAppearances = async (entityId) => {
174
+ if (!this.entitySystem)
175
+ throw new Error('Knowledge Layer not initialized');
176
+ return await this.entitySystem.getEvolution(entityId);
177
+ };
178
+ // Concepts
179
+ vfs.getConcepts = async (path) => {
180
+ if (!this.conceptSystem)
181
+ throw new Error('Knowledge Layer not initialized');
182
+ const concepts = await this.conceptSystem.findConcepts({ manifestedIn: path });
183
+ return concepts;
184
+ };
185
+ vfs.getConceptGraph = async (options) => {
186
+ if (!this.conceptSystem)
187
+ throw new Error('Knowledge Layer not initialized');
188
+ return await this.conceptSystem.getConceptGraph(options);
189
+ };
190
+ // Git bridge
191
+ vfs.exportToGit = async (vfsPath, gitPath) => {
192
+ if (!this.gitBridge)
193
+ throw new Error('Knowledge Layer not initialized');
194
+ return await this.gitBridge.exportToGit(vfsPath, gitPath);
195
+ };
196
+ vfs.importFromGit = async (gitPath, vfsPath) => {
197
+ if (!this.gitBridge)
198
+ throw new Error('Knowledge Layer not initialized');
199
+ return await this.gitBridge.importFromGit(gitPath, vfsPath);
200
+ };
201
+ // Temporal coupling
202
+ vfs.findTemporalCoupling = async (path, windowMs) => {
203
+ if (!this.eventRecorder)
204
+ throw new Error('Knowledge Layer not initialized');
205
+ return await this.eventRecorder.findTemporalCoupling(path, windowMs);
206
+ };
207
+ }
208
+ isSemanticChange(oldContent, newContent) {
209
+ // Simple heuristic - significant size change or different content
210
+ const oldStr = oldContent.toString('utf8');
211
+ const newStr = newContent.toString('utf8');
212
+ // Check for significant size change (>10%)
213
+ const sizeDiff = Math.abs(oldStr.length - newStr.length) / oldStr.length;
214
+ if (sizeDiff > 0.1)
215
+ return true;
216
+ // Check for structural changes (simplified)
217
+ const oldLines = oldStr.split('\n').filter(l => l.trim());
218
+ const newLines = newStr.split('\n').filter(l => l.trim());
219
+ // Different number of non-empty lines
220
+ return Math.abs(oldLines.length - newLines.length) > 5;
221
+ }
222
+ async cleanup(brain) {
223
+ const vfs = brain.vfs?.();
224
+ if (!vfs)
225
+ return;
226
+ // Restore original methods
227
+ for (const [methodName, original] of this.originalMethods) {
228
+ vfs[methodName] = original;
229
+ }
230
+ // Remove added methods
231
+ delete vfs.getHistory;
232
+ delete vfs.reconstructAtTime;
233
+ delete vfs.getVersions;
234
+ delete vfs.restoreVersion;
235
+ delete vfs.findEntity;
236
+ delete vfs.getEntityAppearances;
237
+ delete vfs.getConcepts;
238
+ delete vfs.getConceptGraph;
239
+ delete vfs.exportToGit;
240
+ delete vfs.importFromGit;
241
+ delete vfs.findTemporalCoupling;
242
+ // Clean up components
243
+ this.eventRecorder = undefined;
244
+ this.semanticVersioning = undefined;
245
+ this.entitySystem = undefined;
246
+ this.conceptSystem = undefined;
247
+ this.gitBridge = undefined;
248
+ console.log('Knowledge Layer augmentation removed');
249
+ }
250
+ }
251
+ //# sourceMappingURL=KnowledgeAugmentation.js.map
package/dist/brainy.d.ts CHANGED
@@ -1566,9 +1566,11 @@ export declare class Brainy<T = any> implements BrainyInterface<T> {
1566
1566
  get counts(): {
1567
1567
  entities: () => number;
1568
1568
  relationships: () => number;
1569
- byType: (type?: string) => number | {
1570
- [k: string]: number;
1571
- };
1569
+ byType: (typeOrOptions?: string | {
1570
+ excludeVFS?: boolean;
1571
+ }, options?: {
1572
+ excludeVFS?: boolean;
1573
+ }) => Promise<number | Record<string, number>>;
1572
1574
  byTypeEnum: (type: NounType) => number;
1573
1575
  topTypes: (n?: number) => NounType[];
1574
1576
  topVerbTypes: (n?: number) => VerbType[];
@@ -1579,12 +1581,12 @@ export declare class Brainy<T = any> implements BrainyInterface<T> {
1579
1581
  };
1580
1582
  byCriteria: (field: string, value: any) => Promise<number>;
1581
1583
  getAllTypeCounts: () => Map<string, number>;
1582
- getStats: () => {
1584
+ getStats: (options?: {
1585
+ excludeVFS?: boolean;
1586
+ }) => Promise<{
1583
1587
  entities: {
1584
1588
  total: number;
1585
- byType: {
1586
- [k: string]: number;
1587
- };
1589
+ byType: Record<string, number>;
1588
1590
  };
1589
1591
  relationships: {
1590
1592
  totalRelationships: number;
@@ -1594,7 +1596,7 @@ export declare class Brainy<T = any> implements BrainyInterface<T> {
1594
1596
  totalNodes: number;
1595
1597
  };
1596
1598
  density: number;
1597
- };
1599
+ }>;
1598
1600
  };
1599
1601
  /**
1600
1602
  * Augmentations API - Clean and simple
@@ -1607,14 +1609,16 @@ export declare class Brainy<T = any> implements BrainyInterface<T> {
1607
1609
  /**
1608
1610
  * Get complete statistics - convenience method
1609
1611
  * For more granular counting, use brain.counts API
1612
+ * v6.2.1: Added optional excludeVFS using Roaring bitmap intersection
1613
+ * @param options Optional settings - excludeVFS: filter out VFS entities
1610
1614
  * @returns Complete statistics including entities, relationships, and density
1611
1615
  */
1612
- getStats(): {
1616
+ getStats(options?: {
1617
+ excludeVFS?: boolean;
1618
+ }): Promise<{
1613
1619
  entities: {
1614
1620
  total: number;
1615
- byType: {
1616
- [k: string]: number;
1617
- };
1621
+ byType: Record<string, number>;
1618
1622
  };
1619
1623
  relationships: {
1620
1624
  totalRelationships: number;
@@ -1624,7 +1628,7 @@ export declare class Brainy<T = any> implements BrainyInterface<T> {
1624
1628
  totalNodes: number;
1625
1629
  };
1626
1630
  density: number;
1627
- };
1631
+ }>;
1628
1632
  /**
1629
1633
  * Parse natural language query using advanced NLP with 220+ patterns
1630
1634
  * The embedding model is always available as it's core to Brainy's functionality
package/dist/brainy.js CHANGED
@@ -768,7 +768,13 @@ export class Brainy {
768
768
  }
769
769
  }
770
770
  // Operation 5-6: Update metadata index (remove old, add new)
771
- tx.addOperation(new RemoveFromMetadataIndexOperation(this.metadataIndex, params.id, existing.metadata));
771
+ // v6.2.1: Fix - Include type in removal metadata so noun index is properly updated
772
+ // existing.metadata only contains custom fields, not 'type' which maps to 'noun'
773
+ const removalMetadata = {
774
+ ...existing.metadata,
775
+ type: existing.type // Include type so it maps to 'noun' during removal
776
+ };
777
+ tx.addOperation(new RemoveFromMetadataIndexOperation(this.metadataIndex, params.id, removalMetadata));
772
778
  tx.addOperation(new AddToMetadataIndexOperation(this.metadataIndex, params.id, entityForIndexing));
773
779
  });
774
780
  });
@@ -3405,7 +3411,39 @@ export class Brainy {
3405
3411
  // O(1) total relationship count
3406
3412
  relationships: () => this.graphIndex.getTotalRelationshipCount(),
3407
3413
  // O(1) count by type (string-based, backward compatible)
3408
- byType: (type) => {
3414
+ // v6.2.1: Added optional excludeVFS using Roaring bitmap intersection
3415
+ byType: async (typeOrOptions, options) => {
3416
+ // Handle overloaded signature: byType(type), byType({ excludeVFS }), byType(type, { excludeVFS })
3417
+ let type;
3418
+ let excludeVFS = false;
3419
+ if (typeof typeOrOptions === 'string') {
3420
+ type = typeOrOptions;
3421
+ excludeVFS = options?.excludeVFS ?? false;
3422
+ }
3423
+ else if (typeOrOptions && typeof typeOrOptions === 'object') {
3424
+ excludeVFS = typeOrOptions.excludeVFS ?? false;
3425
+ }
3426
+ if (excludeVFS) {
3427
+ const allCounts = this.metadataIndex.getAllEntityCounts();
3428
+ // Uses Roaring bitmap intersection - hardware accelerated
3429
+ const vfsCounts = await this.metadataIndex.getAllVFSEntityCounts();
3430
+ if (type) {
3431
+ const total = allCounts.get(type) || 0;
3432
+ const vfs = vfsCounts.get(type) || 0;
3433
+ return total - vfs;
3434
+ }
3435
+ // Return all counts with VFS subtracted
3436
+ const result = {};
3437
+ for (const [t, total] of allCounts) {
3438
+ const vfs = vfsCounts.get(t) || 0;
3439
+ const nonVfs = total - vfs;
3440
+ if (nonVfs > 0) {
3441
+ result[t] = nonVfs;
3442
+ }
3443
+ }
3444
+ return result;
3445
+ }
3446
+ // Default path (unchanged) - synchronous for backward compatibility
3409
3447
  if (type) {
3410
3448
  return this.metadataIndex.getEntityCountByType(type);
3411
3449
  }
@@ -3447,7 +3485,32 @@ export class Brainy {
3447
3485
  // Get all type counts as Map for performance-critical operations
3448
3486
  getAllTypeCounts: () => this.metadataIndex.getAllEntityCounts(),
3449
3487
  // Get complete statistics
3450
- getStats: () => {
3488
+ // v6.2.1: Added optional excludeVFS using Roaring bitmap intersection
3489
+ getStats: async (options) => {
3490
+ if (options?.excludeVFS) {
3491
+ const allCounts = this.metadataIndex.getAllEntityCounts();
3492
+ // Uses Roaring bitmap intersection - hardware accelerated
3493
+ const vfsCounts = await this.metadataIndex.getAllVFSEntityCounts();
3494
+ // Compute non-VFS counts via subtraction
3495
+ const byType = {};
3496
+ let total = 0;
3497
+ for (const [type, count] of allCounts) {
3498
+ const vfs = vfsCounts.get(type) || 0;
3499
+ const nonVfs = count - vfs;
3500
+ if (nonVfs > 0) {
3501
+ byType[type] = nonVfs;
3502
+ total += nonVfs;
3503
+ }
3504
+ }
3505
+ const entityStats = { total, byType };
3506
+ const relationshipStats = this.graphIndex.getRelationshipStats();
3507
+ return {
3508
+ entities: entityStats,
3509
+ relationships: relationshipStats,
3510
+ density: total > 0 ? relationshipStats.totalRelationships / total : 0
3511
+ };
3512
+ }
3513
+ // Default path (unchanged) - synchronous for backward compatibility
3451
3514
  const entityStats = {
3452
3515
  total: this.metadataIndex.getTotalEntityCount(),
3453
3516
  byType: Object.fromEntries(this.metadataIndex.getAllEntityCounts())
@@ -3474,10 +3537,12 @@ export class Brainy {
3474
3537
  /**
3475
3538
  * Get complete statistics - convenience method
3476
3539
  * For more granular counting, use brain.counts API
3540
+ * v6.2.1: Added optional excludeVFS using Roaring bitmap intersection
3541
+ * @param options Optional settings - excludeVFS: filter out VFS entities
3477
3542
  * @returns Complete statistics including entities, relationships, and density
3478
3543
  */
3479
- getStats() {
3480
- return this.counts.getStats();
3544
+ async getStats(options) {
3545
+ return this.counts.getStats(options);
3481
3546
  }
3482
3547
  // ============= HELPER METHODS =============
3483
3548
  /**
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Import Manager - Comprehensive data import with intelligent type detection
3
+ *
4
+ * Handles multiple data sources:
5
+ * - Direct data (objects, arrays)
6
+ * - Files (JSON, CSV, text)
7
+ * - URLs (fetch and parse)
8
+ * - Streams (for large files)
9
+ *
10
+ * Uses NeuralImportAugmentation for intelligent processing
11
+ */
12
+ import { NounType } from './types/graphTypes.js';
13
+ export interface ImportOptions {
14
+ source?: 'data' | 'file' | 'url' | 'auto';
15
+ format?: 'json' | 'csv' | 'text' | 'yaml' | 'auto';
16
+ batchSize?: number;
17
+ autoDetect?: boolean;
18
+ typeHint?: NounType;
19
+ extractRelationships?: boolean;
20
+ csvDelimiter?: string;
21
+ csvHeaders?: boolean;
22
+ parallel?: boolean;
23
+ maxConcurrency?: number;
24
+ }
25
+ export interface ImportResult {
26
+ success: boolean;
27
+ nouns: string[];
28
+ verbs: string[];
29
+ errors: string[];
30
+ stats: {
31
+ total: number;
32
+ imported: number;
33
+ failed: number;
34
+ relationships: number;
35
+ };
36
+ }
37
+ export declare class ImportManager {
38
+ private neuralImport;
39
+ private typeMatcher;
40
+ private brain;
41
+ constructor(brain: any);
42
+ /**
43
+ * Initialize the import manager
44
+ */
45
+ init(): Promise<void>;
46
+ /**
47
+ * Main import method - handles all sources
48
+ */
49
+ import(source: string | Buffer | any[] | any, options?: ImportOptions): Promise<ImportResult>;
50
+ /**
51
+ * Import from file
52
+ */
53
+ importFile(filePath: string, options?: ImportOptions): Promise<ImportResult>;
54
+ /**
55
+ * Import from URL
56
+ */
57
+ importUrl(url: string, options?: ImportOptions): Promise<ImportResult>;
58
+ /**
59
+ * Detect source type
60
+ */
61
+ private detectSourceType;
62
+ /**
63
+ * Detect format from file path
64
+ */
65
+ private detectFormatFromPath;
66
+ /**
67
+ * Read file
68
+ */
69
+ private readFile;
70
+ /**
71
+ * Fetch from URL
72
+ */
73
+ private fetchFromUrl;
74
+ }
75
+ /**
76
+ * Create an import manager instance
77
+ */
78
+ export declare function createImportManager(brain: any): ImportManager;