moflo 4.0.1 → 4.0.3
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/.claude/guidance/agent-bootstrap.md +12 -6
- package/bin/setup-project.mjs +201 -0
- package/package.json +114 -109
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +194 -81
- package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.js +1892 -1841
- package/v3/@claude-flow/memory/README.md +587 -0
- package/v3/@claude-flow/memory/dist/agent-memory-scope.d.ts +131 -0
- package/v3/@claude-flow/memory/dist/agent-memory-scope.js +223 -0
- package/v3/@claude-flow/memory/dist/agent-memory-scope.test.d.ts +8 -0
- package/v3/@claude-flow/memory/dist/agent-memory-scope.test.js +463 -0
- package/v3/@claude-flow/memory/dist/agentdb-adapter.d.ts +165 -0
- package/v3/@claude-flow/memory/dist/agentdb-adapter.js +806 -0
- package/v3/@claude-flow/memory/dist/agentdb-backend.d.ts +214 -0
- package/v3/@claude-flow/memory/dist/agentdb-backend.js +844 -0
- package/v3/@claude-flow/memory/dist/agentdb-backend.test.d.ts +7 -0
- package/v3/@claude-flow/memory/dist/agentdb-backend.test.js +258 -0
- package/v3/@claude-flow/memory/dist/application/commands/delete-memory.command.d.ts +65 -0
- package/v3/@claude-flow/memory/dist/application/commands/delete-memory.command.js +129 -0
- package/v3/@claude-flow/memory/dist/application/commands/store-memory.command.d.ts +48 -0
- package/v3/@claude-flow/memory/dist/application/commands/store-memory.command.js +72 -0
- package/v3/@claude-flow/memory/dist/application/index.d.ts +12 -0
- package/v3/@claude-flow/memory/dist/application/index.js +15 -0
- package/v3/@claude-flow/memory/dist/application/queries/search-memory.query.d.ts +72 -0
- package/v3/@claude-flow/memory/dist/application/queries/search-memory.query.js +143 -0
- package/v3/@claude-flow/memory/dist/application/services/memory-application-service.d.ts +121 -0
- package/v3/@claude-flow/memory/dist/application/services/memory-application-service.js +190 -0
- package/v3/@claude-flow/memory/dist/auto-memory-bridge.d.ts +226 -0
- package/v3/@claude-flow/memory/dist/auto-memory-bridge.js +709 -0
- package/v3/@claude-flow/memory/dist/auto-memory-bridge.test.d.ts +8 -0
- package/v3/@claude-flow/memory/dist/auto-memory-bridge.test.js +754 -0
- package/v3/@claude-flow/memory/dist/benchmark.test.d.ts +2 -0
- package/v3/@claude-flow/memory/dist/benchmark.test.js +277 -0
- package/v3/@claude-flow/memory/dist/cache-manager.d.ts +134 -0
- package/v3/@claude-flow/memory/dist/cache-manager.js +407 -0
- package/v3/@claude-flow/memory/dist/controller-registry.d.ts +216 -0
- package/v3/@claude-flow/memory/dist/controller-registry.js +893 -0
- package/v3/@claude-flow/memory/dist/controller-registry.test.d.ts +14 -0
- package/v3/@claude-flow/memory/dist/controller-registry.test.js +636 -0
- package/v3/@claude-flow/memory/dist/database-provider.d.ts +87 -0
- package/v3/@claude-flow/memory/dist/database-provider.js +410 -0
- package/v3/@claude-flow/memory/dist/database-provider.test.d.ts +7 -0
- package/v3/@claude-flow/memory/dist/database-provider.test.js +285 -0
- package/v3/@claude-flow/memory/dist/domain/entities/memory-entry.d.ts +143 -0
- package/v3/@claude-flow/memory/dist/domain/entities/memory-entry.js +226 -0
- package/v3/@claude-flow/memory/dist/domain/index.d.ts +11 -0
- package/v3/@claude-flow/memory/dist/domain/index.js +12 -0
- package/v3/@claude-flow/memory/dist/domain/repositories/memory-repository.interface.d.ts +102 -0
- package/v3/@claude-flow/memory/dist/domain/repositories/memory-repository.interface.js +11 -0
- package/v3/@claude-flow/memory/dist/domain/services/memory-domain-service.d.ts +105 -0
- package/v3/@claude-flow/memory/dist/domain/services/memory-domain-service.js +297 -0
- package/v3/@claude-flow/memory/dist/hnsw-index.d.ts +111 -0
- package/v3/@claude-flow/memory/dist/hnsw-index.js +781 -0
- package/v3/@claude-flow/memory/dist/hnsw-lite.d.ts +23 -0
- package/v3/@claude-flow/memory/dist/hnsw-lite.js +168 -0
- package/v3/@claude-flow/memory/dist/hybrid-backend.d.ts +245 -0
- package/v3/@claude-flow/memory/dist/hybrid-backend.js +569 -0
- package/v3/@claude-flow/memory/dist/hybrid-backend.test.d.ts +8 -0
- package/v3/@claude-flow/memory/dist/hybrid-backend.test.js +320 -0
- package/v3/@claude-flow/memory/dist/index.d.ts +208 -0
- package/v3/@claude-flow/memory/dist/index.js +362 -0
- package/v3/@claude-flow/memory/dist/infrastructure/index.d.ts +17 -0
- package/v3/@claude-flow/memory/dist/infrastructure/index.js +16 -0
- package/v3/@claude-flow/memory/dist/infrastructure/repositories/hybrid-memory-repository.d.ts +66 -0
- package/v3/@claude-flow/memory/dist/infrastructure/repositories/hybrid-memory-repository.js +409 -0
- package/v3/@claude-flow/memory/dist/learning-bridge.d.ts +137 -0
- package/v3/@claude-flow/memory/dist/learning-bridge.js +335 -0
- package/v3/@claude-flow/memory/dist/learning-bridge.test.d.ts +8 -0
- package/v3/@claude-flow/memory/dist/learning-bridge.test.js +578 -0
- package/v3/@claude-flow/memory/dist/memory-graph.d.ts +100 -0
- package/v3/@claude-flow/memory/dist/memory-graph.js +333 -0
- package/v3/@claude-flow/memory/dist/memory-graph.test.d.ts +8 -0
- package/v3/@claude-flow/memory/dist/memory-graph.test.js +609 -0
- package/v3/@claude-flow/memory/dist/migration.d.ts +68 -0
- package/v3/@claude-flow/memory/dist/migration.js +513 -0
- package/v3/@claude-flow/memory/dist/persistent-sona.d.ts +144 -0
- package/v3/@claude-flow/memory/dist/persistent-sona.js +332 -0
- package/v3/@claude-flow/memory/dist/query-builder.d.ts +211 -0
- package/v3/@claude-flow/memory/dist/query-builder.js +438 -0
- package/v3/@claude-flow/memory/dist/rvf-backend.d.ts +51 -0
- package/v3/@claude-flow/memory/dist/rvf-backend.js +481 -0
- package/v3/@claude-flow/memory/dist/rvf-learning-store.d.ts +139 -0
- package/v3/@claude-flow/memory/dist/rvf-learning-store.js +295 -0
- package/v3/@claude-flow/memory/dist/rvf-migration.d.ts +45 -0
- package/v3/@claude-flow/memory/dist/rvf-migration.js +254 -0
- package/v3/@claude-flow/memory/dist/sqlite-backend.d.ts +121 -0
- package/v3/@claude-flow/memory/dist/sqlite-backend.js +564 -0
- package/v3/@claude-flow/memory/dist/sqljs-backend.d.ts +128 -0
- package/v3/@claude-flow/memory/dist/sqljs-backend.js +601 -0
- package/v3/@claude-flow/memory/dist/types.d.ts +484 -0
- package/v3/@claude-flow/memory/dist/types.js +58 -0
- package/v3/@claude-flow/memory/package.json +46 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V3 Cache Manager
|
|
3
|
+
*
|
|
4
|
+
* High-performance LRU cache with TTL support, memory pressure handling,
|
|
5
|
+
* and write-through caching for the unified memory system.
|
|
6
|
+
*
|
|
7
|
+
* @module v3/memory/cache-manager
|
|
8
|
+
*/
|
|
9
|
+
import { EventEmitter } from 'node:events';
|
|
10
|
+
/**
|
|
11
|
+
* High-performance LRU Cache with TTL support
|
|
12
|
+
*
|
|
13
|
+
* Features:
|
|
14
|
+
* - O(1) get, set, delete operations
|
|
15
|
+
* - LRU eviction policy
|
|
16
|
+
* - TTL-based expiration
|
|
17
|
+
* - Memory pressure handling
|
|
18
|
+
* - Write-through caching support
|
|
19
|
+
* - Performance statistics
|
|
20
|
+
*/
|
|
21
|
+
export class CacheManager extends EventEmitter {
|
|
22
|
+
config;
|
|
23
|
+
cache = new Map();
|
|
24
|
+
head = null;
|
|
25
|
+
tail = null;
|
|
26
|
+
currentMemory = 0;
|
|
27
|
+
// Statistics
|
|
28
|
+
stats = {
|
|
29
|
+
hits: 0,
|
|
30
|
+
misses: 0,
|
|
31
|
+
evictions: 0,
|
|
32
|
+
expirations: 0,
|
|
33
|
+
writes: 0,
|
|
34
|
+
};
|
|
35
|
+
// Cleanup timer
|
|
36
|
+
cleanupInterval = null;
|
|
37
|
+
constructor(config = {}) {
|
|
38
|
+
super();
|
|
39
|
+
this.config = this.mergeConfig(config);
|
|
40
|
+
this.startCleanupTimer();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get a value from the cache
|
|
44
|
+
*/
|
|
45
|
+
get(key) {
|
|
46
|
+
const node = this.cache.get(key);
|
|
47
|
+
if (!node) {
|
|
48
|
+
this.stats.misses++;
|
|
49
|
+
this.emit('cache:miss', { key });
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
// Check if expired
|
|
53
|
+
if (this.isExpired(node.value)) {
|
|
54
|
+
this.delete(key);
|
|
55
|
+
this.stats.misses++;
|
|
56
|
+
this.stats.expirations++;
|
|
57
|
+
this.emit('cache:expired', { key });
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
// Update access time and count
|
|
61
|
+
node.value.lastAccessedAt = Date.now();
|
|
62
|
+
node.value.accessCount++;
|
|
63
|
+
// Move to front (most recently used)
|
|
64
|
+
this.moveToFront(node);
|
|
65
|
+
this.stats.hits++;
|
|
66
|
+
this.emit('cache:hit', { key });
|
|
67
|
+
return node.value.data;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Set a value in the cache
|
|
71
|
+
*/
|
|
72
|
+
set(key, data, ttl) {
|
|
73
|
+
const now = Date.now();
|
|
74
|
+
const entryTtl = ttl || this.config.ttl;
|
|
75
|
+
// Check if key already exists
|
|
76
|
+
const existingNode = this.cache.get(key);
|
|
77
|
+
if (existingNode) {
|
|
78
|
+
// Update existing entry
|
|
79
|
+
existingNode.value.data = data;
|
|
80
|
+
existingNode.value.cachedAt = now;
|
|
81
|
+
existingNode.value.expiresAt = now + entryTtl;
|
|
82
|
+
existingNode.value.lastAccessedAt = now;
|
|
83
|
+
this.moveToFront(existingNode);
|
|
84
|
+
this.stats.writes++;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Calculate memory for new entry
|
|
88
|
+
const entryMemory = this.estimateSize(data);
|
|
89
|
+
// Evict entries if needed for memory pressure
|
|
90
|
+
if (this.config.maxMemory) {
|
|
91
|
+
while (this.currentMemory + entryMemory > this.config.maxMemory &&
|
|
92
|
+
this.cache.size > 0) {
|
|
93
|
+
this.evictLRU();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Evict entries if at capacity
|
|
97
|
+
while (this.cache.size >= this.config.maxSize) {
|
|
98
|
+
this.evictLRU();
|
|
99
|
+
}
|
|
100
|
+
// Create new node
|
|
101
|
+
const cachedEntry = {
|
|
102
|
+
data,
|
|
103
|
+
cachedAt: now,
|
|
104
|
+
expiresAt: now + entryTtl,
|
|
105
|
+
lastAccessedAt: now,
|
|
106
|
+
accessCount: 0,
|
|
107
|
+
};
|
|
108
|
+
const node = {
|
|
109
|
+
key,
|
|
110
|
+
value: cachedEntry,
|
|
111
|
+
prev: null,
|
|
112
|
+
next: null,
|
|
113
|
+
};
|
|
114
|
+
// Add to cache
|
|
115
|
+
this.cache.set(key, node);
|
|
116
|
+
this.addToFront(node);
|
|
117
|
+
this.currentMemory += entryMemory;
|
|
118
|
+
this.stats.writes++;
|
|
119
|
+
this.emit('cache:set', { key, ttl: entryTtl });
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Delete a value from the cache
|
|
123
|
+
*/
|
|
124
|
+
delete(key) {
|
|
125
|
+
const node = this.cache.get(key);
|
|
126
|
+
if (!node) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
this.removeNode(node);
|
|
130
|
+
this.cache.delete(key);
|
|
131
|
+
this.currentMemory -= this.estimateSize(node.value.data);
|
|
132
|
+
this.emit('cache:delete', { key });
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Check if a key exists in the cache (without affecting LRU order)
|
|
137
|
+
*/
|
|
138
|
+
has(key) {
|
|
139
|
+
const node = this.cache.get(key);
|
|
140
|
+
if (!node)
|
|
141
|
+
return false;
|
|
142
|
+
if (this.isExpired(node.value)) {
|
|
143
|
+
this.delete(key);
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Clear all entries from the cache
|
|
150
|
+
*/
|
|
151
|
+
clear() {
|
|
152
|
+
this.cache.clear();
|
|
153
|
+
this.head = null;
|
|
154
|
+
this.tail = null;
|
|
155
|
+
this.currentMemory = 0;
|
|
156
|
+
this.emit('cache:cleared', { previousSize: this.cache.size });
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get cache statistics
|
|
160
|
+
*/
|
|
161
|
+
getStats() {
|
|
162
|
+
const total = this.stats.hits + this.stats.misses;
|
|
163
|
+
return {
|
|
164
|
+
size: this.cache.size,
|
|
165
|
+
hitRate: total > 0 ? this.stats.hits / total : 0,
|
|
166
|
+
hits: this.stats.hits,
|
|
167
|
+
misses: this.stats.misses,
|
|
168
|
+
evictions: this.stats.evictions,
|
|
169
|
+
memoryUsage: this.currentMemory,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get all keys in the cache
|
|
174
|
+
*/
|
|
175
|
+
keys() {
|
|
176
|
+
return Array.from(this.cache.keys());
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get the size of the cache
|
|
180
|
+
*/
|
|
181
|
+
get size() {
|
|
182
|
+
return this.cache.size;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Prefetch multiple keys in a single batch
|
|
186
|
+
*/
|
|
187
|
+
async prefetch(keys, loader, ttl) {
|
|
188
|
+
const missing = keys.filter((key) => !this.has(key));
|
|
189
|
+
if (missing.length === 0) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const data = await loader(missing);
|
|
193
|
+
for (const [key, value] of data) {
|
|
194
|
+
this.set(key, value, ttl);
|
|
195
|
+
}
|
|
196
|
+
this.emit('cache:prefetched', { keys: missing.length });
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get or set pattern - get from cache or load and cache
|
|
200
|
+
*/
|
|
201
|
+
async getOrSet(key, loader, ttl) {
|
|
202
|
+
const cached = this.get(key);
|
|
203
|
+
if (cached !== null) {
|
|
204
|
+
return cached;
|
|
205
|
+
}
|
|
206
|
+
const data = await loader();
|
|
207
|
+
this.set(key, data, ttl);
|
|
208
|
+
return data;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Warm the cache with initial data
|
|
212
|
+
*/
|
|
213
|
+
warmUp(entries) {
|
|
214
|
+
for (const entry of entries) {
|
|
215
|
+
this.set(entry.key, entry.data, entry.ttl);
|
|
216
|
+
}
|
|
217
|
+
this.emit('cache:warmedUp', { count: entries.length });
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Invalidate entries matching a pattern
|
|
221
|
+
*/
|
|
222
|
+
invalidatePattern(pattern) {
|
|
223
|
+
const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;
|
|
224
|
+
let invalidated = 0;
|
|
225
|
+
for (const key of this.cache.keys()) {
|
|
226
|
+
if (regex.test(key)) {
|
|
227
|
+
this.delete(key);
|
|
228
|
+
invalidated++;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
this.emit('cache:invalidated', { pattern: pattern.toString(), count: invalidated });
|
|
232
|
+
return invalidated;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Shutdown the cache manager
|
|
236
|
+
*/
|
|
237
|
+
shutdown() {
|
|
238
|
+
if (this.cleanupInterval) {
|
|
239
|
+
clearInterval(this.cleanupInterval);
|
|
240
|
+
this.cleanupInterval = null;
|
|
241
|
+
}
|
|
242
|
+
this.clear();
|
|
243
|
+
this.emit('cache:shutdown');
|
|
244
|
+
}
|
|
245
|
+
// ===== Private Methods =====
|
|
246
|
+
mergeConfig(config) {
|
|
247
|
+
return {
|
|
248
|
+
maxSize: config.maxSize || 10000,
|
|
249
|
+
ttl: config.ttl || 300000, // 5 minutes default
|
|
250
|
+
lruEnabled: config.lruEnabled !== false,
|
|
251
|
+
maxMemory: config.maxMemory,
|
|
252
|
+
writeThrough: config.writeThrough || false,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
isExpired(entry) {
|
|
256
|
+
return Date.now() > entry.expiresAt;
|
|
257
|
+
}
|
|
258
|
+
estimateSize(data) {
|
|
259
|
+
try {
|
|
260
|
+
return JSON.stringify(data).length * 2; // Rough UTF-16 estimate
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
return 1000; // Default for non-serializable objects
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
addToFront(node) {
|
|
267
|
+
node.prev = null;
|
|
268
|
+
node.next = this.head;
|
|
269
|
+
if (this.head) {
|
|
270
|
+
this.head.prev = node;
|
|
271
|
+
}
|
|
272
|
+
this.head = node;
|
|
273
|
+
if (!this.tail) {
|
|
274
|
+
this.tail = node;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
removeNode(node) {
|
|
278
|
+
if (node.prev) {
|
|
279
|
+
node.prev.next = node.next;
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
this.head = node.next;
|
|
283
|
+
}
|
|
284
|
+
if (node.next) {
|
|
285
|
+
node.next.prev = node.prev;
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
this.tail = node.prev;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
moveToFront(node) {
|
|
292
|
+
if (node === this.head)
|
|
293
|
+
return;
|
|
294
|
+
this.removeNode(node);
|
|
295
|
+
this.addToFront(node);
|
|
296
|
+
}
|
|
297
|
+
evictLRU() {
|
|
298
|
+
if (!this.tail)
|
|
299
|
+
return;
|
|
300
|
+
const evictedKey = this.tail.key;
|
|
301
|
+
const evictedSize = this.estimateSize(this.tail.value.data);
|
|
302
|
+
this.removeNode(this.tail);
|
|
303
|
+
this.cache.delete(evictedKey);
|
|
304
|
+
this.currentMemory -= evictedSize;
|
|
305
|
+
this.stats.evictions++;
|
|
306
|
+
this.emit('cache:eviction', { key: evictedKey });
|
|
307
|
+
}
|
|
308
|
+
startCleanupTimer() {
|
|
309
|
+
// Clean up expired entries every minute
|
|
310
|
+
this.cleanupInterval = setInterval(() => {
|
|
311
|
+
this.cleanupExpired();
|
|
312
|
+
}, 60000);
|
|
313
|
+
}
|
|
314
|
+
cleanupExpired() {
|
|
315
|
+
const now = Date.now();
|
|
316
|
+
let cleaned = 0;
|
|
317
|
+
for (const [key, node] of this.cache) {
|
|
318
|
+
if (node.value.expiresAt < now) {
|
|
319
|
+
this.delete(key);
|
|
320
|
+
cleaned++;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (cleaned > 0) {
|
|
324
|
+
this.emit('cache:cleanup', { expired: cleaned });
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Multi-layer cache with L1 (memory) and L2 (storage) tiers
|
|
330
|
+
*/
|
|
331
|
+
export class TieredCacheManager extends EventEmitter {
|
|
332
|
+
l1Cache;
|
|
333
|
+
l2Loader = null;
|
|
334
|
+
l2Writer = null;
|
|
335
|
+
constructor(l1Config = {}, l2Options) {
|
|
336
|
+
super();
|
|
337
|
+
this.l1Cache = new CacheManager(l1Config);
|
|
338
|
+
if (l2Options) {
|
|
339
|
+
this.l2Loader = l2Options.loader;
|
|
340
|
+
this.l2Writer = l2Options.writer ?? null;
|
|
341
|
+
}
|
|
342
|
+
// Forward L1 events
|
|
343
|
+
this.l1Cache.on('cache:hit', (data) => this.emit('l1:hit', data));
|
|
344
|
+
this.l1Cache.on('cache:miss', (data) => this.emit('l1:miss', data));
|
|
345
|
+
this.l1Cache.on('cache:eviction', (data) => this.emit('l1:eviction', data));
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Get from tiered cache
|
|
349
|
+
*/
|
|
350
|
+
async get(key) {
|
|
351
|
+
// Try L1 first
|
|
352
|
+
const l1Result = this.l1Cache.get(key);
|
|
353
|
+
if (l1Result !== null) {
|
|
354
|
+
return l1Result;
|
|
355
|
+
}
|
|
356
|
+
// Try L2 if available
|
|
357
|
+
if (this.l2Loader) {
|
|
358
|
+
const l2Result = await this.l2Loader(key);
|
|
359
|
+
if (l2Result !== null) {
|
|
360
|
+
// Promote to L1
|
|
361
|
+
this.l1Cache.set(key, l2Result);
|
|
362
|
+
this.emit('l2:hit', { key });
|
|
363
|
+
return l2Result;
|
|
364
|
+
}
|
|
365
|
+
this.emit('l2:miss', { key });
|
|
366
|
+
}
|
|
367
|
+
return null;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Set in tiered cache
|
|
371
|
+
*/
|
|
372
|
+
async set(key, value, ttl) {
|
|
373
|
+
// Write to L1
|
|
374
|
+
this.l1Cache.set(key, value, ttl);
|
|
375
|
+
// Write-through to L2 if configured
|
|
376
|
+
if (this.l2Writer) {
|
|
377
|
+
await this.l2Writer(key, value);
|
|
378
|
+
this.emit('l2:write', { key });
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Delete from tiered cache
|
|
383
|
+
*/
|
|
384
|
+
delete(key) {
|
|
385
|
+
return this.l1Cache.delete(key);
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Get L1 cache statistics
|
|
389
|
+
*/
|
|
390
|
+
getStats() {
|
|
391
|
+
return this.l1Cache.getStats();
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Clear L1 cache
|
|
395
|
+
*/
|
|
396
|
+
clear() {
|
|
397
|
+
this.l1Cache.clear();
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Shutdown tiered cache
|
|
401
|
+
*/
|
|
402
|
+
shutdown() {
|
|
403
|
+
this.l1Cache.shutdown();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
export default CacheManager;
|
|
407
|
+
//# sourceMappingURL=cache-manager.js.map
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ControllerRegistry - Central controller lifecycle management for AgentDB v3
|
|
3
|
+
*
|
|
4
|
+
* Wraps the AgentDB class and adds CLI-specific controllers from @claude-flow/memory.
|
|
5
|
+
* Manages initialization (level-based ordering), health checks, and graceful shutdown.
|
|
6
|
+
*
|
|
7
|
+
* Per ADR-053: Replaces memory-initializer.js's raw sql.js usage with a unified
|
|
8
|
+
* controller ecosystem routing all memory operations through AgentDB v3.
|
|
9
|
+
*
|
|
10
|
+
* @module @claude-flow/memory/controller-registry
|
|
11
|
+
*/
|
|
12
|
+
import { EventEmitter } from 'node:events';
|
|
13
|
+
import type { IMemoryBackend, EmbeddingGenerator, SONAMode } from './types.js';
|
|
14
|
+
import type { LearningBridgeConfig } from './learning-bridge.js';
|
|
15
|
+
import type { MemoryGraphConfig } from './memory-graph.js';
|
|
16
|
+
import type { CacheConfig } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Controllers accessible via AgentDB.getController()
|
|
19
|
+
*/
|
|
20
|
+
export type AgentDBControllerName = 'reasoningBank' | 'skills' | 'reflexion' | 'causalGraph' | 'causalRecall' | 'learningSystem' | 'explainableRecall' | 'nightlyLearner' | 'graphTransformer' | 'mutationGuard' | 'attestationLog' | 'vectorBackend' | 'graphAdapter';
|
|
21
|
+
/**
|
|
22
|
+
* CLI-layer controllers (from @claude-flow/memory or new)
|
|
23
|
+
*/
|
|
24
|
+
export type CLIControllerName = 'learningBridge' | 'memoryGraph' | 'agentMemoryScope' | 'tieredCache' | 'hybridSearch' | 'federatedSession' | 'semanticRouter' | 'sonaTrajectory' | 'hierarchicalMemory' | 'memoryConsolidation' | 'batchOperations' | 'contextSynthesizer' | 'gnnService' | 'rvfOptimizer' | 'mmrDiversityRanker' | 'guardedVectorBackend';
|
|
25
|
+
/**
|
|
26
|
+
* All controller names
|
|
27
|
+
*/
|
|
28
|
+
export type ControllerName = AgentDBControllerName | CLIControllerName;
|
|
29
|
+
/**
|
|
30
|
+
* Initialization level for dependency ordering
|
|
31
|
+
*/
|
|
32
|
+
export interface InitLevel {
|
|
33
|
+
level: number;
|
|
34
|
+
controllers: ControllerName[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Individual controller health status
|
|
38
|
+
*/
|
|
39
|
+
export interface ControllerHealth {
|
|
40
|
+
name: ControllerName;
|
|
41
|
+
status: 'healthy' | 'degraded' | 'unavailable';
|
|
42
|
+
initTimeMs: number;
|
|
43
|
+
error?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Aggregated health report for all controllers
|
|
47
|
+
*/
|
|
48
|
+
export interface RegistryHealthReport {
|
|
49
|
+
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
50
|
+
controllers: ControllerHealth[];
|
|
51
|
+
agentdbAvailable: boolean;
|
|
52
|
+
initTimeMs: number;
|
|
53
|
+
timestamp: number;
|
|
54
|
+
activeControllers: number;
|
|
55
|
+
totalControllers: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Runtime configuration for controller activation
|
|
59
|
+
*/
|
|
60
|
+
export interface RuntimeConfig {
|
|
61
|
+
/** Database path for AgentDB */
|
|
62
|
+
dbPath?: string;
|
|
63
|
+
/** Vector dimension (default: 384 for MiniLM) */
|
|
64
|
+
dimension?: number;
|
|
65
|
+
/** Embedding generator function */
|
|
66
|
+
embeddingGenerator?: EmbeddingGenerator;
|
|
67
|
+
/** Memory backend config */
|
|
68
|
+
memory?: {
|
|
69
|
+
enableHNSW?: boolean;
|
|
70
|
+
learningBridge?: Partial<LearningBridgeConfig>;
|
|
71
|
+
memoryGraph?: Partial<MemoryGraphConfig>;
|
|
72
|
+
tieredCache?: Partial<CacheConfig>;
|
|
73
|
+
};
|
|
74
|
+
/** Neural config */
|
|
75
|
+
neural?: {
|
|
76
|
+
enabled?: boolean;
|
|
77
|
+
modelPath?: string;
|
|
78
|
+
sonaMode?: SONAMode;
|
|
79
|
+
};
|
|
80
|
+
/** Controllers to explicitly enable/disable */
|
|
81
|
+
controllers?: Partial<Record<ControllerName, boolean>>;
|
|
82
|
+
/** Backend instance to use (if pre-created) */
|
|
83
|
+
backend?: IMemoryBackend;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Level-based initialization order per ADR-053.
|
|
87
|
+
* Controllers at each level can be initialized in parallel.
|
|
88
|
+
* Each level must complete before the next begins.
|
|
89
|
+
*/
|
|
90
|
+
export declare const INIT_LEVELS: InitLevel[];
|
|
91
|
+
/**
|
|
92
|
+
* Central registry for AgentDB v3 controller lifecycle management.
|
|
93
|
+
*
|
|
94
|
+
* Handles:
|
|
95
|
+
* - Level-based initialization ordering (levels 0-6)
|
|
96
|
+
* - Graceful degradation (each controller fails independently)
|
|
97
|
+
* - Config-driven activation (controllers only instantiate when enabled)
|
|
98
|
+
* - Health check aggregation across all controllers
|
|
99
|
+
* - Ordered shutdown (reverse initialization order)
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const registry = new ControllerRegistry();
|
|
104
|
+
* await registry.initialize({
|
|
105
|
+
* dbPath: './data/memory.db',
|
|
106
|
+
* dimension: 384,
|
|
107
|
+
* memory: {
|
|
108
|
+
* enableHNSW: true,
|
|
109
|
+
* learningBridge: { sonaMode: 'balanced' },
|
|
110
|
+
* memoryGraph: { pageRankDamping: 0.85 },
|
|
111
|
+
* },
|
|
112
|
+
* });
|
|
113
|
+
*
|
|
114
|
+
* const reasoning = registry.get<ReasoningBank>('reasoningBank');
|
|
115
|
+
* const graph = registry.get<MemoryGraph>('memoryGraph');
|
|
116
|
+
*
|
|
117
|
+
* await registry.shutdown();
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export declare class ControllerRegistry extends EventEmitter {
|
|
121
|
+
private controllers;
|
|
122
|
+
private agentdb;
|
|
123
|
+
private backend;
|
|
124
|
+
private config;
|
|
125
|
+
private initialized;
|
|
126
|
+
private initTimeMs;
|
|
127
|
+
/**
|
|
128
|
+
* Initialize all controllers in level-based order.
|
|
129
|
+
*
|
|
130
|
+
* Each level's controllers are initialized in parallel within the level.
|
|
131
|
+
* Failures are isolated: a controller that fails to init is marked as
|
|
132
|
+
* unavailable but does not block other controllers.
|
|
133
|
+
*/
|
|
134
|
+
initialize(config?: RuntimeConfig): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Shutdown all controllers in reverse initialization order.
|
|
137
|
+
*/
|
|
138
|
+
shutdown(): Promise<void>;
|
|
139
|
+
/**
|
|
140
|
+
* Get a controller instance by name.
|
|
141
|
+
* Returns null if the controller is not initialized or unavailable.
|
|
142
|
+
*/
|
|
143
|
+
get<T>(name: ControllerName): T | null;
|
|
144
|
+
/**
|
|
145
|
+
* Check if a controller is enabled and initialized.
|
|
146
|
+
*/
|
|
147
|
+
isEnabled(name: ControllerName): boolean;
|
|
148
|
+
/**
|
|
149
|
+
* Aggregate health check across all controllers.
|
|
150
|
+
*/
|
|
151
|
+
healthCheck(): Promise<RegistryHealthReport>;
|
|
152
|
+
/**
|
|
153
|
+
* Get the underlying AgentDB instance.
|
|
154
|
+
*/
|
|
155
|
+
getAgentDB(): any;
|
|
156
|
+
/**
|
|
157
|
+
* Get the memory backend.
|
|
158
|
+
*/
|
|
159
|
+
getBackend(): IMemoryBackend | null;
|
|
160
|
+
/**
|
|
161
|
+
* Check if the registry is initialized.
|
|
162
|
+
*/
|
|
163
|
+
isInitialized(): boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Get the number of active (successfully initialized) controllers.
|
|
166
|
+
*/
|
|
167
|
+
getActiveCount(): number;
|
|
168
|
+
/**
|
|
169
|
+
* List all registered controller names and their status.
|
|
170
|
+
*/
|
|
171
|
+
listControllers(): Array<{
|
|
172
|
+
name: ControllerName;
|
|
173
|
+
enabled: boolean;
|
|
174
|
+
level: number;
|
|
175
|
+
}>;
|
|
176
|
+
/**
|
|
177
|
+
* Initialize AgentDB instance with dynamic import and fallback chain.
|
|
178
|
+
*/
|
|
179
|
+
private initAgentDB;
|
|
180
|
+
/**
|
|
181
|
+
* Check whether a controller should be initialized based on config.
|
|
182
|
+
*/
|
|
183
|
+
private isControllerEnabled;
|
|
184
|
+
/**
|
|
185
|
+
* Initialize a single controller with error isolation.
|
|
186
|
+
*/
|
|
187
|
+
private initController;
|
|
188
|
+
/**
|
|
189
|
+
* Factory method to create a controller instance.
|
|
190
|
+
* Handles CLI-layer controllers; AgentDB-internal controllers are
|
|
191
|
+
* accessed via agentdb.getController().
|
|
192
|
+
*/
|
|
193
|
+
private createController;
|
|
194
|
+
/**
|
|
195
|
+
* Shutdown a single controller gracefully.
|
|
196
|
+
*/
|
|
197
|
+
private shutdownController;
|
|
198
|
+
/**
|
|
199
|
+
* Create an EmbeddingService for controllers that need it.
|
|
200
|
+
* Uses the config's embedding generator or creates a minimal local service.
|
|
201
|
+
*/
|
|
202
|
+
private createEmbeddingService;
|
|
203
|
+
/**
|
|
204
|
+
* Lightweight in-memory tiered store (fallback when HierarchicalMemory
|
|
205
|
+
* cannot be initialized from agentdb).
|
|
206
|
+
* Enforces per-tier size limits to prevent unbounded memory growth.
|
|
207
|
+
*/
|
|
208
|
+
private createTieredMemoryStub;
|
|
209
|
+
/**
|
|
210
|
+
* No-op consolidation stub (fallback when MemoryConsolidation
|
|
211
|
+
* cannot be initialized from agentdb).
|
|
212
|
+
*/
|
|
213
|
+
private createConsolidationStub;
|
|
214
|
+
}
|
|
215
|
+
export default ControllerRegistry;
|
|
216
|
+
//# sourceMappingURL=controller-registry.d.ts.map
|