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,277 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { MemoryGraph } from './memory-graph.js';
|
|
3
|
+
import { LearningBridge } from './learning-bridge.js';
|
|
4
|
+
import { AutoMemoryBridge } from './auto-memory-bridge.js';
|
|
5
|
+
import { resolveAgentMemoryDir, transferKnowledge } from './agent-memory-scope.js';
|
|
6
|
+
import { createDefaultEntry } from './types.js';
|
|
7
|
+
function createMockBackend(entries = []) {
|
|
8
|
+
const stored = new Map();
|
|
9
|
+
entries.forEach(e => stored.set(e.id, e));
|
|
10
|
+
return {
|
|
11
|
+
initialize: vi.fn(async () => { }),
|
|
12
|
+
shutdown: vi.fn(async () => { }),
|
|
13
|
+
store: vi.fn(async (e) => { stored.set(e.id, e); }),
|
|
14
|
+
get: vi.fn(async (id) => stored.get(id) ?? null),
|
|
15
|
+
getByKey: vi.fn(async () => null),
|
|
16
|
+
update: vi.fn(async (id, u) => { const e = stored.get(id); if (e) {
|
|
17
|
+
Object.assign(e.metadata, u.metadata || {});
|
|
18
|
+
return e;
|
|
19
|
+
} return null; }),
|
|
20
|
+
delete: vi.fn(async (id) => stored.delete(id)),
|
|
21
|
+
query: vi.fn(async () => [...stored.values()]),
|
|
22
|
+
search: vi.fn(async () => []),
|
|
23
|
+
bulkInsert: vi.fn(async (es) => es.forEach(e => stored.set(e.id, e))),
|
|
24
|
+
bulkDelete: vi.fn(async (ids) => { ids.forEach(id => stored.delete(id)); return ids.length; }),
|
|
25
|
+
count: vi.fn(async () => stored.size),
|
|
26
|
+
listNamespaces: vi.fn(async () => ['default']),
|
|
27
|
+
clearNamespace: vi.fn(async () => 0),
|
|
28
|
+
getStats: vi.fn(async () => ({ totalEntries: stored.size, entriesByNamespace: {}, entriesByType: { semantic: 0, episodic: 0, procedural: 0, working: 0, cache: 0 }, memoryUsage: 0, avgQueryTime: 0, avgSearchTime: 0 })),
|
|
29
|
+
healthCheck: vi.fn(async () => ({ status: 'healthy', components: { storage: { status: 'healthy', latency: 0 }, index: { status: 'healthy', latency: 0 }, cache: { status: 'healthy', latency: 0 } }, timestamp: Date.now(), issues: [], recommendations: [] })),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function makeEntry(id, refs = []) {
|
|
33
|
+
return { ...createDefaultEntry({ key: id, content: `Content for ${id}`, references: refs, metadata: { confidence: 0.7 + Math.random() * 0.3 } }), id };
|
|
34
|
+
}
|
|
35
|
+
function createMockNeural() {
|
|
36
|
+
let trajId = 0;
|
|
37
|
+
return {
|
|
38
|
+
initialize: async () => { },
|
|
39
|
+
beginTask: () => `traj-${++trajId}`,
|
|
40
|
+
recordStep: () => { },
|
|
41
|
+
completeTask: async () => { },
|
|
42
|
+
findPatterns: async () => [],
|
|
43
|
+
retrieveMemories: async () => [],
|
|
44
|
+
triggerLearning: async () => { },
|
|
45
|
+
getStats: () => ({}),
|
|
46
|
+
cleanup: async () => { },
|
|
47
|
+
getSONAManager: () => ({ getMode: () => 'balanced' }),
|
|
48
|
+
getReasoningBank: () => ({ consolidate: async () => ({}) }),
|
|
49
|
+
getPatternLearner: () => ({}),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
describe('ADR-049 Performance Benchmarks', () => {
|
|
53
|
+
const targets = [];
|
|
54
|
+
function buildGraphEntries(n) {
|
|
55
|
+
const entries = [];
|
|
56
|
+
for (let i = 0; i < n; i++) {
|
|
57
|
+
const refs = [];
|
|
58
|
+
for (let j = 0; j < 3; j++) {
|
|
59
|
+
const r = Math.floor(Math.random() * n);
|
|
60
|
+
if (r !== i)
|
|
61
|
+
refs.push(`entry-${r}`);
|
|
62
|
+
}
|
|
63
|
+
entries.push(makeEntry(`entry-${i}`, refs));
|
|
64
|
+
}
|
|
65
|
+
return entries;
|
|
66
|
+
}
|
|
67
|
+
function buildGraph(entries, maxNodes) {
|
|
68
|
+
const g = new MemoryGraph({ maxNodes });
|
|
69
|
+
for (const e of entries)
|
|
70
|
+
g.addNode(e);
|
|
71
|
+
for (const e of entries) {
|
|
72
|
+
for (const r of e.references)
|
|
73
|
+
g.addEdge(e.id, r, 'reference');
|
|
74
|
+
}
|
|
75
|
+
return g;
|
|
76
|
+
}
|
|
77
|
+
it('MemoryGraph: build 100 nodes', () => {
|
|
78
|
+
const entries = buildGraphEntries(100);
|
|
79
|
+
const t0 = performance.now();
|
|
80
|
+
buildGraph(entries, 200);
|
|
81
|
+
const dt = performance.now() - t0;
|
|
82
|
+
console.log(` Graph build (100): ${dt.toFixed(2)}ms`);
|
|
83
|
+
expect(dt).toBeLessThan(50);
|
|
84
|
+
});
|
|
85
|
+
it('MemoryGraph: build 1000 nodes', () => {
|
|
86
|
+
const entries = buildGraphEntries(1000);
|
|
87
|
+
const t0 = performance.now();
|
|
88
|
+
buildGraph(entries, 1100);
|
|
89
|
+
const dt = performance.now() - t0;
|
|
90
|
+
console.log(` Graph build (1k): ${dt.toFixed(2)}ms [target: <200ms]`);
|
|
91
|
+
targets.push({ name: 'Graph build (1k nodes)', actual: dt, target: 200, unit: 'ms' });
|
|
92
|
+
expect(dt).toBeLessThan(200);
|
|
93
|
+
});
|
|
94
|
+
it('MemoryGraph: build 2000 nodes', () => {
|
|
95
|
+
const entries = buildGraphEntries(2000);
|
|
96
|
+
const t0 = performance.now();
|
|
97
|
+
buildGraph(entries, 2100);
|
|
98
|
+
const dt = performance.now() - t0;
|
|
99
|
+
console.log(` Graph build (2k): ${dt.toFixed(2)}ms`);
|
|
100
|
+
expect(dt).toBeLessThan(500);
|
|
101
|
+
});
|
|
102
|
+
it('MemoryGraph: PageRank 1000 nodes', () => {
|
|
103
|
+
const entries = buildGraphEntries(1000);
|
|
104
|
+
const g = buildGraph(entries, 1100);
|
|
105
|
+
const t0 = performance.now();
|
|
106
|
+
g.computePageRank();
|
|
107
|
+
const dt = performance.now() - t0;
|
|
108
|
+
console.log(` PageRank (1k): ${dt.toFixed(2)}ms [target: <100ms]`);
|
|
109
|
+
targets.push({ name: 'PageRank (1k nodes)', actual: dt, target: 100, unit: 'ms' });
|
|
110
|
+
expect(dt).toBeLessThan(100);
|
|
111
|
+
});
|
|
112
|
+
it('MemoryGraph: PageRank 2000 nodes', () => {
|
|
113
|
+
const entries = buildGraphEntries(2000);
|
|
114
|
+
const g = buildGraph(entries, 2100);
|
|
115
|
+
const t0 = performance.now();
|
|
116
|
+
g.computePageRank();
|
|
117
|
+
const dt = performance.now() - t0;
|
|
118
|
+
console.log(` PageRank (2k): ${dt.toFixed(2)}ms`);
|
|
119
|
+
expect(dt).toBeLessThan(300);
|
|
120
|
+
});
|
|
121
|
+
it('MemoryGraph: community detection 1000 nodes', () => {
|
|
122
|
+
const entries = buildGraphEntries(1000);
|
|
123
|
+
const g = buildGraph(entries, 1100);
|
|
124
|
+
g.computePageRank();
|
|
125
|
+
const t0 = performance.now();
|
|
126
|
+
g.detectCommunities();
|
|
127
|
+
const dt = performance.now() - t0;
|
|
128
|
+
const stats = g.getStats();
|
|
129
|
+
console.log(` Communities (1k): ${dt.toFixed(2)}ms (${stats.communityCount} found)`);
|
|
130
|
+
expect(dt).toBeLessThan(200);
|
|
131
|
+
});
|
|
132
|
+
it('MemoryGraph: rankWithGraph 10 results', () => {
|
|
133
|
+
const entries = buildGraphEntries(1000);
|
|
134
|
+
const g = buildGraph(entries, 1100);
|
|
135
|
+
g.computePageRank();
|
|
136
|
+
const fakeResults = entries.slice(0, 10).map(e => ({ entry: e, score: Math.random(), distance: Math.random() }));
|
|
137
|
+
const t0 = performance.now();
|
|
138
|
+
for (let i = 0; i < 100; i++)
|
|
139
|
+
g.rankWithGraph(fakeResults);
|
|
140
|
+
const dt = (performance.now() - t0) / 100;
|
|
141
|
+
console.log(` rankWithGraph(10): ${dt.toFixed(3)}ms (avg of 100 runs)`);
|
|
142
|
+
expect(dt).toBeLessThan(1);
|
|
143
|
+
});
|
|
144
|
+
it('MemoryGraph: getTopNodes(20)', () => {
|
|
145
|
+
const entries = buildGraphEntries(1000);
|
|
146
|
+
const g = buildGraph(entries, 1100);
|
|
147
|
+
g.computePageRank();
|
|
148
|
+
g.detectCommunities();
|
|
149
|
+
const t0 = performance.now();
|
|
150
|
+
for (let i = 0; i < 100; i++)
|
|
151
|
+
g.getTopNodes(20);
|
|
152
|
+
const dt = (performance.now() - t0) / 100;
|
|
153
|
+
console.log(` getTopNodes(20): ${dt.toFixed(3)}ms (avg of 100 runs)`);
|
|
154
|
+
expect(dt).toBeLessThan(5);
|
|
155
|
+
});
|
|
156
|
+
it('MemoryGraph: getNeighbors depth=2', () => {
|
|
157
|
+
const entries = buildGraphEntries(1000);
|
|
158
|
+
const g = buildGraph(entries, 1100);
|
|
159
|
+
const t0 = performance.now();
|
|
160
|
+
for (let i = 0; i < 100; i++)
|
|
161
|
+
g.getNeighbors(entries[i % entries.length].id, 2);
|
|
162
|
+
const dt = (performance.now() - t0) / 100;
|
|
163
|
+
console.log(` getNeighbors(d=2): ${dt.toFixed(3)}ms (avg of 100 runs)`);
|
|
164
|
+
expect(dt).toBeLessThan(5);
|
|
165
|
+
});
|
|
166
|
+
it('LearningBridge: record 1000 insights', async () => {
|
|
167
|
+
const mockNeural = createMockNeural();
|
|
168
|
+
const backend = createMockBackend();
|
|
169
|
+
const lb = new LearningBridge(backend, { neuralLoader: async () => mockNeural, consolidationThreshold: 99999 });
|
|
170
|
+
const t0 = performance.now();
|
|
171
|
+
for (let i = 0; i < 1000; i++) {
|
|
172
|
+
await lb.onInsightRecorded({ category: 'debugging', summary: `Insight ${i}`, source: 'bench', confidence: 0.8 }, `entry-${i}`);
|
|
173
|
+
}
|
|
174
|
+
const dt = performance.now() - t0;
|
|
175
|
+
const per = dt / 1000;
|
|
176
|
+
console.log(` Record 1000: ${dt.toFixed(2)}ms (${per.toFixed(3)}ms/each) [target: <5ms/each]`);
|
|
177
|
+
targets.push({ name: 'Insight recording', actual: per, target: 5, unit: 'ms/each' });
|
|
178
|
+
expect(per).toBeLessThan(5);
|
|
179
|
+
lb.destroy();
|
|
180
|
+
});
|
|
181
|
+
it('LearningBridge: access 1000 insights', async () => {
|
|
182
|
+
const mockNeural = createMockNeural();
|
|
183
|
+
const entries = [];
|
|
184
|
+
for (let i = 0; i < 1000; i++) {
|
|
185
|
+
const e = makeEntry(`entry-${i}`);
|
|
186
|
+
e.metadata.confidence = 0.5;
|
|
187
|
+
entries.push(e);
|
|
188
|
+
}
|
|
189
|
+
const backend = createMockBackend(entries);
|
|
190
|
+
const lb = new LearningBridge(backend, { neuralLoader: async () => mockNeural, consolidationThreshold: 99999 });
|
|
191
|
+
// warm up trajectories
|
|
192
|
+
for (let i = 0; i < 1000; i++) {
|
|
193
|
+
await lb.onInsightRecorded({ category: 'debugging', summary: `I-${i}`, source: 'bench', confidence: 0.8 }, `entry-${i}`);
|
|
194
|
+
}
|
|
195
|
+
const t0 = performance.now();
|
|
196
|
+
for (let i = 0; i < 1000; i++)
|
|
197
|
+
await lb.onInsightAccessed(`entry-${i}`);
|
|
198
|
+
const dt = performance.now() - t0;
|
|
199
|
+
console.log(` Access 1000: ${dt.toFixed(2)}ms (${(dt / 1000).toFixed(3)}ms/each)`);
|
|
200
|
+
expect(dt / 1000).toBeLessThan(5);
|
|
201
|
+
lb.destroy();
|
|
202
|
+
});
|
|
203
|
+
it('LearningBridge: consolidation', async () => {
|
|
204
|
+
const mockNeural = createMockNeural();
|
|
205
|
+
const backend = createMockBackend();
|
|
206
|
+
const lb = new LearningBridge(backend, { neuralLoader: async () => mockNeural, consolidationThreshold: 1 });
|
|
207
|
+
for (let i = 0; i < 100; i++) {
|
|
208
|
+
await lb.onInsightRecorded({ category: 'debugging', summary: `I-${i}`, source: 'bench', confidence: 0.8 }, `entry-${i}`);
|
|
209
|
+
}
|
|
210
|
+
const t0 = performance.now();
|
|
211
|
+
const result = await lb.consolidate();
|
|
212
|
+
const dt = performance.now() - t0;
|
|
213
|
+
console.log(` Consolidation: ${dt.toFixed(2)}ms (${result.trajectoriesCompleted} trajectories) [target: <500ms]`);
|
|
214
|
+
targets.push({ name: 'Consolidation', actual: dt, target: 500, unit: 'ms' });
|
|
215
|
+
expect(dt).toBeLessThan(500);
|
|
216
|
+
lb.destroy();
|
|
217
|
+
});
|
|
218
|
+
it('LearningBridge: decay 1000 entries', async () => {
|
|
219
|
+
const mockNeural = createMockNeural();
|
|
220
|
+
const entries = [];
|
|
221
|
+
for (let i = 0; i < 1000; i++) {
|
|
222
|
+
const e = makeEntry(`decay-${i}`);
|
|
223
|
+
e.metadata.confidence = 0.9;
|
|
224
|
+
e.lastAccessedAt = Date.now() - 7200000;
|
|
225
|
+
entries.push(e);
|
|
226
|
+
}
|
|
227
|
+
const backend = createMockBackend(entries);
|
|
228
|
+
const lb = new LearningBridge(backend, { neuralLoader: async () => mockNeural });
|
|
229
|
+
const t0 = performance.now();
|
|
230
|
+
const decayed = await lb.decayConfidences('default');
|
|
231
|
+
const dt = performance.now() - t0;
|
|
232
|
+
console.log(` Decay 1k entries: ${dt.toFixed(2)}ms (${decayed} decayed) [target: <50ms]`);
|
|
233
|
+
targets.push({ name: 'Confidence decay (1k)', actual: dt, target: 50, unit: 'ms' });
|
|
234
|
+
expect(dt).toBeLessThan(50);
|
|
235
|
+
lb.destroy();
|
|
236
|
+
});
|
|
237
|
+
it('AgentMemoryScope: resolve 10k paths', () => {
|
|
238
|
+
const scopes = ['project', 'local', 'user'];
|
|
239
|
+
const t0 = performance.now();
|
|
240
|
+
for (let i = 0; i < 10000; i++)
|
|
241
|
+
resolveAgentMemoryDir(`agent-${i % 100}`, scopes[i % 3]);
|
|
242
|
+
const dt = performance.now() - t0;
|
|
243
|
+
console.log(` Resolve 10k paths: ${dt.toFixed(2)}ms (${(dt / 10).toFixed(1)}us/each)`);
|
|
244
|
+
expect(dt).toBeLessThan(200); // Not an ADR-049 target; relaxed for CI variance
|
|
245
|
+
});
|
|
246
|
+
it('AgentMemoryScope: transfer knowledge', async () => {
|
|
247
|
+
const sourceEntries = [];
|
|
248
|
+
for (let i = 0; i < 50; i++) {
|
|
249
|
+
const e = makeEntry(`src-${i}`, []);
|
|
250
|
+
e.tags = ['debugging'];
|
|
251
|
+
e.metadata.confidence = 0.5 + Math.random() * 0.5;
|
|
252
|
+
e.namespace = 'learnings';
|
|
253
|
+
sourceEntries.push(e);
|
|
254
|
+
}
|
|
255
|
+
const sourceBackend = createMockBackend(sourceEntries);
|
|
256
|
+
const targetBackend = createMockBackend();
|
|
257
|
+
const targetBridge = new AutoMemoryBridge(targetBackend, { memoryDir: '/tmp/bench-target' });
|
|
258
|
+
const t0 = performance.now();
|
|
259
|
+
const result = await transferKnowledge(sourceBackend, targetBridge, { sourceNamespace: 'learnings', minConfidence: 0.8, maxEntries: 20 });
|
|
260
|
+
const dt = performance.now() - t0;
|
|
261
|
+
console.log(` Transfer knowledge: ${dt.toFixed(2)}ms (${result.transferred} transferred) [target: <100ms]`);
|
|
262
|
+
targets.push({ name: 'Knowledge transfer', actual: dt, target: 100, unit: 'ms' });
|
|
263
|
+
expect(dt).toBeLessThan(100);
|
|
264
|
+
});
|
|
265
|
+
it('SUMMARY: all targets met', () => {
|
|
266
|
+
console.log('\n=== ADR-049 Performance Summary ===\n');
|
|
267
|
+
for (const t of targets) {
|
|
268
|
+
const pass = t.actual <= t.target;
|
|
269
|
+
const ratio = (t.target / t.actual).toFixed(1);
|
|
270
|
+
console.log(` ${pass ? 'PASS' : 'FAIL'} ${t.name.padEnd(28)} ${t.actual.toFixed(2).padStart(8)} ${t.unit.padEnd(8)} target: <${t.target}${t.unit} (${ratio}x headroom)`);
|
|
271
|
+
}
|
|
272
|
+
console.log('');
|
|
273
|
+
const allPass = targets.every(t => t.actual <= t.target);
|
|
274
|
+
expect(allPass).toBe(true);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
//# sourceMappingURL=benchmark.test.js.map
|
|
@@ -0,0 +1,134 @@
|
|
|
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
|
+
import { CacheConfig, CacheStats, MemoryEntry } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* High-performance LRU Cache with TTL support
|
|
13
|
+
*
|
|
14
|
+
* Features:
|
|
15
|
+
* - O(1) get, set, delete operations
|
|
16
|
+
* - LRU eviction policy
|
|
17
|
+
* - TTL-based expiration
|
|
18
|
+
* - Memory pressure handling
|
|
19
|
+
* - Write-through caching support
|
|
20
|
+
* - Performance statistics
|
|
21
|
+
*/
|
|
22
|
+
export declare class CacheManager<T = MemoryEntry> extends EventEmitter {
|
|
23
|
+
private config;
|
|
24
|
+
private cache;
|
|
25
|
+
private head;
|
|
26
|
+
private tail;
|
|
27
|
+
private currentMemory;
|
|
28
|
+
private stats;
|
|
29
|
+
private cleanupInterval;
|
|
30
|
+
constructor(config?: Partial<CacheConfig>);
|
|
31
|
+
/**
|
|
32
|
+
* Get a value from the cache
|
|
33
|
+
*/
|
|
34
|
+
get(key: string): T | null;
|
|
35
|
+
/**
|
|
36
|
+
* Set a value in the cache
|
|
37
|
+
*/
|
|
38
|
+
set(key: string, data: T, ttl?: number): void;
|
|
39
|
+
/**
|
|
40
|
+
* Delete a value from the cache
|
|
41
|
+
*/
|
|
42
|
+
delete(key: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Check if a key exists in the cache (without affecting LRU order)
|
|
45
|
+
*/
|
|
46
|
+
has(key: string): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Clear all entries from the cache
|
|
49
|
+
*/
|
|
50
|
+
clear(): void;
|
|
51
|
+
/**
|
|
52
|
+
* Get cache statistics
|
|
53
|
+
*/
|
|
54
|
+
getStats(): CacheStats;
|
|
55
|
+
/**
|
|
56
|
+
* Get all keys in the cache
|
|
57
|
+
*/
|
|
58
|
+
keys(): string[];
|
|
59
|
+
/**
|
|
60
|
+
* Get the size of the cache
|
|
61
|
+
*/
|
|
62
|
+
get size(): number;
|
|
63
|
+
/**
|
|
64
|
+
* Prefetch multiple keys in a single batch
|
|
65
|
+
*/
|
|
66
|
+
prefetch(keys: string[], loader: (keys: string[]) => Promise<Map<string, T>>, ttl?: number): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Get or set pattern - get from cache or load and cache
|
|
69
|
+
*/
|
|
70
|
+
getOrSet(key: string, loader: () => Promise<T>, ttl?: number): Promise<T>;
|
|
71
|
+
/**
|
|
72
|
+
* Warm the cache with initial data
|
|
73
|
+
*/
|
|
74
|
+
warmUp(entries: Array<{
|
|
75
|
+
key: string;
|
|
76
|
+
data: T;
|
|
77
|
+
ttl?: number;
|
|
78
|
+
}>): void;
|
|
79
|
+
/**
|
|
80
|
+
* Invalidate entries matching a pattern
|
|
81
|
+
*/
|
|
82
|
+
invalidatePattern(pattern: string | RegExp): number;
|
|
83
|
+
/**
|
|
84
|
+
* Shutdown the cache manager
|
|
85
|
+
*/
|
|
86
|
+
shutdown(): void;
|
|
87
|
+
private mergeConfig;
|
|
88
|
+
private isExpired;
|
|
89
|
+
private estimateSize;
|
|
90
|
+
private addToFront;
|
|
91
|
+
private removeNode;
|
|
92
|
+
private moveToFront;
|
|
93
|
+
private evictLRU;
|
|
94
|
+
private startCleanupTimer;
|
|
95
|
+
private cleanupExpired;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Multi-layer cache with L1 (memory) and L2 (storage) tiers
|
|
99
|
+
*/
|
|
100
|
+
export declare class TieredCacheManager<T = MemoryEntry> extends EventEmitter {
|
|
101
|
+
private l1Cache;
|
|
102
|
+
private l2Loader;
|
|
103
|
+
private l2Writer;
|
|
104
|
+
constructor(l1Config?: Partial<CacheConfig>, l2Options?: {
|
|
105
|
+
loader: (key: string) => Promise<T | null>;
|
|
106
|
+
writer?: (key: string, value: T) => Promise<void>;
|
|
107
|
+
});
|
|
108
|
+
/**
|
|
109
|
+
* Get from tiered cache
|
|
110
|
+
*/
|
|
111
|
+
get(key: string): Promise<T | null>;
|
|
112
|
+
/**
|
|
113
|
+
* Set in tiered cache
|
|
114
|
+
*/
|
|
115
|
+
set(key: string, value: T, ttl?: number): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Delete from tiered cache
|
|
118
|
+
*/
|
|
119
|
+
delete(key: string): boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Get L1 cache statistics
|
|
122
|
+
*/
|
|
123
|
+
getStats(): CacheStats;
|
|
124
|
+
/**
|
|
125
|
+
* Clear L1 cache
|
|
126
|
+
*/
|
|
127
|
+
clear(): void;
|
|
128
|
+
/**
|
|
129
|
+
* Shutdown tiered cache
|
|
130
|
+
*/
|
|
131
|
+
shutdown(): void;
|
|
132
|
+
}
|
|
133
|
+
export default CacheManager;
|
|
134
|
+
//# sourceMappingURL=cache-manager.d.ts.map
|