@soulcraft/brainy 3.9.0 → 3.10.0

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.
Files changed (43) hide show
  1. package/README.md +89 -33
  2. package/dist/augmentations/KnowledgeAugmentation.d.ts +40 -0
  3. package/dist/augmentations/KnowledgeAugmentation.js +251 -0
  4. package/dist/augmentations/defaultAugmentations.d.ts +1 -0
  5. package/dist/augmentations/defaultAugmentations.js +5 -0
  6. package/dist/brainy.d.ts +11 -0
  7. package/dist/brainy.js +87 -1
  8. package/dist/embeddings/EmbeddingManager.js +14 -2
  9. package/dist/utils/mutex.d.ts +2 -0
  10. package/dist/utils/mutex.js +14 -3
  11. package/dist/vfs/ConceptSystem.d.ts +202 -0
  12. package/dist/vfs/ConceptSystem.js +598 -0
  13. package/dist/vfs/EntityManager.d.ts +75 -0
  14. package/dist/vfs/EntityManager.js +216 -0
  15. package/dist/vfs/EventRecorder.d.ts +83 -0
  16. package/dist/vfs/EventRecorder.js +292 -0
  17. package/dist/vfs/FSCompat.d.ts +85 -0
  18. package/dist/vfs/FSCompat.js +257 -0
  19. package/dist/vfs/GitBridge.d.ts +167 -0
  20. package/dist/vfs/GitBridge.js +537 -0
  21. package/dist/vfs/KnowledgeAugmentation.d.ts +104 -0
  22. package/dist/vfs/KnowledgeAugmentation.js +146 -0
  23. package/dist/vfs/KnowledgeLayer.d.ts +35 -0
  24. package/dist/vfs/KnowledgeLayer.js +443 -0
  25. package/dist/vfs/PathResolver.d.ts +96 -0
  26. package/dist/vfs/PathResolver.js +362 -0
  27. package/dist/vfs/PersistentEntitySystem.d.ts +163 -0
  28. package/dist/vfs/PersistentEntitySystem.js +525 -0
  29. package/dist/vfs/SemanticVersioning.d.ts +105 -0
  30. package/dist/vfs/SemanticVersioning.js +318 -0
  31. package/dist/vfs/VirtualFileSystem.d.ts +246 -0
  32. package/dist/vfs/VirtualFileSystem.js +1927 -0
  33. package/dist/vfs/importers/DirectoryImporter.d.ts +86 -0
  34. package/dist/vfs/importers/DirectoryImporter.js +298 -0
  35. package/dist/vfs/index.d.ts +19 -0
  36. package/dist/vfs/index.js +26 -0
  37. package/dist/vfs/streams/VFSReadStream.d.ts +19 -0
  38. package/dist/vfs/streams/VFSReadStream.js +54 -0
  39. package/dist/vfs/streams/VFSWriteStream.d.ts +21 -0
  40. package/dist/vfs/streams/VFSWriteStream.js +70 -0
  41. package/dist/vfs/types.d.ts +330 -0
  42. package/dist/vfs/types.js +46 -0
  43. package/package.json +1 -1
package/dist/brainy.js CHANGED
@@ -14,6 +14,7 @@ import { createDefaultAugmentations } from './augmentations/defaultAugmentations
14
14
  import { ImprovedNeuralAPI } from './neural/improvedNeuralAPI.js';
15
15
  import { NaturalLanguageProcessor } from './neural/naturalLanguageProcessor.js';
16
16
  import { TripleIntelligenceSystem } from './triple/TripleIntelligenceSystem.js';
17
+ import { VirtualFileSystem } from './vfs/VirtualFileSystem.js';
17
18
  import { MetadataIndexManager } from './utils/metadataIndex.js';
18
19
  import { GraphAdjacencyIndex } from './graph/graphAdjacencyIndex.js';
19
20
  import { createPipeline } from './streaming/pipeline.js';
@@ -138,6 +139,12 @@ export class Brainy {
138
139
  throw new Error('Brainy not initialized. Call init() first.');
139
140
  }
140
141
  }
142
+ /**
143
+ * Check if Brainy is initialized
144
+ */
145
+ get isInitialized() {
146
+ return this.initialized;
147
+ }
141
148
  // ============= CORE CRUD OPERATIONS =============
