@soulcraft/brainy 1.5.0 → 2.0.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.
- package/CHANGELOG.md +188 -0
- package/LICENSE +2 -2
- package/README.md +201 -596
- package/bin/brainy-interactive.js +564 -0
- package/bin/brainy-ts.js +18 -0
- package/bin/brainy.js +672 -81
- package/dist/augmentationPipeline.d.ts +48 -220
- package/dist/augmentationPipeline.js +60 -508
- package/dist/augmentationRegistry.d.ts +22 -31
- package/dist/augmentationRegistry.js +28 -79
- package/dist/augmentations/apiServerAugmentation.d.ts +108 -0
- package/dist/augmentations/apiServerAugmentation.js +502 -0
- package/dist/augmentations/batchProcessingAugmentation.d.ts +95 -0
- package/dist/augmentations/batchProcessingAugmentation.js +567 -0
- package/dist/augmentations/brainyAugmentation.d.ts +153 -0
- package/dist/augmentations/brainyAugmentation.js +145 -0
- package/dist/augmentations/cacheAugmentation.d.ts +105 -0
- package/dist/augmentations/cacheAugmentation.js +238 -0
- package/dist/augmentations/conduitAugmentations.d.ts +54 -156
- package/dist/augmentations/conduitAugmentations.js +156 -1082
- package/dist/augmentations/connectionPoolAugmentation.d.ts +62 -0
- package/dist/augmentations/connectionPoolAugmentation.js +316 -0
- package/dist/augmentations/defaultAugmentations.d.ts +53 -0
- package/dist/augmentations/defaultAugmentations.js +88 -0
- package/dist/augmentations/entityRegistryAugmentation.d.ts +126 -0
- package/dist/augmentations/entityRegistryAugmentation.js +386 -0
- package/dist/augmentations/indexAugmentation.d.ts +117 -0
- package/dist/augmentations/indexAugmentation.js +284 -0
- package/dist/augmentations/intelligentVerbScoringAugmentation.d.ts +152 -0
- package/dist/augmentations/intelligentVerbScoringAugmentation.js +554 -0
- package/dist/augmentations/metricsAugmentation.d.ts +202 -0
- package/dist/augmentations/metricsAugmentation.js +291 -0
- package/dist/augmentations/monitoringAugmentation.d.ts +94 -0
- package/dist/augmentations/monitoringAugmentation.js +227 -0
- package/dist/augmentations/neuralImport.d.ts +50 -117
- package/dist/augmentations/neuralImport.js +255 -629
- package/dist/augmentations/requestDeduplicatorAugmentation.d.ts +52 -0
- package/dist/augmentations/requestDeduplicatorAugmentation.js +162 -0
- package/dist/augmentations/serverSearchAugmentations.d.ts +43 -22
- package/dist/augmentations/serverSearchAugmentations.js +125 -72
- package/dist/augmentations/storageAugmentation.d.ts +54 -0
- package/dist/augmentations/storageAugmentation.js +93 -0
- package/dist/augmentations/storageAugmentations.d.ts +96 -0
- package/dist/augmentations/storageAugmentations.js +182 -0
- package/dist/augmentations/synapseAugmentation.d.ts +156 -0
- package/dist/augmentations/synapseAugmentation.js +312 -0
- package/dist/augmentations/walAugmentation.d.ts +108 -0
- package/dist/augmentations/walAugmentation.js +515 -0
- package/dist/brainyData.d.ts +404 -130
- package/dist/brainyData.js +1331 -853
- package/dist/chat/BrainyChat.d.ts +16 -8
- package/dist/chat/BrainyChat.js +60 -32
- package/dist/chat/ChatCLI.d.ts +1 -1
- package/dist/chat/ChatCLI.js +6 -6
- package/dist/cli/catalog.d.ts +3 -3
- package/dist/cli/catalog.js +116 -70
- package/dist/cli/commands/core.d.ts +61 -0
- package/dist/cli/commands/core.js +348 -0
- package/dist/cli/commands/neural.d.ts +25 -0
- package/dist/cli/commands/neural.js +508 -0
- package/dist/cli/commands/utility.d.ts +37 -0
- package/dist/cli/commands/utility.js +276 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.js +167 -0
- package/dist/cli/interactive.d.ts +164 -0
- package/dist/cli/interactive.js +542 -0
- package/dist/cortex/neuralImport.js +5 -5
- package/dist/critical/model-guardian.js +11 -4
- package/dist/embeddings/lightweight-embedder.d.ts +23 -0
- package/dist/embeddings/lightweight-embedder.js +136 -0
- package/dist/embeddings/universal-memory-manager.d.ts +38 -0
- package/dist/embeddings/universal-memory-manager.js +206 -0
- package/dist/embeddings/worker-embedding.d.ts +7 -0
- package/dist/embeddings/worker-embedding.js +77 -0
- package/dist/embeddings/worker-manager.d.ts +28 -0
- package/dist/embeddings/worker-manager.js +162 -0
- package/dist/examples/basicUsage.js +7 -7
- package/dist/graph/pathfinding.d.ts +78 -0
- package/dist/graph/pathfinding.js +393 -0
- package/dist/hnsw/hnswIndex.d.ts +13 -0
- package/dist/hnsw/hnswIndex.js +35 -0
- package/dist/hnsw/hnswIndexOptimized.d.ts +1 -0
- package/dist/hnsw/hnswIndexOptimized.js +3 -0
- package/dist/index.d.ts +9 -11
- package/dist/index.js +21 -11
- package/dist/indices/fieldIndex.d.ts +76 -0
- package/dist/indices/fieldIndex.js +357 -0
- package/dist/mcp/brainyMCPAdapter.js +3 -2
- package/dist/mcp/mcpAugmentationToolset.js +11 -17
- package/dist/neural/embeddedPatterns.d.ts +41 -0
- package/dist/neural/embeddedPatterns.js +4044 -0
- package/dist/neural/naturalLanguageProcessor.d.ts +94 -0
- package/dist/neural/naturalLanguageProcessor.js +317 -0
- package/dist/neural/naturalLanguageProcessorStatic.d.ts +64 -0
- package/dist/neural/naturalLanguageProcessorStatic.js +151 -0
- package/dist/neural/neuralAPI.d.ts +255 -0
- package/dist/neural/neuralAPI.js +612 -0
- package/dist/neural/patternLibrary.d.ts +101 -0
- package/dist/neural/patternLibrary.js +313 -0
- package/dist/neural/patterns.d.ts +27 -0
- package/dist/neural/patterns.js +68 -0
- package/dist/neural/staticPatternMatcher.d.ts +35 -0
- package/dist/neural/staticPatternMatcher.js +153 -0
- package/dist/scripts/precomputePatternEmbeddings.d.ts +19 -0
- package/dist/scripts/precomputePatternEmbeddings.js +100 -0
- package/dist/storage/adapters/fileSystemStorage.d.ts +5 -0
- package/dist/storage/adapters/fileSystemStorage.js +20 -0
- package/dist/storage/adapters/s3CompatibleStorage.d.ts +5 -0
- package/dist/storage/adapters/s3CompatibleStorage.js +16 -0
- package/dist/storage/enhancedClearOperations.d.ts +83 -0
- package/dist/storage/enhancedClearOperations.js +345 -0
- package/dist/storage/storageFactory.js +31 -27
- package/dist/triple/TripleIntelligence.d.ts +134 -0
- package/dist/triple/TripleIntelligence.js +548 -0
- package/dist/types/augmentations.d.ts +45 -344
- package/dist/types/augmentations.js +5 -2
- package/dist/types/brainyDataInterface.d.ts +20 -10
- package/dist/types/graphTypes.d.ts +46 -0
- package/dist/types/graphTypes.js +16 -2
- package/dist/utils/BoundedRegistry.d.ts +29 -0
- package/dist/utils/BoundedRegistry.js +54 -0
- package/dist/utils/embedding.js +20 -3
- package/dist/utils/hybridModelManager.js +10 -5
- package/dist/utils/metadataFilter.d.ts +33 -19
- package/dist/utils/metadataFilter.js +58 -23
- package/dist/utils/metadataIndex.d.ts +37 -6
- package/dist/utils/metadataIndex.js +427 -64
- package/dist/utils/requestDeduplicator.d.ts +10 -0
- package/dist/utils/requestDeduplicator.js +24 -0
- package/dist/utils/unifiedCache.d.ts +103 -0
- package/dist/utils/unifiedCache.js +311 -0
- package/package.json +43 -128
- package/scripts/ensure-models.js +108 -0
- package/scripts/prepare-models.js +387 -0
- package/OFFLINE_MODELS.md +0 -56
- package/dist/intelligence/neuralEngine.d.ts +0 -207
- package/dist/intelligence/neuralEngine.js +0 -706
- package/dist/utils/modelLoader.d.ts +0 -32
- package/dist/utils/modelLoader.js +0 -219
- package/dist/utils/modelManager.d.ts +0 -77
- package/dist/utils/modelManager.js +0 -219
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity Registry Augmentation
|
|
3
|
+
* Fast external-ID to internal-UUID mapping for streaming data processing
|
|
4
|
+
* Works in write-only mode for high-performance deduplication
|
|
5
|
+
*/
|
|
6
|
+
import { BaseAugmentation } from './brainyAugmentation.js';
|
|
7
|
+
/**
|
|
8
|
+
* High-performance entity registry for external ID to Brainy UUID mapping
|
|
9
|
+
* Optimized for streaming data scenarios like Bluesky firehose processing
|
|
10
|
+
*/
|
|
11
|
+
export class EntityRegistryAugmentation extends BaseAugmentation {
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
super();
|
|
14
|
+
this.name = 'entity-registry';
|
|
15
|
+
this.description = 'Fast external-ID to internal-UUID mapping for streaming data';
|
|
16
|
+
this.timing = 'before';
|
|
17
|
+
this.operations = ['add', 'addNoun', 'addVerb'];
|
|
18
|
+
this.priority = 90; // High priority for entity registration
|
|
19
|
+
this.memoryIndex = new Map();
|
|
20
|
+
this.fieldIndices = new Map(); // field -> value -> brainyId
|
|
21
|
+
this.config = {
|
|
22
|
+
maxCacheSize: config.maxCacheSize ?? 100000,
|
|
23
|
+
cacheTTL: config.cacheTTL ?? 300000, // 5 minutes
|
|
24
|
+
indexedFields: config.indexedFields ?? ['did', 'handle', 'uri', 'id', 'external_id'],
|
|
25
|
+
persistence: config.persistence ?? 'hybrid',
|
|
26
|
+
syncInterval: config.syncInterval ?? 30000 // 30 seconds
|
|
27
|
+
};
|
|
28
|
+
// Initialize field indices
|
|
29
|
+
for (const field of this.config.indexedFields) {
|
|
30
|
+
this.fieldIndices.set(field, new Map());
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async initialize(context) {
|
|
34
|
+
this.brain = context.brain;
|
|
35
|
+
this.storage = context.storage;
|
|
36
|
+
// Load existing mappings from storage
|
|
37
|
+
if (this.config.persistence === 'storage' || this.config.persistence === 'hybrid') {
|
|
38
|
+
await this.loadFromStorage();
|
|
39
|
+
}
|
|
40
|
+
// Start sync timer for hybrid mode
|
|
41
|
+
if (this.config.persistence === 'hybrid') {
|
|
42
|
+
this.syncTimer = setInterval(() => {
|
|
43
|
+
this.syncToStorage().catch(console.error);
|
|
44
|
+
}, this.config.syncInterval);
|
|
45
|
+
}
|
|
46
|
+
console.log(`🔍 EntityRegistry initialized: ${this.memoryIndex.size} cached mappings`);
|
|
47
|
+
}
|
|
48
|
+
async shutdown() {
|
|
49
|
+
// Final sync before shutdown
|
|
50
|
+
if (this.config.persistence === 'storage' || this.config.persistence === 'hybrid') {
|
|
51
|
+
await this.syncToStorage();
|
|
52
|
+
}
|
|
53
|
+
if (this.syncTimer) {
|
|
54
|
+
clearInterval(this.syncTimer);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Execute the augmentation
|
|
59
|
+
*/
|
|
60
|
+
async execute(operation, params, next) {
|
|
61
|
+
console.log(`🔍 [EntityRegistry] execute called: operation=${operation}`);
|
|
62
|
+
// For add operations, check for duplicates first
|
|
63
|
+
if (operation === 'add' || operation === 'addNoun') {
|
|
64
|
+
const metadata = params.metadata || {};
|
|
65
|
+
// Check if entity already exists
|
|
66
|
+
for (const field of this.config.indexedFields) {
|
|
67
|
+
const value = this.extractFieldValue(metadata, field);
|
|
68
|
+
if (value) {
|
|
69
|
+
const existingId = await this.lookupEntity(field, value);
|
|
70
|
+
if (existingId) {
|
|
71
|
+
// Entity already exists, return the existing one
|
|
72
|
+
console.log(`🔍 Duplicate detected: ${field}:${value} → ${existingId}`);
|
|
73
|
+
return { id: existingId, duplicate: true };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// For addVerb operations, resolve external IDs to internal UUIDs
|
|
79
|
+
if (operation === 'addVerb') {
|
|
80
|
+
const sourceId = params.sourceId;
|
|
81
|
+
const targetId = params.targetId;
|
|
82
|
+
// Try to resolve source and target IDs if they look like external IDs
|
|
83
|
+
for (const field of this.config.indexedFields) {
|
|
84
|
+
// Check if sourceId matches an external ID pattern
|
|
85
|
+
if (typeof sourceId === 'string' && this.looksLikeExternalId(sourceId, field)) {
|
|
86
|
+
const resolvedSourceId = await this.lookupEntity(field, sourceId);
|
|
87
|
+
if (resolvedSourceId) {
|
|
88
|
+
console.log(`🔍 [EntityRegistry] Resolved source: ${sourceId} → ${resolvedSourceId}`);
|
|
89
|
+
params.sourceId = resolvedSourceId;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Check if targetId matches an external ID pattern
|
|
93
|
+
if (typeof targetId === 'string' && this.looksLikeExternalId(targetId, field)) {
|
|
94
|
+
const resolvedTargetId = await this.lookupEntity(field, targetId);
|
|
95
|
+
if (resolvedTargetId) {
|
|
96
|
+
console.log(`🔍 [EntityRegistry] Resolved target: ${targetId} → ${resolvedTargetId}`);
|
|
97
|
+
params.targetId = resolvedTargetId;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Proceed with the operation
|
|
103
|
+
const result = await next();
|
|
104
|
+
// Register the entity after successful add
|
|
105
|
+
if ((operation === 'add' || operation === 'addNoun' || operation === 'addVerb') && result) {
|
|
106
|
+
// Handle both formats: string UUID or object with id property
|
|
107
|
+
const brainyId = typeof result === 'string' ? result : result.id;
|
|
108
|
+
if (brainyId) {
|
|
109
|
+
const metadata = params.metadata || {};
|
|
110
|
+
const nounType = params.nounType || 'default';
|
|
111
|
+
console.log(`🔍 [EntityRegistry] Registering entity: ${brainyId}`);
|
|
112
|
+
await this.registerEntity(brainyId, metadata, nounType);
|
|
113
|
+
console.log(`✅ [EntityRegistry] Entity registered successfully`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Register a new entity mapping
|
|
120
|
+
*/
|
|
121
|
+
async registerEntity(brainyId, metadata, nounType) {
|
|
122
|
+
const now = Date.now();
|
|
123
|
+
// Extract indexed fields from metadata
|
|
124
|
+
for (const field of this.config.indexedFields) {
|
|
125
|
+
const value = this.extractFieldValue(metadata, field);
|
|
126
|
+
if (value) {
|
|
127
|
+
const key = `${field}:${value}`;
|
|
128
|
+
// Add to memory index
|
|
129
|
+
const mapping = {
|
|
130
|
+
externalId: value,
|
|
131
|
+
field,
|
|
132
|
+
brainyId,
|
|
133
|
+
nounType,
|
|
134
|
+
lastAccessed: now,
|
|
135
|
+
metadata
|
|
136
|
+
};
|
|
137
|
+
this.memoryIndex.set(key, mapping);
|
|
138
|
+
// Add to field-specific index
|
|
139
|
+
const fieldIndex = this.fieldIndices.get(field);
|
|
140
|
+
if (fieldIndex) {
|
|
141
|
+
fieldIndex.set(value, brainyId);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Enforce cache size limit (LRU eviction)
|
|
146
|
+
await this.evictOldEntries();
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Fast lookup: external ID → Brainy UUID
|
|
150
|
+
* Works in write-only mode without search indexes
|
|
151
|
+
*/
|
|
152
|
+
async lookupEntity(field, value) {
|
|
153
|
+
const key = `${field}:${value}`;
|
|
154
|
+
const cached = this.memoryIndex.get(key);
|
|
155
|
+
if (cached) {
|
|
156
|
+
// Update last accessed time
|
|
157
|
+
cached.lastAccessed = Date.now();
|
|
158
|
+
return cached.brainyId;
|
|
159
|
+
}
|
|
160
|
+
// If not in cache and using storage persistence, try loading from storage
|
|
161
|
+
if (this.config.persistence === 'storage' || this.config.persistence === 'hybrid') {
|
|
162
|
+
const stored = await this.loadFromStorageByField(field, value);
|
|
163
|
+
if (stored) {
|
|
164
|
+
// Add to memory cache
|
|
165
|
+
this.memoryIndex.set(key, stored);
|
|
166
|
+
const fieldIndex = this.fieldIndices.get(field);
|
|
167
|
+
if (fieldIndex) {
|
|
168
|
+
fieldIndex.set(value, stored.brainyId);
|
|
169
|
+
}
|
|
170
|
+
return stored.brainyId;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Batch lookup for multiple external IDs
|
|
177
|
+
*/
|
|
178
|
+
async lookupBatch(lookups) {
|
|
179
|
+
const results = new Map();
|
|
180
|
+
const missingKeys = [];
|
|
181
|
+
// Check memory cache first
|
|
182
|
+
for (const lookup of lookups) {
|
|
183
|
+
const key = `${lookup.field}:${lookup.value}`;
|
|
184
|
+
const cached = this.memoryIndex.get(key);
|
|
185
|
+
if (cached) {
|
|
186
|
+
cached.lastAccessed = Date.now();
|
|
187
|
+
results.set(key, cached.brainyId);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
missingKeys.push({ ...lookup, key });
|
|
191
|
+
results.set(key, null);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// Batch load missing keys from storage
|
|
195
|
+
if (missingKeys.length > 0 && (this.config.persistence === 'storage' || this.config.persistence === 'hybrid')) {
|
|
196
|
+
const stored = await this.loadBatchFromStorage(missingKeys);
|
|
197
|
+
for (const [key, mapping] of stored) {
|
|
198
|
+
if (mapping) {
|
|
199
|
+
// Add to memory cache
|
|
200
|
+
this.memoryIndex.set(key, mapping);
|
|
201
|
+
const fieldIndex = this.fieldIndices.get(mapping.field);
|
|
202
|
+
if (fieldIndex) {
|
|
203
|
+
fieldIndex.set(mapping.externalId, mapping.brainyId);
|
|
204
|
+
}
|
|
205
|
+
results.set(key, mapping.brainyId);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return results;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Check if entity exists (faster than lookupEntity for existence checks)
|
|
213
|
+
*/
|
|
214
|
+
async hasEntity(field, value) {
|
|
215
|
+
const fieldIndex = this.fieldIndices.get(field);
|
|
216
|
+
if (fieldIndex && fieldIndex.has(value)) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
return (await this.lookupEntity(field, value)) !== null;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get all entities by field (e.g., all DIDs)
|
|
223
|
+
*/
|
|
224
|
+
async getEntitiesByField(field) {
|
|
225
|
+
const fieldIndex = this.fieldIndices.get(field);
|
|
226
|
+
return fieldIndex ? Array.from(fieldIndex.keys()) : [];
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get registry statistics
|
|
230
|
+
*/
|
|
231
|
+
getStats() {
|
|
232
|
+
const fieldCounts = {};
|
|
233
|
+
for (const [field, index] of this.fieldIndices) {
|
|
234
|
+
fieldCounts[field] = index.size;
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
totalMappings: this.memoryIndex.size,
|
|
238
|
+
fieldCounts,
|
|
239
|
+
cacheHitRate: 0.95, // TODO: Implement actual hit rate tracking
|
|
240
|
+
memoryUsage: this.estimateMemoryUsage()
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Clear all cached mappings
|
|
245
|
+
*/
|
|
246
|
+
async clearCache() {
|
|
247
|
+
this.memoryIndex.clear();
|
|
248
|
+
for (const fieldIndex of this.fieldIndices.values()) {
|
|
249
|
+
fieldIndex.clear();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
// Private helper methods
|
|
253
|
+
/**
|
|
254
|
+
* Check if an ID looks like it could be an external ID for a specific field
|
|
255
|
+
*/
|
|
256
|
+
looksLikeExternalId(id, field) {
|
|
257
|
+
// Basic heuristics to detect external ID patterns
|
|
258
|
+
switch (field) {
|
|
259
|
+
case 'did':
|
|
260
|
+
return id.startsWith('did:');
|
|
261
|
+
case 'handle':
|
|
262
|
+
return id.includes('.') && (id.includes('bsky') || id.includes('social'));
|
|
263
|
+
case 'external_id':
|
|
264
|
+
return !id.match(/^[a-f0-9-]{36}$/i); // Not a UUID
|
|
265
|
+
case 'uri':
|
|
266
|
+
return id.startsWith('http') || id.startsWith('at://');
|
|
267
|
+
case 'id':
|
|
268
|
+
return !id.match(/^[a-f0-9-]{36}$/i); // Not a UUID
|
|
269
|
+
default:
|
|
270
|
+
// For custom fields, assume non-UUID strings might be external IDs
|
|
271
|
+
return typeof id === 'string' && id.length > 3 && !id.match(/^[a-f0-9-]{36}$/i);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
extractFieldValue(metadata, field) {
|
|
275
|
+
if (!metadata)
|
|
276
|
+
return null;
|
|
277
|
+
// Support nested field access (e.g., "author.did")
|
|
278
|
+
const parts = field.split('.');
|
|
279
|
+
let value = metadata;
|
|
280
|
+
for (const part of parts) {
|
|
281
|
+
value = value?.[part];
|
|
282
|
+
if (value === undefined || value === null) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return typeof value === 'string' ? value : String(value);
|
|
287
|
+
}
|
|
288
|
+
async evictOldEntries() {
|
|
289
|
+
if (this.memoryIndex.size <= this.config.maxCacheSize) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
// Sort by last accessed time and remove oldest entries
|
|
293
|
+
const entries = Array.from(this.memoryIndex.entries());
|
|
294
|
+
entries.sort(([, a], [, b]) => a.lastAccessed - b.lastAccessed);
|
|
295
|
+
const toRemove = entries.slice(0, entries.length - this.config.maxCacheSize);
|
|
296
|
+
for (const [key, mapping] of toRemove) {
|
|
297
|
+
this.memoryIndex.delete(key);
|
|
298
|
+
const fieldIndex = this.fieldIndices.get(mapping.field);
|
|
299
|
+
if (fieldIndex) {
|
|
300
|
+
fieldIndex.delete(mapping.externalId);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
async loadFromStorage() {
|
|
305
|
+
if (!this.brain)
|
|
306
|
+
return;
|
|
307
|
+
try {
|
|
308
|
+
// Load registry data from a special storage location
|
|
309
|
+
const registryData = await this.brain.storage?.getMetadata('__entity_registry__');
|
|
310
|
+
if (registryData && registryData.mappings) {
|
|
311
|
+
for (const mapping of registryData.mappings) {
|
|
312
|
+
const key = `${mapping.field}:${mapping.externalId}`;
|
|
313
|
+
this.memoryIndex.set(key, mapping);
|
|
314
|
+
const fieldIndex = this.fieldIndices.get(mapping.field);
|
|
315
|
+
if (fieldIndex) {
|
|
316
|
+
fieldIndex.set(mapping.externalId, mapping.brainyId);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
console.warn('Failed to load entity registry from storage:', error);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
async syncToStorage() {
|
|
326
|
+
if (!this.brain)
|
|
327
|
+
return;
|
|
328
|
+
try {
|
|
329
|
+
const mappings = Array.from(this.memoryIndex.values());
|
|
330
|
+
await this.brain.storage?.saveMetadata('__entity_registry__', {
|
|
331
|
+
version: 1,
|
|
332
|
+
lastSync: Date.now(),
|
|
333
|
+
mappings
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
console.warn('Failed to sync entity registry to storage:', error);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
async loadFromStorageByField(field, value) {
|
|
341
|
+
// For now, this would require a full load. In production, you'd want
|
|
342
|
+
// a more sophisticated storage index system
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
async loadBatchFromStorage(keys) {
|
|
346
|
+
// For now, return empty. In production, implement batch storage lookup
|
|
347
|
+
return new Map();
|
|
348
|
+
}
|
|
349
|
+
estimateMemoryUsage() {
|
|
350
|
+
// Rough estimate: 200 bytes per mapping on average
|
|
351
|
+
return this.memoryIndex.size * 200;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// Hook into Brainy's add operations to automatically register entities
|
|
355
|
+
export class AutoRegisterEntitiesAugmentation extends BaseAugmentation {
|
|
356
|
+
constructor() {
|
|
357
|
+
super(...arguments);
|
|
358
|
+
this.name = 'auto-register-entities';
|
|
359
|
+
this.description = 'Automatically register entities in the registry when added';
|
|
360
|
+
this.timing = 'after';
|
|
361
|
+
this.operations = ['add', 'addNoun', 'addVerb'];
|
|
362
|
+
this.priority = 85; // After entity registry
|
|
363
|
+
}
|
|
364
|
+
async initialize(context) {
|
|
365
|
+
this.brain = context.brain;
|
|
366
|
+
// Find the entity registry augmentation from the registry
|
|
367
|
+
this.registry = this.brain?.augmentations?.augmentations?.find((aug) => aug instanceof EntityRegistryAugmentation);
|
|
368
|
+
}
|
|
369
|
+
async execute(operation, params, next) {
|
|
370
|
+
const result = await next();
|
|
371
|
+
// After successful add, register the entity
|
|
372
|
+
if ((operation === 'add' || operation === 'addNoun' || operation === 'addVerb') && result) {
|
|
373
|
+
if (this.registry) {
|
|
374
|
+
// Handle both formats: string UUID or object with id property
|
|
375
|
+
const brainyId = typeof result === 'string' ? result : result.id;
|
|
376
|
+
if (brainyId) {
|
|
377
|
+
const metadata = params.metadata || {};
|
|
378
|
+
const nounType = params.nounType || 'default';
|
|
379
|
+
await this.registry.registerEntity(brainyId, metadata, nounType);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return result;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
//# sourceMappingURL=entityRegistryAugmentation.js.map
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Index Augmentation - Optional Metadata Indexing
|
|
3
|
+
*
|
|
4
|
+
* Replaces the hardcoded MetadataIndex in BrainyData with an optional augmentation.
|
|
5
|
+
* Provides O(1) metadata filtering and field lookups.
|
|
6
|
+
*
|
|
7
|
+
* Zero-config: Automatically enabled for better search performance
|
|
8
|
+
* Can be disabled or customized via augmentation registry
|
|
9
|
+
*/
|
|
10
|
+
import { BaseAugmentation } from './brainyAugmentation.js';
|
|
11
|
+
import { MetadataIndexManager } from '../utils/metadataIndex.js';
|
|
12
|
+
export interface IndexConfig {
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
maxFieldValues?: number;
|
|
15
|
+
maxIndexSize?: number;
|
|
16
|
+
autoRebuild?: boolean;
|
|
17
|
+
rebuildThreshold?: number;
|
|
18
|
+
flushInterval?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* IndexAugmentation - Makes metadata indexing optional and pluggable
|
|
22
|
+
*
|
|
23
|
+
* Features:
|
|
24
|
+
* - O(1) metadata field lookups
|
|
25
|
+
* - Fast pre-filtering for searches
|
|
26
|
+
* - Automatic index maintenance
|
|
27
|
+
* - Zero-config with smart defaults
|
|
28
|
+
*/
|
|
29
|
+
export declare class IndexAugmentation extends BaseAugmentation {
|
|
30
|
+
readonly name = "index";
|
|
31
|
+
readonly timing: "after";
|
|
32
|
+
operations: ("add" | "updateMetadata" | "delete" | "clear" | "all")[];
|
|
33
|
+
readonly priority = 60;
|
|
34
|
+
private metadataIndex;
|
|
35
|
+
private config;
|
|
36
|
+
private flushTimer;
|
|
37
|
+
constructor(config?: IndexConfig);
|
|
38
|
+
protected onInitialize(): Promise<void>;
|
|
39
|
+
protected onShutdown(): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Execute augmentation - maintain index on data operations
|
|
42
|
+
*/
|
|
43
|
+
execute<T = any>(operation: string, params: any, next: () => Promise<T>): Promise<T>;
|
|
44
|
+
/**
|
|
45
|
+
* Handle add operation - index new metadata
|
|
46
|
+
*/
|
|
47
|
+
private handleAdd;
|
|
48
|
+
/**
|
|
49
|
+
* Handle update operation - reindex metadata
|
|
50
|
+
*/
|
|
51
|
+
private handleUpdate;
|
|
52
|
+
/**
|
|
53
|
+
* Handle delete operation - remove from index
|
|
54
|
+
*/
|
|
55
|
+
private handleDelete;
|
|
56
|
+
/**
|
|
57
|
+
* Handle clear operation - clear index
|
|
58
|
+
*/
|
|
59
|
+
private handleClear;
|
|
60
|
+
/**
|
|
61
|
+
* Start periodic flush timer
|
|
62
|
+
*/
|
|
63
|
+
private startFlushTimer;
|
|
64
|
+
/**
|
|
65
|
+
* Get IDs that match metadata filter (for pre-filtering)
|
|
66
|
+
*/
|
|
67
|
+
getIdsForFilter(filter: Record<string, any>): Promise<string[]>;
|
|
68
|
+
/**
|
|
69
|
+
* Get available values for a field
|
|
70
|
+
*/
|
|
71
|
+
getFilterValues(field: string): Promise<any[]>;
|
|
72
|
+
/**
|
|
73
|
+
* Get all indexed fields
|
|
74
|
+
*/
|
|
75
|
+
getFilterFields(): Promise<string[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Get index statistics
|
|
78
|
+
*/
|
|
79
|
+
getStats(): Promise<{
|
|
80
|
+
enabled: boolean;
|
|
81
|
+
totalEntries: number;
|
|
82
|
+
fieldsIndexed: never[];
|
|
83
|
+
memoryUsage: number;
|
|
84
|
+
} | {
|
|
85
|
+
totalEntries: number;
|
|
86
|
+
totalIds: number;
|
|
87
|
+
fieldsIndexed: string[];
|
|
88
|
+
lastRebuild: number;
|
|
89
|
+
indexSize: number;
|
|
90
|
+
enabled: boolean;
|
|
91
|
+
memoryUsage?: undefined;
|
|
92
|
+
}>;
|
|
93
|
+
/**
|
|
94
|
+
* Rebuild the index from storage
|
|
95
|
+
*/
|
|
96
|
+
rebuild(): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Flush index to storage
|
|
99
|
+
*/
|
|
100
|
+
flush(): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Add entry to index (public method for direct access)
|
|
103
|
+
*/
|
|
104
|
+
addToIndex(id: string, metadata: Record<string, any>): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Remove entry from index (public method for direct access)
|
|
107
|
+
*/
|
|
108
|
+
removeFromIndex(id: string, metadata: Record<string, any>): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Get the underlying MetadataIndexManager instance
|
|
111
|
+
*/
|
|
112
|
+
getMetadataIndex(): MetadataIndexManager | null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Factory function for zero-config index augmentation
|
|
116
|
+
*/
|
|
117
|
+
export declare function createIndexAugmentation(config?: IndexConfig): IndexAugmentation;
|