@soulcraft/brainy 3.9.1 → 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 +64 -6
  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
@@ -0,0 +1,598 @@
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 { NounType, VerbType } from '../types/graphTypes.js';
9
+ import { cosineDistance } from '../utils/distance.js';
10
+ import { v4 as uuidv4 } from '../universal/uuid.js';
11
+ /**
12
+ * Universal Concept System
13
+ *
14
+ * Manages concepts that exist independently of any specific file or context
15
+ * Examples:
16
+ * - "Authentication" concept appearing in docs, code, tests
17
+ * - "Customer Journey" concept in marketing, UX, analytics
18
+ * - "Dependency Injection" pattern across multiple codebases
19
+ * - "Sustainability" theme in various research papers
20
+ */
21
+ export class ConceptSystem {
22
+ constructor(brain, config) {
23
+ this.brain = brain;
24
+ this.conceptCache = new Map();
25
+ this.config = {
26
+ autoLink: config?.autoLink ?? false,
27
+ similarityThreshold: config?.similarityThreshold ?? 0.7,
28
+ maxManifestations: config?.maxManifestations ?? 1000,
29
+ strengthDecay: config?.strengthDecay ?? 0.95 // 5% decay over time
30
+ };
31
+ }
32
+ /**
33
+ * Create a new universal concept
34
+ */
35
+ async createConcept(concept) {
36
+ const conceptId = uuidv4();
37
+ const timestamp = Date.now();
38
+ const universalConcept = {
39
+ ...concept,
40
+ id: conceptId,
41
+ created: timestamp,
42
+ lastUpdated: timestamp,
43
+ version: 1,
44
+ links: [],
45
+ manifestations: []
46
+ };
47
+ // Generate embedding for concept
48
+ let embedding;
49
+ try {
50
+ embedding = await this.generateConceptEmbedding(universalConcept);
51
+ }
52
+ catch (error) {
53
+ console.warn('Failed to generate concept embedding:', error);
54
+ }
55
+ // Store concept in Brainy
56
+ const brainyEntity = await this.brain.add({
57
+ type: NounType.Concept,
58
+ data: Buffer.from(JSON.stringify(universalConcept)),
59
+ metadata: {
60
+ ...universalConcept,
61
+ conceptType: 'universal',
62
+ system: 'vfs-concept'
63
+ },
64
+ vector: embedding
65
+ });
66
+ // Auto-link to similar concepts if enabled
67
+ if (this.config.autoLink) {
68
+ await this.autoLinkConcept(conceptId);
69
+ }
70
+ // Update cache
71
+ this.conceptCache.set(conceptId, universalConcept);
72
+ return brainyEntity;
73
+ }
74
+ /**
75
+ * Find concepts by various criteria
76
+ */
77
+ async findConcepts(query) {
78
+ const searchQuery = {
79
+ conceptType: 'universal',
80
+ system: 'vfs-concept'
81
+ };
82
+ // Direct attribute matching
83
+ if (query.name)
84
+ searchQuery.name = query.name;
85
+ if (query.domain)
86
+ searchQuery.domain = query.domain;
87
+ if (query.category)
88
+ searchQuery.category = query.category;
89
+ // Keyword matching
90
+ if (query.keywords && query.keywords.length > 0) {
91
+ searchQuery.keywords = { $in: query.keywords };
92
+ }
93
+ // File manifestation search
94
+ if (query.manifestedIn) {
95
+ // Find concepts that have manifestations in this file
96
+ const manifestationResults = await this.brain.find({
97
+ where: {
98
+ filePath: query.manifestedIn,
99
+ eventType: 'concept-manifestation',
100
+ system: 'vfs-concept'
101
+ },
102
+ type: NounType.Event,
103
+ limit: 1000
104
+ });
105
+ const conceptIds = manifestationResults.map(r => r.entity.metadata.conceptId);
106
+ if (conceptIds.length > 0) {
107
+ searchQuery.id = { $in: conceptIds };
108
+ }
109
+ else {
110
+ return []; // No concepts found in this file
111
+ }
112
+ }
113
+ // Search in Brainy
114
+ let results = await this.brain.find({
115
+ where: searchQuery,
116
+ type: NounType.Concept,
117
+ limit: 1000
118
+ });
119
+ // If searching for similar concepts, use vector similarity
120
+ if (query.similar) {
121
+ try {
122
+ const queryEmbedding = await this.generateTextEmbedding(query.similar);
123
+ if (queryEmbedding) {
124
+ // Get all concepts and rank by similarity
125
+ const allConcepts = await this.brain.find({
126
+ where: { conceptType: 'universal', system: 'vfs-concept' },
127
+ type: NounType.Concept,
128
+ limit: 10000
129
+ });
130
+ const withSimilarity = allConcepts
131
+ .filter(c => c.entity.vector && c.entity.vector.length > 0)
132
+ .map(c => ({
133
+ concept: c,
134
+ similarity: 1 - cosineDistance(queryEmbedding, c.entity.vector)
135
+ }))
136
+ .filter(s => s.similarity > this.config.similarityThreshold)
137
+ .sort((a, b) => b.similarity - a.similarity);
138
+ results = withSimilarity.map(s => s.concept);
139
+ }
140
+ }
141
+ catch (error) {
142
+ console.warn('Failed to perform concept similarity search:', error);
143
+ }
144
+ }
145
+ return results.map(r => r.entity.metadata);
146
+ }
147
+ /**
148
+ * Link two concepts together
149
+ */
150
+ async linkConcept(fromConceptId, toConceptId, relationship, options) {
151
+ const linkId = uuidv4();
152
+ const fromConcept = await this.getConcept(fromConceptId);
153
+ const toConcept = await this.getConcept(toConceptId);
154
+ if (!fromConcept || !toConcept) {
155
+ throw new Error('One or both concepts not found');
156
+ }
157
+ // Create link
158
+ const link = {
159
+ id: linkId,
160
+ targetConceptId: toConceptId,
161
+ relationship,
162
+ strength: options?.strength ?? 0.8,
163
+ context: options?.context,
164
+ bidirectional: options?.bidirectional ?? false
165
+ };
166
+ // Add link to source concept
167
+ fromConcept.links.push(link);
168
+ fromConcept.lastUpdated = Date.now();
169
+ await this.updateConcept(fromConcept);
170
+ // Add bidirectional link if specified
171
+ if (link.bidirectional) {
172
+ const reverseRelationship = this.getReverseRelationship(relationship);
173
+ const reverseLink = {
174
+ id: uuidv4(),
175
+ targetConceptId: fromConceptId,
176
+ relationship: reverseRelationship,
177
+ strength: link.strength,
178
+ context: link.context,
179
+ bidirectional: true
180
+ };
181
+ toConcept.links.push(reverseLink);
182
+ toConcept.lastUpdated = Date.now();
183
+ await this.updateConcept(toConcept);
184
+ }
185
+ // Create Brainy relationship
186
+ await this.brain.relate({
187
+ from: fromConceptId,
188
+ to: toConceptId,
189
+ type: this.getVerbType(relationship),
190
+ metadata: {
191
+ strength: link.strength,
192
+ context: link.context,
193
+ bidirectional: link.bidirectional
194
+ }
195
+ });
196
+ return linkId;
197
+ }
198
+ /**
199
+ * Record a manifestation of a concept in a file
200
+ */
201
+ async recordManifestation(conceptId, filePath, context, form, options) {
202
+ const concept = await this.getConcept(conceptId);
203
+ if (!concept) {
204
+ throw new Error(`Concept ${conceptId} not found`);
205
+ }
206
+ const manifestationId = uuidv4();
207
+ const timestamp = Date.now();
208
+ const manifestation = {
209
+ id: manifestationId,
210
+ conceptId,
211
+ filePath,
212
+ context,
213
+ form,
214
+ position: options?.position,
215
+ confidence: options?.confidence ?? 1.0,
216
+ timestamp,
217
+ extractedBy: options?.extractedBy ?? 'manual'
218
+ };
219
+ // Store manifestation as Brainy event
220
+ await this.brain.add({
221
+ type: NounType.Event,
222
+ data: Buffer.from(context),
223
+ metadata: {
224
+ ...manifestation,
225
+ eventType: 'concept-manifestation',
226
+ system: 'vfs-concept'
227
+ }
228
+ });
229
+ // Create relationship to concept
230
+ await this.brain.relate({
231
+ from: manifestationId,
232
+ to: conceptId,
233
+ type: VerbType.Implements
234
+ });
235
+ // Update concept with new manifestation
236
+ concept.manifestations.push(manifestation);
237
+ concept.lastUpdated = timestamp;
238
+ // Update concept strength based on manifestations
239
+ concept.strength = Math.min(1.0, concept.strength + 0.1);
240
+ // Prune old manifestations if needed
241
+ if (concept.manifestations.length > this.config.maxManifestations) {
242
+ concept.manifestations = concept.manifestations
243
+ .sort((a, b) => b.timestamp - a.timestamp)
244
+ .slice(0, this.config.maxManifestations);
245
+ }
246
+ // Update stored concept
247
+ await this.updateConcept(concept);
248
+ return manifestationId;
249
+ }
250
+ /**
251
+ * Extract and link concepts from content
252
+ */
253
+ async extractAndLinkConcepts(filePath, content) {
254
+ if (!this.config.autoLink) {
255
+ return [];
256
+ }
257
+ const text = content.toString('utf8');
258
+ const extractedConcepts = [];
259
+ // Simple concept extraction patterns
260
+ // In production, this would use advanced NLP/AI models
261
+ const conceptPatterns = [
262
+ // Technical concepts
263
+ /\b(authentication|authorization|validation|encryption|caching|logging|monitoring)\b/gi,
264
+ // Business concepts
265
+ /\b(customer\s+journey|user\s+experience|business\s+logic|revenue\s+model)\b/gi,
266
+ // Design patterns
267
+ /\b(singleton|factory|observer|strategy|adapter|decorator)\b/gi,
268
+ // General concepts
269
+ /\b(security|performance|scalability|maintainability|reliability)\b/gi
270
+ ];
271
+ for (const pattern of conceptPatterns) {
272
+ const matches = text.matchAll(pattern);
273
+ for (const match of matches) {
274
+ const conceptName = match[0].toLowerCase();
275
+ const context = this.extractContext(text, match.index || 0);
276
+ // Find or create concept
277
+ let concepts = await this.findConcepts({ name: conceptName });
278
+ let conceptId;
279
+ if (concepts.length === 0) {
280
+ // Create new concept
281
+ conceptId = await this.createConcept({
282
+ name: conceptName,
283
+ domain: this.detectDomain(conceptName, text),
284
+ category: this.detectCategory(conceptName),
285
+ keywords: [conceptName],
286
+ strength: 0.5,
287
+ metadata: {}
288
+ });
289
+ extractedConcepts.push(conceptId);
290
+ }
291
+ else {
292
+ conceptId = concepts[0].id;
293
+ }
294
+ // Record manifestation
295
+ await this.recordManifestation(conceptId, filePath, context, this.detectManifestationForm(context), {
296
+ confidence: 0.8,
297
+ extractedBy: 'auto'
298
+ });
299
+ }
300
+ }
301
+ return extractedConcepts;
302
+ }
303
+ /**
304
+ * Get concept graph for visualization
305
+ */
306
+ async getConceptGraph(options) {
307
+ const query = {
308
+ conceptType: 'universal',
309
+ system: 'vfs-concept'
310
+ };
311
+ if (options?.domain) {
312
+ query.domain = options.domain;
313
+ }
314
+ if (options?.minStrength) {
315
+ query.strength = { $gte: options.minStrength };
316
+ }
317
+ const results = await this.brain.find({
318
+ where: query,
319
+ type: NounType.Concept,
320
+ limit: options?.maxConcepts || 1000
321
+ });
322
+ const concepts = results.map(r => r.entity.metadata);
323
+ // Build graph structure
324
+ const graphConcepts = concepts.map(c => ({
325
+ id: c.id,
326
+ name: c.name,
327
+ domain: c.domain,
328
+ strength: c.strength,
329
+ manifestationCount: c.manifestations.length
330
+ }));
331
+ const graphLinks = [];
332
+ for (const concept of concepts) {
333
+ for (const link of concept.links) {
334
+ // Only include links to concepts in our result set
335
+ if (concepts.find(c => c.id === link.targetConceptId)) {
336
+ graphLinks.push({
337
+ source: concept.id,
338
+ target: link.targetConceptId,
339
+ relationship: link.relationship,
340
+ strength: link.strength
341
+ });
342
+ }
343
+ }
344
+ }
345
+ return {
346
+ concepts: graphConcepts,
347
+ links: graphLinks
348
+ };
349
+ }
350
+ /**
351
+ * Find appearances of a concept
352
+ */
353
+ async findAppearances(conceptId, options) {
354
+ const query = {
355
+ conceptId,
356
+ eventType: 'concept-manifestation',
357
+ system: 'vfs-concept'
358
+ };
359
+ if (options?.filePath) {
360
+ query.filePath = options.filePath;
361
+ }
362
+ if (options?.form) {
363
+ query.form = options.form;
364
+ }
365
+ if (options?.minConfidence) {
366
+ query.confidence = { $gte: options.minConfidence };
367
+ }
368
+ const results = await this.brain.find({
369
+ where: query,
370
+ type: NounType.Event,
371
+ limit: options?.limit || 1000
372
+ });
373
+ return results
374
+ .map(r => r.entity.metadata)
375
+ .sort((a, b) => b.timestamp - a.timestamp);
376
+ }
377
+ /**
378
+ * Auto-link concept to similar concepts
379
+ */
380
+ async autoLinkConcept(conceptId) {
381
+ const concept = await this.getConcept(conceptId);
382
+ if (!concept)
383
+ return;
384
+ // Find similar concepts
385
+ const similar = await this.findConcepts({
386
+ similar: concept.name + ' ' + (concept.description || '')
387
+ });
388
+ for (const similarConcept of similar) {
389
+ if (similarConcept.id === conceptId)
390
+ continue;
391
+ // Calculate relationship strength based on similarity
392
+ const strength = await this.calculateConceptSimilarity(concept, similarConcept);
393
+ if (strength > this.config.similarityThreshold) {
394
+ await this.linkConcept(conceptId, similarConcept.id, 'related', { strength, bidirectional: true });
395
+ }
396
+ }
397
+ }
398
+ /**
399
+ * Get concept by ID
400
+ */
401
+ async getConcept(conceptId) {
402
+ // Check cache first
403
+ if (this.conceptCache.has(conceptId)) {
404
+ return this.conceptCache.get(conceptId);
405
+ }
406
+ // Query from Brainy
407
+ const results = await this.brain.find({
408
+ where: {
409
+ id: conceptId,
410
+ conceptType: 'universal',
411
+ system: 'vfs-concept'
412
+ },
413
+ type: NounType.Concept,
414
+ limit: 1
415
+ });
416
+ if (results.length === 0) {
417
+ return null;
418
+ }
419
+ const concept = results[0].entity.metadata;
420
+ this.conceptCache.set(conceptId, concept);
421
+ return concept;
422
+ }
423
+ /**
424
+ * Update stored concept
425
+ */
426
+ async updateConcept(concept) {
427
+ // Find the Brainy entity
428
+ const results = await this.brain.find({
429
+ where: {
430
+ id: concept.id,
431
+ conceptType: 'universal',
432
+ system: 'vfs-concept'
433
+ },
434
+ type: NounType.Concept,
435
+ limit: 1
436
+ });
437
+ if (results.length > 0) {
438
+ await this.brain.update({
439
+ id: results[0].entity.id,
440
+ data: Buffer.from(JSON.stringify(concept)),
441
+ metadata: {
442
+ ...concept,
443
+ conceptType: 'universal',
444
+ system: 'vfs-concept'
445
+ }
446
+ });
447
+ }
448
+ // Update cache
449
+ this.conceptCache.set(concept.id, concept);
450
+ }
451
+ /**
452
+ * Calculate similarity between two concepts
453
+ */
454
+ async calculateConceptSimilarity(concept1, concept2) {
455
+ // Simple similarity calculation
456
+ let similarity = 0;
457
+ // Domain similarity
458
+ if (concept1.domain === concept2.domain)
459
+ similarity += 0.3;
460
+ // Category similarity
461
+ if (concept1.category === concept2.category)
462
+ similarity += 0.2;
463
+ // Keyword overlap
464
+ const commonKeywords = concept1.keywords.filter(k => concept2.keywords.includes(k));
465
+ similarity += (commonKeywords.length / Math.max(concept1.keywords.length, concept2.keywords.length)) * 0.3;
466
+ // Name similarity (simple string comparison)
467
+ const nameWords1 = concept1.name.toLowerCase().split(/\s+/);
468
+ const nameWords2 = concept2.name.toLowerCase().split(/\s+/);
469
+ const commonWords = nameWords1.filter(w => nameWords2.includes(w));
470
+ similarity += (commonWords.length / Math.max(nameWords1.length, nameWords2.length)) * 0.2;
471
+ return Math.min(1.0, similarity);
472
+ }
473
+ /**
474
+ * Generate embedding for concept
475
+ */
476
+ async generateConceptEmbedding(concept) {
477
+ try {
478
+ const text = [
479
+ concept.name,
480
+ concept.description || '',
481
+ concept.domain,
482
+ concept.category,
483
+ ...(Array.isArray(concept.keywords) ? concept.keywords : [])
484
+ ].join(' ');
485
+ return await this.generateTextEmbedding(text);
486
+ }
487
+ catch (error) {
488
+ console.error('Failed to generate concept embedding:', error);
489
+ return undefined;
490
+ }
491
+ }
492
+ /**
493
+ * Generate embedding for text
494
+ */
495
+ async generateTextEmbedding(text) {
496
+ try {
497
+ // Generate embedding using Brainy's embed method
498
+ const vector = await this.brain.embed(text);
499
+ return vector;
500
+ }
501
+ catch (error) {
502
+ console.debug('Failed to generate embedding:', error);
503
+ return undefined;
504
+ }
505
+ }
506
+ /**
507
+ * Get reverse relationship type
508
+ */
509
+ getReverseRelationship(relationship) {
510
+ const reverseMap = {
511
+ 'extends': 'extended-by',
512
+ 'implements': 'implemented-by',
513
+ 'uses': 'used-by',
514
+ 'opposite': 'opposite',
515
+ 'related': 'related',
516
+ 'contains': 'part-of',
517
+ 'part-of': 'contains'
518
+ };
519
+ return reverseMap[relationship] || 'related';
520
+ }
521
+ /**
522
+ * Map concept relationship to VerbType
523
+ */
524
+ getVerbType(relationship) {
525
+ const verbMap = {
526
+ 'extends': VerbType.Extends,
527
+ 'implements': VerbType.Implements,
528
+ 'uses': VerbType.Uses,
529
+ 'opposite': VerbType.Conflicts,
530
+ 'related': VerbType.RelatedTo,
531
+ 'contains': VerbType.Contains,
532
+ 'part-of': VerbType.PartOf
533
+ };
534
+ return verbMap[relationship] || VerbType.RelatedTo;
535
+ }
536
+ /**
537
+ * Detect concept domain from context
538
+ */
539
+ detectDomain(conceptName, context) {
540
+ if (/import|export|function|class|const|var|let/.test(context))
541
+ return 'technical';
542
+ if (/customer|user|business|revenue|market/.test(context))
543
+ return 'business';
544
+ if (/design|pattern|architecture/.test(context))
545
+ return 'design';
546
+ if (/research|study|analysis/.test(context))
547
+ return 'academic';
548
+ return 'general';
549
+ }
550
+ /**
551
+ * Detect concept category
552
+ */
553
+ detectCategory(conceptName) {
554
+ if (/pattern|strategy|factory|singleton/.test(conceptName))
555
+ return 'pattern';
556
+ if (/principle|rule|law/.test(conceptName))
557
+ return 'principle';
558
+ if (/method|approach|technique/.test(conceptName))
559
+ return 'method';
560
+ if (/entity|object|model/.test(conceptName))
561
+ return 'entity';
562
+ return 'concept';
563
+ }
564
+ /**
565
+ * Detect manifestation form from context
566
+ */
567
+ detectManifestationForm(context) {
568
+ if (context.includes('definition') || context.includes('is defined as'))
569
+ return 'definition';
570
+ if (context.includes('example') || context.includes('for instance'))
571
+ return 'example';
572
+ if (context.includes('implements') || context.includes('function'))
573
+ return 'implementation';
574
+ if (context.includes('discussed') || context.includes('explains'))
575
+ return 'discussion';
576
+ return 'usage';
577
+ }
578
+ /**
579
+ * Extract context around a position
580
+ */
581
+ extractContext(text, position, radius = 150) {
582
+ const start = Math.max(0, position - radius);
583
+ const end = Math.min(text.length, position + radius);
584
+ return text.slice(start, end);
585
+ }
586
+ /**
587
+ * Clear concept cache
588
+ */
589
+ clearCache(conceptId) {
590
+ if (conceptId) {
591
+ this.conceptCache.delete(conceptId);
592
+ }
593
+ else {
594
+ this.conceptCache.clear();
595
+ }
596
+ }
597
+ }
598
+ //# sourceMappingURL=ConceptSystem.js.map
@@ -0,0 +1,75 @@
1
+ /**
2
+ * EntityManager Base Class
3
+ *
4
+ * Provides standardized entity ID management for all Knowledge Layer components
5
+ * Solves the root cause of ID mismatch issues by establishing clear patterns
6
+ */
7
+ import { Brainy } from '../brainy.js';
8
+ import { NounType } from '../types/graphTypes.js';
9
+ /**
10
+ * Standard entity structure used by all Knowledge Layer components
11
+ */
12
+ export interface ManagedEntity {
13
+ /** Domain-specific ID (for external references) */
14
+ id: string;
15
+ /** The actual Brainy entity ID (for internal operations) */
16
+ brainyId?: string;
17
+ /** Entity metadata */
18
+ [key: string]: any;
19
+ }
20
+ /**
21
+ * EntityManager Base Class
22
+ *
23
+ * All Knowledge Layer components should extend this to get standardized:
24
+ * - Entity storage and retrieval
25
+ * - ID management and mapping
26
+ * - Query patterns
27
+ * - Relationship creation
28
+ */
29
+ export declare abstract class EntityManager {
30
+ protected brain: Brainy;
31
+ protected systemName: string;
32
+ private idMappings;
33
+ private brainyToMappings;
34
+ constructor(brain: Brainy, systemName: string);
35
+ /**
36
+ * Store an entity with proper ID management
37
+ */
38
+ protected storeEntity<T extends ManagedEntity>(entity: T, nounType: NounType, embedding?: number[], data?: any): Promise<string>;
39
+ /**
40
+ * Update an existing entity
41
+ */
42
+ protected updateEntity<T extends ManagedEntity>(entity: T, embedding?: number[]): Promise<void>;
43
+ /**
44
+ * Retrieve entity by domain ID
45
+ */
46
+ protected getEntity<T extends ManagedEntity>(domainId: string): Promise<T | null>;
47
+ /**
48
+ * Find entities by metadata criteria
49
+ */
50
+ protected findEntities<T extends ManagedEntity>(criteria: Record<string, any>, nounType?: NounType, limit?: number): Promise<T[]>;
51
+ /**
52
+ * Create relationship between entities using proper Brainy IDs
53
+ */
54
+ protected createRelationship(fromDomainId: string, toDomainId: string, relationshipType: any, metadata?: Record<string, any>): Promise<void>;
55
+ /**
56
+ * Get Brainy ID for a domain ID
57
+ */
58
+ protected getBrainyId(domainId: string): Promise<string | null>;
59
+ /**
60
+ * Get domain ID for a Brainy ID
61
+ */
62
+ protected getDomainId(brainyId: string): string | null;
63
+ /**
64
+ * Delete entity by domain ID
65
+ */
66
+ protected deleteEntity(domainId: string): Promise<void>;
67
+ /**
68
+ * Clear ID mapping cache (useful for tests)
69
+ */
70
+ protected clearMappingCache(): void;
71
+ /**
72
+ * Batch load mappings for performance
73
+ */
74
+ protected loadMappings(domainIds: string[]): Promise<void>;
75
+ }