142
149
  /**
143
150
  * Add an entity to the database
@@ -895,6 +902,15 @@ export class Brainy {
895
902
  }
896
903
  return this._nlp;
897
904
  }
905
+ /**
906
+ * Virtual File System API - Knowledge Operating System
907
+ */
908
+ vfs() {
909
+ if (!this._vfs) {
910
+ this._vfs = new VirtualFileSystem(this);
911
+ }
912
+ return this._vfs;
913
+ }
898
914
  /**
899
915
  * Data Management API - backup, restore, import, export
900
916
  */
@@ -1448,9 +1464,79 @@ export class Brainy {
1448
1464
  }
1449
1465
  /**
1450
1466
  * Embed data into vector
1467
+ * Handles any data type by converting to string representation
1451
1468
  */
1452
1469
  async embed(data) {
1453
- return this.embedder(data);
1470
+ // Handle different data types intelligently
1471
+ let textToEmbed;
1472
+ if (typeof data === 'string') {
1473
+ textToEmbed = data;
1474
+ }
1475
+ else if (Array.isArray(data)) {
1476
+ // Array of items - convert each to string
1477
+ textToEmbed = data.map(item => {
1478
+ if (typeof item === 'string')
1479
+ return item;
1480
+ if (typeof item === 'number' || typeof item === 'boolean')
1481
+ return String(item);
1482
+ if (item && typeof item === 'object') {
1483
+ // For objects, try to extract meaningful text
1484
+ if (item.data)
1485
+ return String(item.data);
1486
+ if (item.content)
1487
+ return String(item.content);
1488
+ if (item.text)
1489
+ return String(item.text);
1490
+ if (item.name)
1491
+ return String(item.name);
1492
+ if (item.title)
1493
+ return String(item.title);
1494
+ if (item.description)
1495
+ return String(item.description);
1496
+ // Fallback to JSON for complex objects
1497
+ try {
1498
+ return JSON.stringify(item);
1499
+ }
1500
+ catch {
1501
+ return String(item);
1502
+ }
1503
+ }
1504
+ return String(item);
1505
+ });
1506
+ }
1507
+ else if (data && typeof data === 'object') {
1508
+ // Single object - extract meaningful text
1509
+ if (data.data)
1510
+ textToEmbed = String(data.data);
1511
+ else if (data.content)
1512
+ textToEmbed = String(data.content);
1513
+ else if (data.text)
1514
+ textToEmbed = String(data.text);
1515
+ else if (data.name)
1516
+ textToEmbed = String(data.name);
1517
+ else if (data.title)
1518
+ textToEmbed = String(data.title);
1519
+ else if (data.description)
1520
+ textToEmbed = String(data.description);
1521
+ else {
1522
+ // For complex objects, create a descriptive string
1523
+ try {
1524
+ textToEmbed = JSON.stringify(data);
1525
+ }
1526
+ catch {
1527
+ textToEmbed = String(data);
1528
+ }
1529
+ }
1530
+ }
1531
+ else if (data === null || data === undefined) {
1532
+ // Handle null/undefined gracefully
1533
+ textToEmbed = '';
1534
+ }
1535
+ else {
1536
+ // Numbers, booleans, etc - convert to string
1537
+ textToEmbed = String(data);
1538
+ }
1539
+ return this.embedder(textToEmbed);
1454
1540
  }
