@agentic-robotics/mcp 0.1.3 โ 0.2.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/dist/benchmark.d.ts +97 -0
- package/dist/benchmark.d.ts.map +1 -0
- package/dist/benchmark.js +330 -0
- package/dist/benchmark.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +79 -0
- package/dist/cli.js.map +1 -0
- package/dist/enhanced-memory.d.ts +118 -0
- package/dist/enhanced-memory.d.ts.map +1 -0
- package/dist/enhanced-memory.js +296 -0
- package/dist/enhanced-memory.js.map +1 -0
- package/dist/enhanced-server.d.ts +122 -0
- package/dist/enhanced-server.d.ts.map +1 -0
- package/dist/enhanced-server.js +361 -0
- package/dist/enhanced-server.js.map +1 -0
- package/dist/flow-orchestrator.d.ts +75 -0
- package/dist/flow-orchestrator.d.ts.map +1 -0
- package/dist/flow-orchestrator.js +350 -0
- package/dist/flow-orchestrator.js.map +1 -0
- package/dist/hybrid-benchmark.d.ts +44 -0
- package/dist/hybrid-benchmark.d.ts.map +1 -0
- package/dist/hybrid-benchmark.js +232 -0
- package/dist/hybrid-benchmark.js.map +1 -0
- package/dist/hybrid-memory.d.ts +81 -0
- package/dist/hybrid-memory.d.ts.map +1 -0
- package/dist/hybrid-memory.js +296 -0
- package/dist/hybrid-memory.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/interface.d.ts +38 -0
- package/dist/interface.d.ts.map +1 -0
- package/dist/interface.js +75 -0
- package/dist/interface.js.map +1 -0
- package/dist/memory.d.ts +52 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +230 -0
- package/dist/memory.js.map +1 -0
- package/dist/optimized-benchmark.d.ts +74 -0
- package/dist/optimized-benchmark.d.ts.map +1 -0
- package/dist/optimized-benchmark.js +231 -0
- package/dist/optimized-benchmark.js.map +1 -0
- package/dist/server.d.ts +55 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +147 -0
- package/dist/server.js.map +1 -0
- package/package.json +3 -2
- package/src/enhanced-server.ts +1 -1
- package/src/flow-orchestrator.ts +177 -117
- package/src/hybrid-memory.ts +2 -2
- package/src/memory.ts +171 -52
- package/src/optimized-benchmark.ts +0 -302
- package/src/optimized-memory.ts +0 -271
package/src/memory.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AgentDB Reflexion Memory Integration
|
|
3
3
|
*
|
|
4
|
-
* Enables robot learning from past experiences with
|
|
4
|
+
* Enables robot learning from past experiences with secure command execution
|
|
5
|
+
* SECURITY: Uses spawn() with argument arrays to prevent command injection
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import { spawn } from 'child_process';
|
|
8
|
-
import { promisify } from 'util';
|
|
9
|
-
import { exec } from 'child_process';
|
|
10
|
-
|
|
11
|
-
const execAsync = promisify(exec);
|
|
12
9
|
|
|
13
10
|
export interface Episode {
|
|
14
11
|
sessionId: string;
|
|
@@ -29,11 +26,51 @@ export interface Memory {
|
|
|
29
26
|
timestamp: number;
|
|
30
27
|
}
|
|
31
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Helper to safely spawn a command and capture output
|
|
31
|
+
* Prevents command injection by using spawn with argument array
|
|
32
|
+
*/
|
|
33
|
+
function spawnAsync(
|
|
34
|
+
command: string,
|
|
35
|
+
args: string[],
|
|
36
|
+
env?: Record<string, string>
|
|
37
|
+
): Promise<{ stdout: string; stderr: string; code: number }> {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
const child = spawn(command, args, {
|
|
40
|
+
env: { ...process.env, ...env },
|
|
41
|
+
shell: false, // Critical: disable shell interpretation
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
let stdout = '';
|
|
45
|
+
let stderr = '';
|
|
46
|
+
|
|
47
|
+
child.stdout?.on('data', (data) => {
|
|
48
|
+
stdout += data.toString();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
child.stderr?.on('data', (data) => {
|
|
52
|
+
stderr += data.toString();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
child.on('close', (code) => {
|
|
56
|
+
resolve({ stdout, stderr, code: code || 0 });
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
child.on('error', (error) => {
|
|
60
|
+
reject(error);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
32
65
|
export class AgentDBMemory {
|
|
33
66
|
private dbPath: string;
|
|
34
67
|
private initialized: boolean = false;
|
|
35
68
|
|
|
36
69
|
constructor(dbPath: string) {
|
|
70
|
+
// Validate dbPath to prevent path traversal
|
|
71
|
+
if (!dbPath || dbPath.includes('..') || dbPath.includes(';') || dbPath.includes('|')) {
|
|
72
|
+
throw new Error('Invalid database path');
|
|
73
|
+
}
|
|
37
74
|
this.dbPath = dbPath;
|
|
38
75
|
}
|
|
39
76
|
|
|
@@ -41,38 +78,64 @@ export class AgentDBMemory {
|
|
|
41
78
|
if (this.initialized) return;
|
|
42
79
|
|
|
43
80
|
try {
|
|
44
|
-
// Initialize AgentDB database
|
|
45
|
-
const { stdout, stderr } = await
|
|
46
|
-
|
|
47
|
-
|
|
81
|
+
// Initialize AgentDB database - use spawn with argument array for security
|
|
82
|
+
const { stdout, stderr, code } = await spawnAsync('npx', [
|
|
83
|
+
'agentdb',
|
|
84
|
+
'init',
|
|
85
|
+
this.dbPath,
|
|
86
|
+
'--dimension',
|
|
87
|
+
'768',
|
|
88
|
+
'--preset',
|
|
89
|
+
'medium',
|
|
90
|
+
]);
|
|
48
91
|
|
|
49
|
-
|
|
50
|
-
|
|
92
|
+
if (code === 0 || stderr.includes('already exists')) {
|
|
93
|
+
console.error('AgentDB initialized:', this.dbPath);
|
|
94
|
+
this.initialized = true;
|
|
95
|
+
} else {
|
|
96
|
+
throw new Error(`Initialization failed: ${stderr}`);
|
|
97
|
+
}
|
|
51
98
|
} catch (error: any) {
|
|
52
99
|
// Database might already exist
|
|
53
|
-
if (
|
|
54
|
-
|
|
100
|
+
if (error.message?.includes('already exists')) {
|
|
101
|
+
this.initialized = true;
|
|
102
|
+
} else {
|
|
103
|
+
throw new Error(`Failed to initialize AgentDB: ${error.message}`);
|
|
55
104
|
}
|
|
56
|
-
this.initialized = true;
|
|
57
105
|
}
|
|
58
106
|
}
|
|
59
107
|
|
|
60
108
|
async storeEpisode(episode: Episode): Promise<void> {
|
|
61
|
-
|
|
62
|
-
'
|
|
63
|
-
|
|
64
|
-
`"${episode.taskName}"`,
|
|
65
|
-
episode.confidence.toString(),
|
|
66
|
-
episode.success.toString(),
|
|
67
|
-
episode.outcome ? `"${episode.outcome}"` : '""',
|
|
68
|
-
].join(' ');
|
|
109
|
+
if (!this.initialized) {
|
|
110
|
+
throw new Error('AgentDB not initialized. Call initialize() first.');
|
|
111
|
+
}
|
|
69
112
|
|
|
70
113
|
try {
|
|
71
|
-
|
|
114
|
+
// Use spawn with argument array to prevent command injection
|
|
115
|
+
const { code, stderr } = await spawnAsync(
|
|
116
|
+
'npx',
|
|
117
|
+
[
|
|
118
|
+
'agentdb',
|
|
119
|
+
'reflexion',
|
|
120
|
+
'store',
|
|
121
|
+
episode.sessionId,
|
|
122
|
+
episode.taskName,
|
|
123
|
+
episode.confidence.toString(),
|
|
124
|
+
episode.success.toString(),
|
|
125
|
+
episode.outcome || '',
|
|
126
|
+
],
|
|
127
|
+
{ AGENTDB_PATH: this.dbPath }
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
if (code !== 0) {
|
|
131
|
+
throw new Error(`Command failed: ${stderr}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
72
134
|
console.error(`Stored episode: ${episode.taskName} (success: ${episode.success})`);
|
|
73
135
|
} catch (error: any) {
|
|
74
|
-
|
|
75
|
-
|
|
136
|
+
const errorMsg = `Failed to store episode "${episode.taskName}": ${error.message}`;
|
|
137
|
+
console.error('Error storing episode:', errorMsg);
|
|
138
|
+
throw new Error(errorMsg); // Throw instead of silently failing
|
|
76
139
|
}
|
|
77
140
|
}
|
|
78
141
|
|
|
@@ -86,27 +149,38 @@ export class AgentDBMemory {
|
|
|
86
149
|
synthesizeContext?: boolean;
|
|
87
150
|
} = {}
|
|
88
151
|
): Promise<Memory[]> {
|
|
89
|
-
|
|
152
|
+
if (!this.initialized) {
|
|
153
|
+
throw new Error('AgentDB not initialized. Call initialize() first.');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Build safe argument array
|
|
157
|
+
const args = ['agentdb', 'reflexion', 'retrieve', query, '--k', k.toString()];
|
|
90
158
|
|
|
91
159
|
if (options.minReward !== undefined) {
|
|
92
|
-
|
|
160
|
+
args.push('--min-reward', options.minReward.toString());
|
|
93
161
|
}
|
|
94
162
|
if (options.onlySuccesses) {
|
|
95
|
-
|
|
163
|
+
args.push('--only-successes');
|
|
96
164
|
}
|
|
97
165
|
if (options.onlyFailures) {
|
|
98
|
-
|
|
166
|
+
args.push('--only-failures');
|
|
99
167
|
}
|
|
100
168
|
if (options.synthesizeContext) {
|
|
101
|
-
|
|
169
|
+
args.push('--synthesize-context');
|
|
102
170
|
}
|
|
103
171
|
|
|
104
172
|
try {
|
|
105
|
-
const { stdout } = await
|
|
173
|
+
const { stdout, code, stderr } = await spawnAsync('npx', args, {
|
|
174
|
+
AGENTDB_PATH: this.dbPath,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (code !== 0) {
|
|
178
|
+
throw new Error(`Command failed: ${stderr}`);
|
|
179
|
+
}
|
|
106
180
|
|
|
107
181
|
// Parse JSON output
|
|
108
182
|
const lines = stdout.trim().split('\n');
|
|
109
|
-
const jsonLine = lines.find(line => line.startsWith('[') || line.startsWith('{'));
|
|
183
|
+
const jsonLine = lines.find((line) => line.startsWith('[') || line.startsWith('{'));
|
|
110
184
|
|
|
111
185
|
if (jsonLine) {
|
|
112
186
|
const data = JSON.parse(jsonLine);
|
|
@@ -115,8 +189,8 @@ export class AgentDBMemory {
|
|
|
115
189
|
|
|
116
190
|
return [];
|
|
117
191
|
} catch (error: any) {
|
|
118
|
-
|
|
119
|
-
|
|
192
|
+
// Throw error instead of silently returning empty array
|
|
193
|
+
throw new Error(`Failed to retrieve memories for query "${query}": ${error.message}`);
|
|
120
194
|
}
|
|
121
195
|
}
|
|
122
196
|
|
|
@@ -128,21 +202,41 @@ export class AgentDBMemory {
|
|
|
128
202
|
domain?: string;
|
|
129
203
|
} = {}
|
|
130
204
|
): Promise<{ memories: Memory[]; context?: string }> {
|
|
205
|
+
if (!this.initialized) {
|
|
206
|
+
throw new Error('AgentDB not initialized. Call initialize() first.');
|
|
207
|
+
}
|
|
208
|
+
|
|
131
209
|
const { k = 5, minConfidence = 0.0, domain } = options;
|
|
132
210
|
|
|
133
|
-
|
|
211
|
+
// Build safe argument array
|
|
212
|
+
const args = [
|
|
213
|
+
'agentdb',
|
|
214
|
+
'query',
|
|
215
|
+
'--query',
|
|
216
|
+
query,
|
|
217
|
+
'--k',
|
|
218
|
+
k.toString(),
|
|
219
|
+
'--min-confidence',
|
|
220
|
+
minConfidence.toString(),
|
|
221
|
+
];
|
|
134
222
|
|
|
135
223
|
if (domain) {
|
|
136
|
-
|
|
224
|
+
args.push('--domain', domain);
|
|
137
225
|
}
|
|
138
226
|
|
|
139
|
-
|
|
227
|
+
args.push('--synthesize-context', '--format', 'json');
|
|
140
228
|
|
|
141
229
|
try {
|
|
142
|
-
const { stdout } = await
|
|
230
|
+
const { stdout, code, stderr } = await spawnAsync('npx', args, {
|
|
231
|
+
AGENTDB_PATH: this.dbPath,
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
if (code !== 0) {
|
|
235
|
+
throw new Error(`Command failed: ${stderr}`);
|
|
236
|
+
}
|
|
143
237
|
|
|
144
238
|
const lines = stdout.trim().split('\n');
|
|
145
|
-
const jsonLine = lines.find(line => line.startsWith('[') || line.startsWith('{'));
|
|
239
|
+
const jsonLine = lines.find((line) => line.startsWith('[') || line.startsWith('{'));
|
|
146
240
|
|
|
147
241
|
if (jsonLine) {
|
|
148
242
|
const data = JSON.parse(jsonLine);
|
|
@@ -154,8 +248,8 @@ export class AgentDBMemory {
|
|
|
154
248
|
|
|
155
249
|
return { memories: [] };
|
|
156
250
|
} catch (error: any) {
|
|
157
|
-
|
|
158
|
-
|
|
251
|
+
// Throw error instead of silently returning empty array
|
|
252
|
+
throw new Error(`Failed to query with context "${query}": ${error.message}`);
|
|
159
253
|
}
|
|
160
254
|
}
|
|
161
255
|
|
|
@@ -164,29 +258,54 @@ export class AgentDBMemory {
|
|
|
164
258
|
minReward?: number;
|
|
165
259
|
timeWindowDays?: number;
|
|
166
260
|
} = {}): Promise<void> {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
timeWindowDays = 7,
|
|
171
|
-
} = options;
|
|
261
|
+
if (!this.initialized) {
|
|
262
|
+
throw new Error('AgentDB not initialized. Call initialize() first.');
|
|
263
|
+
}
|
|
172
264
|
|
|
173
|
-
const
|
|
265
|
+
const { minAttempts = 3, minReward = 0.7, timeWindowDays = 7 } = options;
|
|
174
266
|
|
|
175
267
|
try {
|
|
176
|
-
|
|
268
|
+
const { code, stderr } = await spawnAsync(
|
|
269
|
+
'npx',
|
|
270
|
+
[
|
|
271
|
+
'agentdb',
|
|
272
|
+
'skill',
|
|
273
|
+
'consolidate',
|
|
274
|
+
minAttempts.toString(),
|
|
275
|
+
minReward.toString(),
|
|
276
|
+
timeWindowDays.toString(),
|
|
277
|
+
'true',
|
|
278
|
+
],
|
|
279
|
+
{ AGENTDB_PATH: this.dbPath }
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
if (code !== 0) {
|
|
283
|
+
throw new Error(`Command failed: ${stderr}`);
|
|
284
|
+
}
|
|
285
|
+
|
|
177
286
|
console.error('Skills consolidated from successful episodes');
|
|
178
287
|
} catch (error: any) {
|
|
179
|
-
|
|
288
|
+
throw new Error(`Failed to consolidate skills: ${error.message}`);
|
|
180
289
|
}
|
|
181
290
|
}
|
|
182
291
|
|
|
183
292
|
async getStats(): Promise<any> {
|
|
293
|
+
if (!this.initialized) {
|
|
294
|
+
throw new Error('AgentDB not initialized. Call initialize() first.');
|
|
295
|
+
}
|
|
296
|
+
|
|
184
297
|
try {
|
|
185
|
-
const { stdout } = await
|
|
298
|
+
const { stdout, code, stderr } = await spawnAsync('npx', ['agentdb', 'db', 'stats'], {
|
|
299
|
+
AGENTDB_PATH: this.dbPath,
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
if (code !== 0) {
|
|
303
|
+
throw new Error(`Command failed: ${stderr}`);
|
|
304
|
+
}
|
|
305
|
+
|
|
186
306
|
return { stats: stdout.trim() };
|
|
187
307
|
} catch (error: any) {
|
|
188
|
-
|
|
189
|
-
return { stats: 'unavailable' };
|
|
308
|
+
throw new Error(`Failed to get stats: ${error.message}`);
|
|
190
309
|
}
|
|
191
310
|
}
|
|
192
311
|
|
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Optimized Benchmark Suite
|
|
3
|
-
*
|
|
4
|
-
* Uses JavaScript APIs directly for accurate performance measurement
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { OptimizedAgentDBMemory } from './optimized-memory.js';
|
|
8
|
-
import type { Episode } from './memory.js';
|
|
9
|
-
|
|
10
|
-
interface BenchmarkResult {
|
|
11
|
-
name: string;
|
|
12
|
-
iterations: number;
|
|
13
|
-
totalTime: number;
|
|
14
|
-
avgTime: number;
|
|
15
|
-
minTime: number;
|
|
16
|
-
maxTime: number;
|
|
17
|
-
opsPerSec: number;
|
|
18
|
-
p50: number;
|
|
19
|
-
p95: number;
|
|
20
|
-
p99: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface BenchmarkSuite {
|
|
24
|
-
agentdb: {
|
|
25
|
-
storeEpisode: BenchmarkResult;
|
|
26
|
-
retrieveMemories: BenchmarkResult;
|
|
27
|
-
queryWithContext: BenchmarkResult;
|
|
28
|
-
consolidateSkills: BenchmarkResult;
|
|
29
|
-
searchSkills: BenchmarkResult;
|
|
30
|
-
};
|
|
31
|
-
overall: {
|
|
32
|
-
totalTime: number;
|
|
33
|
-
timestamp: string;
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export class OptimizedBenchmark {
|
|
38
|
-
private memory: OptimizedAgentDBMemory;
|
|
39
|
-
|
|
40
|
-
constructor() {
|
|
41
|
-
this.memory = new OptimizedAgentDBMemory('./optimized-benchmark.db');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async initialize(): Promise<void> {
|
|
45
|
-
console.log('๐ Initializing optimized benchmark suite...\n');
|
|
46
|
-
await this.memory.initialize();
|
|
47
|
-
console.log('โ
Benchmark suite ready\n');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Run complete benchmark suite
|
|
52
|
-
*/
|
|
53
|
-
async runAll(): Promise<BenchmarkSuite> {
|
|
54
|
-
const suiteStartTime = Date.now();
|
|
55
|
-
|
|
56
|
-
console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
|
|
57
|
-
console.log('โ Optimized Integration Benchmark Suite โ');
|
|
58
|
-
console.log('โ AgentDB JavaScript API Performance Test โ');
|
|
59
|
-
console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n');
|
|
60
|
-
|
|
61
|
-
// AgentDB Benchmarks with JS API
|
|
62
|
-
console.log('๐ AGENTDB BENCHMARKS (JS API)\n');
|
|
63
|
-
|
|
64
|
-
const storeEpisode = await this.benchmarkStoreEpisode(1000);
|
|
65
|
-
this.printResult('Store Episode', storeEpisode);
|
|
66
|
-
|
|
67
|
-
const retrieveMemories = await this.benchmarkRetrieveMemories(500);
|
|
68
|
-
this.printResult('Retrieve Memories', retrieveMemories);
|
|
69
|
-
|
|
70
|
-
const queryWithContext = await this.benchmarkQueryWithContext(300);
|
|
71
|
-
this.printResult('Query with Context', queryWithContext);
|
|
72
|
-
|
|
73
|
-
const consolidateSkills = await this.benchmarkConsolidateSkills(10);
|
|
74
|
-
this.printResult('Consolidate Skills', consolidateSkills);
|
|
75
|
-
|
|
76
|
-
const searchSkills = await this.benchmarkSearchSkills(200);
|
|
77
|
-
this.printResult('Search Skills', searchSkills);
|
|
78
|
-
|
|
79
|
-
const totalTime = Date.now() - suiteStartTime;
|
|
80
|
-
|
|
81
|
-
console.log('\nโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
|
|
82
|
-
console.log('โ BENCHMARK COMPLETE โ');
|
|
83
|
-
console.log(`โ Total Time: ${(totalTime / 1000).toFixed(2)}s โ`);
|
|
84
|
-
console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n');
|
|
85
|
-
|
|
86
|
-
// Print performance metrics
|
|
87
|
-
const metrics = this.memory.getMetrics();
|
|
88
|
-
console.log('๐ PERFORMANCE METRICS\n');
|
|
89
|
-
console.log(` Store Operations: ${metrics.storeCount}`);
|
|
90
|
-
console.log(` Avg Store Time: ${metrics.avgStoreTime.toFixed(3)}ms`);
|
|
91
|
-
console.log(` Retrieve Operations: ${metrics.retrieveCount}`);
|
|
92
|
-
console.log(` Avg Retrieve Time: ${metrics.avgRetrieveTime.toFixed(3)}ms\n`);
|
|
93
|
-
|
|
94
|
-
return {
|
|
95
|
-
agentdb: {
|
|
96
|
-
storeEpisode,
|
|
97
|
-
retrieveMemories,
|
|
98
|
-
queryWithContext,
|
|
99
|
-
consolidateSkills,
|
|
100
|
-
searchSkills,
|
|
101
|
-
},
|
|
102
|
-
overall: {
|
|
103
|
-
totalTime,
|
|
104
|
-
timestamp: new Date().toISOString(),
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Benchmark: Store Episode (JS API)
|
|
111
|
-
*/
|
|
112
|
-
private async benchmarkStoreEpisode(iterations: number): Promise<BenchmarkResult> {
|
|
113
|
-
const times: number[] = [];
|
|
114
|
-
|
|
115
|
-
for (let i = 0; i < iterations; i++) {
|
|
116
|
-
const episode: Episode = {
|
|
117
|
-
sessionId: `bench-${i}`,
|
|
118
|
-
taskName: 'navigation',
|
|
119
|
-
confidence: Math.random(),
|
|
120
|
-
success: Math.random() > 0.3,
|
|
121
|
-
outcome: 'Completed navigation task',
|
|
122
|
-
strategy: 'adaptive_planning',
|
|
123
|
-
metadata: { x: i, y: i * 2, latency: Math.random() * 100 },
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const start = performance.now();
|
|
127
|
-
await this.memory.storeEpisode(episode);
|
|
128
|
-
times.push(performance.now() - start);
|
|
129
|
-
|
|
130
|
-
if (i % 100 === 0 && i > 0) {
|
|
131
|
-
process.stderr.write(` Progress: ${i}/${iterations}\r`);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return this.calculateStats('Store Episode', times);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Benchmark: Retrieve Memories (JS API)
|
|
140
|
-
*/
|
|
141
|
-
private async benchmarkRetrieveMemories(iterations: number): Promise<BenchmarkResult> {
|
|
142
|
-
const times: number[] = [];
|
|
143
|
-
|
|
144
|
-
const queries = [
|
|
145
|
-
'navigation task',
|
|
146
|
-
'object detection',
|
|
147
|
-
'path planning',
|
|
148
|
-
'sensor fusion',
|
|
149
|
-
'motor control',
|
|
150
|
-
];
|
|
151
|
-
|
|
152
|
-
for (let i = 0; i < iterations; i++) {
|
|
153
|
-
const query = queries[i % queries.length];
|
|
154
|
-
|
|
155
|
-
const start = performance.now();
|
|
156
|
-
await this.memory.retrieveMemories(query, 5, {
|
|
157
|
-
onlySuccesses: true,
|
|
158
|
-
synthesizeContext: true,
|
|
159
|
-
});
|
|
160
|
-
times.push(performance.now() - start);
|
|
161
|
-
|
|
162
|
-
if (i % 50 === 0 && i > 0) {
|
|
163
|
-
process.stderr.write(` Progress: ${i}/${iterations}\r`);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return this.calculateStats('Retrieve Memories', times);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Benchmark: Query with Context (JS API)
|
|
172
|
-
*/
|
|
173
|
-
private async benchmarkQueryWithContext(iterations: number): Promise<BenchmarkResult> {
|
|
174
|
-
const times: number[] = [];
|
|
175
|
-
|
|
176
|
-
for (let i = 0; i < iterations; i++) {
|
|
177
|
-
const start = performance.now();
|
|
178
|
-
await this.memory.queryWithContext('warehouse navigation', {
|
|
179
|
-
k: 10,
|
|
180
|
-
minConfidence: 0.5,
|
|
181
|
-
synthesizeReasoning: true,
|
|
182
|
-
});
|
|
183
|
-
times.push(performance.now() - start);
|
|
184
|
-
|
|
185
|
-
if (i % 30 === 0 && i > 0) {
|
|
186
|
-
process.stderr.write(` Progress: ${i}/${iterations}\r`);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return this.calculateStats('Query with Context', times);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Benchmark: Consolidate Skills (JS API)
|
|
195
|
-
*/
|
|
196
|
-
private async benchmarkConsolidateSkills(iterations: number): Promise<BenchmarkResult> {
|
|
197
|
-
const times: number[] = [];
|
|
198
|
-
|
|
199
|
-
for (let i = 0; i < iterations; i++) {
|
|
200
|
-
const start = performance.now();
|
|
201
|
-
await this.memory.consolidateSkills({
|
|
202
|
-
minAttempts: 3,
|
|
203
|
-
minReward: 0.7,
|
|
204
|
-
timeWindowDays: 7,
|
|
205
|
-
enablePruning: true,
|
|
206
|
-
});
|
|
207
|
-
times.push(performance.now() - start);
|
|
208
|
-
|
|
209
|
-
if (i % 2 === 0 && i > 0) {
|
|
210
|
-
process.stderr.write(` Progress: ${i}/${iterations}\r`);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return this.calculateStats('Consolidate Skills', times);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Benchmark: Search Skills (JS API)
|
|
219
|
-
*/
|
|
220
|
-
private async benchmarkSearchSkills(iterations: number): Promise<BenchmarkResult> {
|
|
221
|
-
const times: number[] = [];
|
|
222
|
-
|
|
223
|
-
for (let i = 0; i < iterations; i++) {
|
|
224
|
-
const start = performance.now();
|
|
225
|
-
await this.memory.searchSkills('navigation', {
|
|
226
|
-
k: 5,
|
|
227
|
-
minSuccessRate: 0.5,
|
|
228
|
-
sortBy: 'success_rate',
|
|
229
|
-
});
|
|
230
|
-
times.push(performance.now() - start);
|
|
231
|
-
|
|
232
|
-
if (i % 20 === 0 && i > 0) {
|
|
233
|
-
process.stderr.write(` Progress: ${i}/${iterations}\r`);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return this.calculateStats('Search Skills', times);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Calculate statistics from timing data
|
|
242
|
-
*/
|
|
243
|
-
private calculateStats(name: string, times: number[]): BenchmarkResult {
|
|
244
|
-
const sorted = [...times].sort((a, b) => a - b);
|
|
245
|
-
const total = times.reduce((a, b) => a + b, 0);
|
|
246
|
-
|
|
247
|
-
return {
|
|
248
|
-
name,
|
|
249
|
-
iterations: times.length,
|
|
250
|
-
totalTime: total,
|
|
251
|
-
avgTime: total / times.length,
|
|
252
|
-
minTime: sorted[0],
|
|
253
|
-
maxTime: sorted[sorted.length - 1],
|
|
254
|
-
opsPerSec: (times.length / total) * 1000,
|
|
255
|
-
p50: sorted[Math.floor(sorted.length * 0.50)],
|
|
256
|
-
p95: sorted[Math.floor(sorted.length * 0.95)],
|
|
257
|
-
p99: sorted[Math.floor(sorted.length * 0.99)],
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Print benchmark result
|
|
263
|
-
*/
|
|
264
|
-
private printResult(name: string, result: BenchmarkResult): void {
|
|
265
|
-
console.log(`${name}:`);
|
|
266
|
-
console.log(` Iterations: ${result.iterations.toLocaleString()}`);
|
|
267
|
-
console.log(` Avg Time: ${result.avgTime.toFixed(3)}ms`);
|
|
268
|
-
console.log(` Min/Max: ${result.minTime.toFixed(3)}ms / ${result.maxTime.toFixed(3)}ms`);
|
|
269
|
-
console.log(` p50/p95/p99: ${result.p50.toFixed(3)}ms / ${result.p95.toFixed(3)}ms / ${result.p99.toFixed(3)}ms`);
|
|
270
|
-
console.log(` Ops/sec: ${result.opsPerSec.toFixed(0)}`);
|
|
271
|
-
console.log('');
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* Export results to JSON
|
|
276
|
-
*/
|
|
277
|
-
async exportResults(suite: BenchmarkSuite, filename: string): Promise<void> {
|
|
278
|
-
const fs = await import('fs/promises');
|
|
279
|
-
await fs.writeFile(filename, JSON.stringify(suite, null, 2));
|
|
280
|
-
console.log(`๐ Results exported to ${filename}`);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
async close(): Promise<void> {
|
|
284
|
-
await this.memory.close();
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// CLI entry point
|
|
289
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
290
|
-
const benchmark = new OptimizedBenchmark();
|
|
291
|
-
|
|
292
|
-
try {
|
|
293
|
-
await benchmark.initialize();
|
|
294
|
-
const results = await benchmark.runAll();
|
|
295
|
-
await benchmark.exportResults(results, './optimized-benchmark-results.json');
|
|
296
|
-
} catch (error) {
|
|
297
|
-
console.error('โ Benchmark failed:', error);
|
|
298
|
-
process.exit(1);
|
|
299
|
-
} finally {
|
|
300
|
-
await benchmark.close();
|
|
301
|
-
}
|
|
302
|
-
}
|