1455
1541
  /**
1456
1542
  * Warm up the system
@@ -165,8 +165,20 @@ export class EmbeddingManager {
165
165
  if (!this.model) {
166
166
  throw new Error('Model not initialized');
167
167
  }
168
- // Handle array input
169
- const input = Array.isArray(text) ? text.join(' ') : text;
168
+ // CRITICAL FIX: Ensure input is always a string
169
+ let input;
170
+ if (Array.isArray(text)) {
171
+ // Join array elements, converting each to string first
172
+ input = text.map(t => typeof t === 'string' ? t : String(t)).join(' ');
173
+ }
174
+ else if (typeof text === 'string') {
175
+ input = text;
176
+ }
177
+ else {
178
+ // This shouldn't happen but let's be defensive
179
+ console.warn('EmbeddingManager.embed received non-string input:', typeof text);
180
+ input = String(text);
181
+ }
170
182
  // Generate embedding
171
183
  const output = await this.model(input, {
172
184
  pooling: 'mean',
@@ -29,7 +29,9 @@ export declare class FileMutex implements MutexInterface {
29
29
  private lockDir;
30
30
  private processLocks;
31
31
  private lockTimers;
32
+ private modulesLoaded;
32
33
  constructor(lockDir: string);
34
+ private loadNodeModules;
33
35
  acquire(key: string, timeout?: number): Promise<() => void>;
34
36
  private release;
35
37
  runExclusive<T>(key: string, fn: () => Promise<T>, timeout?: number): Promise<T>;
@@ -74,14 +74,25 @@ export class FileMutex {
74
74
  constructor(lockDir) {
75
75
  this.processLocks = new Map();
76
76
  this.lockTimers = new Map();
77
+ this.modulesLoaded = false;
77
78
  this.lockDir = lockDir;
78
- // Lazy load Node.js modules
79
+ }
80
+ async loadNodeModules() {
81
+ if (this.modulesLoaded)
82
+ return;
79
83
  if (typeof window === 'undefined') {
80
- this.fs = require('fs');
81
- this.path = require('path');
84
+ // Modern ESM-compatible dynamic imports
85
+ const [fs, path] = await Promise.all([
86
+ import('fs'),
87
+ import('path')
88
+ ]);
89
+ this.fs = fs;
90
+ this.path = path;
91
+ this.modulesLoaded = true;
82
92
  }
83
93
  }
84
94
  async acquire(key, timeout = 30000) {
95
+ await this.loadNodeModules();
85
96
  if (!this.fs || !this.path) {
86
97
  throw new Error('FileMutex is only available in Node.js environments');
87
98
  }
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Universal Concept System for VFS
3
+ *
4
+ * Manages concepts that transcend files and exist independently
5
+ * Ideas that can be linked to multiple manifestations across domains
6
+ * PRODUCTION-READY: Real implementation using Brainy
7
+ */
8
+ import { Brainy } from '../brainy.js';
9
+ /**
10
+ * Universal concept that exists independently of files
11
+ */
12
+ export interface UniversalConcept {
13
+ id: string;
14
+ name: string;
15
+ description?: string;
16
+ domain: string;
17
+ category: string;
18
+ keywords: string[];
19
+ links: ConceptLink[];
20
+ manifestations: ConceptManifestation[];
21
+ strength: number;
22
+ created: number;
23
+ lastUpdated: number;
24
+ version: number;
25
+ metadata: Record<string, any>;
26
+ }
27
+ /**
28
+ * A link between concepts
29
+ */
30
+ export interface ConceptLink {
31
+ id: string;
32
+ targetConceptId: string;
33
+ relationship: 'extends' | 'implements' | 'uses' | 'opposite' | 'related' | 'contains' | 'part-of';
34
+ strength: number;
35
+ context?: string;
36
+ bidirectional: boolean;
37
+ }
38
+ /**
39
+ * A manifestation of a concept in a specific location
40
+ */
41
+ export interface ConceptManifestation {
42
+ id: string;
43
+ conceptId: string;
44
+ filePath: string;
45
+ context: string;
46
+ form: 'definition' | 'usage' | 'example' | 'discussion' | 'implementation';
47
+ position?: {
48
+ line?: number;
49
+ column?: number;
50
+ offset?: number;
51
+ };
52
+ confidence: number;
53
+ timestamp: number;
54
+ extractedBy: 'manual' | 'auto' | 'ai';
55
+ }
56
+ /**
57
+ * Configuration for concept system
58
+ */
59
+ export interface ConceptSystemConfig {
60
+ autoLink?: boolean;
61
+ similarityThreshold?: number;
62
+ maxManifestations?: number;
63
+ strengthDecay?: number;
64
+ }
65
+ /**
66
+ * Concept graph structure for visualization
67
+ */
68
+ export interface ConceptGraph {
69
+ concepts: Array<{
70
+ id: string;
71
+ name: string;
72
+ domain: string;
73
+ strength: number;
74
+ manifestationCount: number;
75
+ }>;
76
+ links: Array<{
77
+ source: string;
78
+ target: string;
79
+ relationship: string;
80
+ strength: number;
81
+ }>;
82
+ }
83
+ /**
84
+ * Universal Concept System
85
+ *
86
+ * Manages concepts that exist independently of any specific file or context
87
+ * Examples:
88
+ * - "Authentication" concept appearing in docs, code, tests
89
+ * - "Customer Journey" concept in marketing, UX, analytics
90
+ * - "Dependency Injection" pattern across multiple codebases
91
+ * - "Sustainability" theme in various research papers
92
+ */
93
+ export declare class ConceptSystem {
94
+ private brain;
95
+ private config;
96
+ private conceptCache;
97
+ constructor(brain: Brainy, config?: ConceptSystemConfig);
98
+ /**
99
+ * Create a new universal concept
100
+ */
101
+ createConcept(concept: Omit<UniversalConcept, 'id' | 'created' | 'lastUpdated' | 'version' | 'links' | 'manifestations'>): Promise<string>;
102
+ /**
103
+ * Find concepts by various criteria
104
+ */
105
+ findConcepts(query: {
106
+ name?: string;
107
+ domain?: string;
108
+ category?: string;
109
+ keywords?: string[];
110
+ similar?: string;
111
+ manifestedIn?: string;
112
+ }): Promise<UniversalConcept[]>;
113
+ /**
114
+ * Link two concepts together
115
+ */
116
+ linkConcept(fromConceptId: string, toConceptId: string, relationship: ConceptLink['relationship'], options?: {
117
+ strength?: number;
118
+ context?: string;
119
+ bidirectional?: boolean;
120
+ }): Promise<string>;
121
+ /**
122
+ * Record a manifestation of a concept in a file
123
+ */
124
+ recordManifestation(conceptId: string, filePath: string, context: string, form: ConceptManifestation['form'], options?: {
125
+ position?: ConceptManifestation['position'];
126
+ confidence?: number;
127
+ extractedBy?: ConceptManifestation['extractedBy'];
128
+ }): Promise<string>;
129
+ /**
130
+ * Extract and link concepts from content
131
+ */
132
+ extractAndLinkConcepts(filePath: string, content: Buffer): Promise<string[]>;
133
+ /**
134
+ * Get concept graph for visualization
135
+ */
136
+ getConceptGraph(options?: {
137
+ domain?: string;
138
+ minStrength?: number;
139
+ maxConcepts?: number;
140
+ }): Promise<ConceptGraph>;
141
+ /**
142
+ * Find appearances of a concept
143
+ */
144
+ findAppearances(conceptId: string, options?: {
145
+ filePath?: string;
146
+ form?: ConceptManifestation['form'];
147
+ minConfidence?: number;
148
+ limit?: number;
149
+ }): Promise<ConceptManifestation[]>;
150
+ /**
151
+ * Auto-link concept to similar concepts
152
+ */
153
+ private autoLinkConcept;
154
+ /**
155
+ * Get concept by ID
156
+ */
157
+ private getConcept;
158
+ /**
159
+ * Update stored concept
160
+ */
161
+ private updateConcept;
162
+ /**
163
+ * Calculate similarity between two concepts
164
+ */
165
+ private calculateConceptSimilarity;
166
+ /**
167
+ * Generate embedding for concept
168
+ */
169
+ private generateConceptEmbedding;
170
+ /**
171
+ * Generate embedding for text
172
+ */
173
+ private generateTextEmbedding;
174
+ /**
175
+ * Get reverse relationship type
176
+ */
177
+ private getReverseRelationship;
178
+ /**
179
+ * Map concept relationship to VerbType
180
+ */
181
+ private getVerbType;
182
+ /**
183
+ * Detect concept domain from context
184
+ */
185
+ private detectDomain;
186
+ /**
187
+ * Detect concept category
188
+ */
189
+ private detectCategory;
190
+ /**
191
+ * Detect manifestation form from context
192
+ */
193
+ private detectManifestationForm;
194
+ /**
195
+ * Extract context around a position
196
+ */
197
+ private extractContext;
198
+ /**
199
+ * Clear concept cache
200
+ */
201
+ clearCache(conceptId?: string): void;
202
+ }