@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.
Files changed (55) hide show
  1. package/dist/benchmark.d.ts +97 -0
  2. package/dist/benchmark.d.ts.map +1 -0
  3. package/dist/benchmark.js +330 -0
  4. package/dist/benchmark.js.map +1 -0
  5. package/dist/cli.d.ts +6 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +79 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/enhanced-memory.d.ts +118 -0
  10. package/dist/enhanced-memory.d.ts.map +1 -0
  11. package/dist/enhanced-memory.js +296 -0
  12. package/dist/enhanced-memory.js.map +1 -0
  13. package/dist/enhanced-server.d.ts +122 -0
  14. package/dist/enhanced-server.d.ts.map +1 -0
  15. package/dist/enhanced-server.js +361 -0
  16. package/dist/enhanced-server.js.map +1 -0
  17. package/dist/flow-orchestrator.d.ts +75 -0
  18. package/dist/flow-orchestrator.d.ts.map +1 -0
  19. package/dist/flow-orchestrator.js +350 -0
  20. package/dist/flow-orchestrator.js.map +1 -0
  21. package/dist/hybrid-benchmark.d.ts +44 -0
  22. package/dist/hybrid-benchmark.d.ts.map +1 -0
  23. package/dist/hybrid-benchmark.js +232 -0
  24. package/dist/hybrid-benchmark.js.map +1 -0
  25. package/dist/hybrid-memory.d.ts +81 -0
  26. package/dist/hybrid-memory.d.ts.map +1 -0
  27. package/dist/hybrid-memory.js +296 -0
  28. package/dist/hybrid-memory.js.map +1 -0
  29. package/dist/index.d.ts +10 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +10 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/interface.d.ts +38 -0
  34. package/dist/interface.d.ts.map +1 -0
  35. package/dist/interface.js +75 -0
  36. package/dist/interface.js.map +1 -0
  37. package/dist/memory.d.ts +52 -0
  38. package/dist/memory.d.ts.map +1 -0
  39. package/dist/memory.js +230 -0
  40. package/dist/memory.js.map +1 -0
  41. package/dist/optimized-benchmark.d.ts +74 -0
  42. package/dist/optimized-benchmark.d.ts.map +1 -0
  43. package/dist/optimized-benchmark.js +231 -0
  44. package/dist/optimized-benchmark.js.map +1 -0
  45. package/dist/server.d.ts +55 -0
  46. package/dist/server.d.ts.map +1 -0
  47. package/dist/server.js +147 -0
  48. package/dist/server.js.map +1 -0
  49. package/package.json +3 -2
  50. package/src/enhanced-server.ts +1 -1
  51. package/src/flow-orchestrator.ts +177 -117
  52. package/src/hybrid-memory.ts +2 -2
  53. package/src/memory.ts +171 -52
  54. package/src/optimized-benchmark.ts +0 -302
  55. package/src/optimized-memory.ts +0 -271
package/dist/server.js ADDED
@@ -0,0 +1,147 @@
1
+ /**
2
+ * ROS3 MCP Server implementation - Simplified version
3
+ */
4
+ import { ROS3Interface } from './interface.js';
5
+ import { AgentDBMemory } from './memory.js';
6
+ export class ROS3McpServer {
7
+ ros3;
8
+ memory;
9
+ name;
10
+ version;
11
+ constructor(config = {}) {
12
+ const { name = 'ros3-mcp-server', version = '1.0.0', dbPath = './ros3-agentdb.db', } = config;
13
+ this.name = name;
14
+ this.version = version;
15
+ // Initialize ROS3 interface
16
+ this.ros3 = new ROS3Interface();
17
+ // Initialize AgentDB memory
18
+ this.memory = new AgentDBMemory(dbPath);
19
+ }
20
+ async start() {
21
+ // Initialize AgentDB
22
+ await this.memory.initialize();
23
+ console.error(`${this.name} v${this.version} started`);
24
+ console.error('AgentDB initialized and ready');
25
+ console.error('');
26
+ console.error('Available tools:');
27
+ console.error(' - move_robot: Move robot to target pose');
28
+ console.error(' - get_pose: Get current robot pose');
29
+ console.error(' - get_status: Get robot status');
30
+ console.error(' - read_lidar: Read LIDAR data');
31
+ console.error(' - detect_objects: Detect objects from camera');
32
+ console.error(' - query_memory: Query past experiences');
33
+ console.error(' - consolidate_skills: Learn from experiences');
34
+ console.error(' - get_memory_stats: Get memory statistics');
35
+ }
36
+ async stop() {
37
+ await this.memory.close();
38
+ console.error(`${this.name} stopped`);
39
+ }
40
+ // Tool implementations
41
+ async moveRobot(params) {
42
+ const { x, y, z, roll, pitch, yaw, speed = 0.5, frame = 'world' } = params;
43
+ const startTime = Date.now();
44
+ try {
45
+ await this.ros3.moveToPose({ x, y, z, roll, pitch, yaw }, speed, frame);
46
+ const latency = Date.now() - startTime;
47
+ await this.memory.storeEpisode({
48
+ sessionId: `motion-${Date.now()}`,
49
+ taskName: 'move_robot',
50
+ confidence: 0.9,
51
+ success: true,
52
+ outcome: `Moved to [${x}, ${y}, ${z}] in ${latency}ms`,
53
+ strategy: `speed_${speed}_frame_${frame}`,
54
+ metadata: { x, y, z, roll, pitch, yaw, speed, frame, latency },
55
+ });
56
+ return `Robot moved to [${x}, ${y}, ${z}] in ${frame} frame. Completed in ${latency}ms.`;
57
+ }
58
+ catch (error) {
59
+ await this.memory.storeEpisode({
60
+ sessionId: `motion-${Date.now()}`,
61
+ taskName: 'move_robot',
62
+ confidence: 0.0,
63
+ success: false,
64
+ outcome: `Failed: ${error.message}`,
65
+ metadata: { x, y, z, roll, pitch, yaw, speed, frame },
66
+ });
67
+ throw error;
68
+ }
69
+ }
70
+ async getPose() {
71
+ const pose = await this.ros3.getCurrentPose();
72
+ return `Current pose: [${pose.x}, ${pose.y}, ${pose.z}] (roll=${pose.roll}, pitch=${pose.pitch}, yaw=${pose.yaw})`;
73
+ }
74
+ async getStatus() {
75
+ const status = await this.ros3.getStatus();
76
+ return `Robot status: ${status.status}, Health: ${status.health}`;
77
+ }
78
+ async readLidar(params) {
79
+ const { filter = 'all', max_points = 10000 } = params;
80
+ const startTime = Date.now();
81
+ const cloud = await this.ros3.getLidarData(filter, max_points);
82
+ const latency = Date.now() - startTime;
83
+ await this.memory.storeEpisode({
84
+ sessionId: `lidar-${Date.now()}`,
85
+ taskName: 'read_lidar',
86
+ confidence: 1.0,
87
+ success: true,
88
+ outcome: `Retrieved ${cloud.points.length} points in ${latency}ms`,
89
+ metadata: { filter, max_points, num_points: cloud.points.length, latency },
90
+ });
91
+ return `LIDAR data: ${cloud.points.length} points (filter: ${filter}, latency: ${latency}ms)`;
92
+ }
93
+ async detectObjects(params) {
94
+ const { camera, confidence_threshold = 0.5 } = params;
95
+ const startTime = Date.now();
96
+ const detections = await this.ros3.detectObjects(camera, confidence_threshold);
97
+ const latency = Date.now() - startTime;
98
+ await this.memory.storeEpisode({
99
+ sessionId: `vision-${Date.now()}`,
100
+ taskName: 'detect_objects',
101
+ confidence: 0.9,
102
+ success: true,
103
+ outcome: `Detected ${detections.length} objects in ${latency}ms`,
104
+ metadata: { camera, confidence_threshold, num_detections: detections.length, latency },
105
+ });
106
+ return `Detected ${detections.length} objects from ${camera} camera:\n${JSON.stringify(detections, null, 2)}`;
107
+ }
108
+ async queryMemory(params) {
109
+ const { query, k = 5, only_successes = false, min_confidence = 0.0 } = params;
110
+ const result = await this.memory.queryWithContext(query, { k, minConfidence: min_confidence });
111
+ const filteredMemories = only_successes
112
+ ? result.memories.filter((m) => m.success)
113
+ : result.memories;
114
+ return `Found ${filteredMemories.length} memories for "${query}":\n${JSON.stringify(filteredMemories, null, 2)}`;
115
+ }
116
+ async consolidateSkills(params) {
117
+ const { min_attempts = 3, min_reward = 0.7, time_window_days = 7 } = params || {};
118
+ await this.memory.consolidateSkills({
119
+ minAttempts: min_attempts,
120
+ minReward: min_reward,
121
+ timeWindowDays: time_window_days,
122
+ });
123
+ return `Skills consolidated (min_attempts: ${min_attempts}, min_reward: ${min_reward}, window: ${time_window_days} days)`;
124
+ }
125
+ async getMemoryStats() {
126
+ const stats = await this.memory.getStats();
127
+ return `AgentDB Statistics:\n${stats.stats}`;
128
+ }
129
+ // Get server info
130
+ getInfo() {
131
+ return {
132
+ name: this.name,
133
+ version: this.version,
134
+ tools: [
135
+ 'move_robot',
136
+ 'get_pose',
137
+ 'get_status',
138
+ 'read_lidar',
139
+ 'detect_objects',
140
+ 'query_memory',
141
+ 'consolidate_skills',
142
+ 'get_memory_stats',
143
+ ],
144
+ };
145
+ }
146
+ }
147
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentic-robotics/mcp",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Model Context Protocol server for agentic robotics with AgentDB integration",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -27,6 +27,7 @@
27
27
  },
28
28
  "scripts": {
29
29
  "build": "tsc",
30
+ "prepublishOnly": "npm run build",
30
31
  "dev": "tsx src/cli.ts",
31
32
  "start": "node dist/cli.js",
32
33
  "test": "vitest",
@@ -34,7 +35,7 @@
34
35
  "benchmark:hybrid": "tsx src/hybrid-benchmark.ts"
35
36
  },
36
37
  "dependencies": {
37
- "@agentic-robotics/core": "^0.1.3",
38
+ "@agentic-robotics/core": "^0.2.0",
38
39
  "@modelcontextprotocol/sdk": "^1.0.0",
39
40
  "agentdb": "^1.6.1",
40
41
  "agentic-flow": "^1.10.2",
@@ -27,7 +27,7 @@ export interface EnhancedROS3McpServerConfig {
27
27
  export class EnhancedROS3McpServer {
28
28
  private ros3: ROS3Interface;
29
29
  private memory: EnhancedAgentDBMemory;
30
- private orchestrator: FlowOrchestrator;
30
+ private orchestrator?: FlowOrchestrator;
31
31
  private name: string;
32
32
  private version: string;
33
33
  private config: EnhancedROS3McpServerConfig;
@@ -1,15 +1,13 @@
1
1
  /**
2
- * Agentic Flow Orchestration Integration
2
+ * Agentic Flow Orchestration Integration - SECURE VERSION
3
3
  *
4
4
  * Integrates agentic-flow's 66 agents and 213 MCP tools for
5
5
  * multi-robot coordination and complex task execution
6
+ *
7
+ * SECURITY: All command execution uses secure spawn() with argument arrays
6
8
  */
7
9
 
8
10
  import { spawn } from 'child_process';
9
- import { promisify } from 'util';
10
- import { exec } from 'child_process';
11
-
12
- const execAsync = promisify(exec);
13
11
 
14
12
  export interface AgentTask {
15
13
  id: string;
@@ -47,12 +45,63 @@ export interface OrchestrationMetrics {
47
45
  toolUsage: Record<string, number>;
48
46
  }
49
47
 
48
+ /**
49
+ * Secure helper to spawn commands with proper argument handling
50
+ */
51
+ function spawnAsync(
52
+ command: string,
53
+ args: string[],
54
+ options: { timeout?: number } = {}
55
+ ): Promise<{ stdout: string; stderr: string; code: number }> {
56
+ return new Promise((resolve, reject) => {
57
+ const child = spawn(command, args, {
58
+ shell: false, // Critical: disable shell interpretation
59
+ timeout: options.timeout,
60
+ });
61
+
62
+ let stdout = '';
63
+ let stderr = '';
64
+
65
+ child.stdout?.on('data', (data) => {
66
+ stdout += data.toString();
67
+ });
68
+
69
+ child.stderr?.on('data', (data) => {
70
+ stderr += data.toString();
71
+ });
72
+
73
+ child.on('close', (code) => {
74
+ resolve({ stdout, stderr, code: code || 0 });
75
+ });
76
+
77
+ child.on('error', (error) => {
78
+ reject(error);
79
+ });
80
+ });
81
+ }
82
+
83
+ /**
84
+ * Validate and sanitize task parameters
85
+ */
86
+ function validateTaskParams(params: Record<string, any>): void {
87
+ // Check for command injection attempts
88
+ const paramStr = JSON.stringify(params);
89
+ if (paramStr.includes(';') || paramStr.includes('|') || paramStr.includes('&')) {
90
+ throw new Error('Invalid characters in task parameters');
91
+ }
92
+ }
93
+
50
94
  export class FlowOrchestrator {
51
95
  private config: SwarmConfig;
52
96
  private metrics: OrchestrationMetrics;
53
97
  private initialized: boolean = false;
54
98
 
55
99
  constructor(config: SwarmConfig = {}) {
100
+ // Validate config
101
+ if (config.numAgents && (config.numAgents < 1 || config.numAgents > 200)) {
102
+ throw new Error('numAgents must be between 1 and 200');
103
+ }
104
+
56
105
  this.config = {
57
106
  numAgents: config.numAgents || 66,
58
107
  strategy: config.strategy || 'adaptive',
@@ -77,16 +126,13 @@ export class FlowOrchestrator {
77
126
  const startTime = Date.now();
78
127
 
79
128
  try {
80
- // Initialize agentic-flow with configuration
81
- const cmd = [
82
- 'npx agentic-flow init',
83
- `--agents ${this.config.numAgents}`,
84
- `--strategy ${this.config.strategy}`,
85
- this.config.reasoningEnabled ? '--enable-reasoning' : '',
86
- this.config.learningEnabled ? '--enable-learning' : '',
87
- ].filter(Boolean).join(' ');
129
+ // Secure initialization with spawn
130
+ const args = ['agentic-flow', 'init', '--agents', this.config.numAgents!.toString(), '--strategy', this.config.strategy!];
131
+
132
+ if (this.config.reasoningEnabled) args.push('--enable-reasoning');
133
+ if (this.config.learningEnabled) args.push('--enable-learning');
88
134
 
89
- await execAsync(cmd);
135
+ await spawnAsync('npx', args);
90
136
 
91
137
  const initTime = Date.now() - startTime;
92
138
  console.error(`🌊 Agentic Flow initialized (${this.config.numAgents} agents, ${initTime}ms)`);
@@ -97,29 +143,45 @@ export class FlowOrchestrator {
97
143
  }
98
144
  }
99
145
 
100
- /**
101
- * Execute a single task using agentic-flow orchestration
102
- */
103
146
  async executeTask(task: AgentTask): Promise<AgentResult> {
147
+ if (!this.initialized) {
148
+ throw new Error('FlowOrchestrator not initialized. Call initialize() first.');
149
+ }
150
+
151
+ // Validate input
152
+ validateTaskParams(task.params);
153
+
104
154
  const startTime = Date.now();
105
155
  this.metrics.totalTasks++;
106
156
 
107
157
  try {
108
- const cmd = [
109
- 'npx agentic-flow execute',
110
- `--task-type "${task.type}"`,
111
- `--priority ${task.priority}`,
112
- `--params '${JSON.stringify(task.params)}'`,
113
- task.timeout ? `--timeout ${task.timeout}` : '',
114
- task.retries ? `--retries ${task.retries}` : '',
115
- this.config.reasoningEnabled ? '--enable-reasoning' : '',
116
- '--format json',
117
- ].filter(Boolean).join(' ');
118
-
119
- const { stdout } = await execAsync(cmd, { timeout: task.timeout || 30000 });
158
+ const args = [
159
+ 'agentic-flow',
160
+ 'execute',
161
+ '--task-type',
162
+ task.type,
163
+ '--priority',
164
+ task.priority,
165
+ '--params',
166
+ JSON.stringify(task.params),
167
+ '--format',
168
+ 'json',
169
+ ];
170
+
171
+ if (task.timeout) args.push('--timeout', task.timeout.toString());
172
+ if (task.retries) args.push('--retries', task.retries.toString());
173
+ if (this.config.reasoningEnabled) args.push('--enable-reasoning');
174
+
175
+ const { stdout, code } = await spawnAsync('npx', args, {
176
+ timeout: task.timeout || 30000,
177
+ });
178
+
179
+ if (code !== 0) {
180
+ throw new Error(`Agentic-flow execution failed with code ${code}`);
181
+ }
120
182
 
121
183
  const lines = stdout.trim().split('\n');
122
- const jsonLine = lines.find(line => line.startsWith('{'));
184
+ const jsonLine = lines.find((line) => line.startsWith('{'));
123
185
 
124
186
  if (jsonLine) {
125
187
  const data = JSON.parse(jsonLine);
@@ -159,30 +221,41 @@ export class FlowOrchestrator {
159
221
  }
160
222
  }
161
223
 
162
- /**
163
- * Execute multiple tasks in parallel using swarm intelligence
164
- */
165
224
  async executeSwarm(tasks: AgentTask[]): Promise<AgentResult[]> {
166
- const startTime = Date.now();
225
+ if (!this.initialized) {
226
+ throw new Error('FlowOrchestrator not initialized. Call initialize() first.');
227
+ }
167
228
 
229
+ const startTime = Date.now();
168
230
  console.error(`🐝 Executing swarm with ${tasks.length} tasks`);
169
231
 
170
232
  try {
171
- // Use agentic-flow's swarm coordination
172
- const tasksJson = JSON.stringify(tasks);
173
- const cmd = [
174
- 'npx agentic-flow swarm',
175
- `--tasks '${tasksJson}'`,
176
- `--strategy ${this.config.strategy}`,
177
- `--num-agents ${this.config.numAgents}`,
178
- this.config.reasoningEnabled ? '--enable-reasoning' : '',
179
- '--format json',
180
- ].filter(Boolean).join(' ');
181
-
182
- const { stdout } = await execAsync(cmd, { timeout: 60000 });
233
+ // Validate all tasks
234
+ tasks.forEach((task) => validateTaskParams(task.params));
235
+
236
+ const args = [
237
+ 'agentic-flow',
238
+ 'swarm',
239
+ '--tasks',
240
+ JSON.stringify(tasks),
241
+ '--strategy',
242
+ this.config.strategy!,
243
+ '--num-agents',
244
+ this.config.numAgents!.toString(),
245
+ '--format',
246
+ 'json',
247
+ ];
248
+
249
+ if (this.config.reasoningEnabled) args.push('--enable-reasoning');
250
+
251
+ const { stdout, code } = await spawnAsync('npx', args, { timeout: 60000 });
252
+
253
+ if (code !== 0) {
254
+ throw new Error(`Swarm execution failed with code ${code}`);
255
+ }
183
256
 
184
257
  const lines = stdout.trim().split('\n');
185
- const jsonLine = lines.find(line => line.startsWith('[') || line.startsWith('{'));
258
+ const jsonLine = lines.find((line) => line.startsWith('[') || line.startsWith('{'));
186
259
 
187
260
  if (jsonLine) {
188
261
  const data = JSON.parse(jsonLine);
@@ -206,8 +279,7 @@ export class FlowOrchestrator {
206
279
  } catch (error: any) {
207
280
  console.error(`❌ Swarm execution failed: ${error.message}`);
208
281
 
209
- // Return individual failures
210
- return tasks.map(task => ({
282
+ return tasks.map((task) => ({
211
283
  taskId: task.id,
212
284
  success: false,
213
285
  result: { error: error.message },
@@ -218,9 +290,6 @@ export class FlowOrchestrator {
218
290
  }
219
291
  }
220
292
 
221
- /**
222
- * Coordinate multiple robots using agentic-flow
223
- */
224
293
  async coordinateRobots(
225
294
  robots: string[],
226
295
  mission: {
@@ -234,22 +303,38 @@ export class FlowOrchestrator {
234
303
  executionPlan: any;
235
304
  estimatedTime: number;
236
305
  }> {
306
+ if (!this.initialized) {
307
+ throw new Error('FlowOrchestrator not initialized. Call initialize() first.');
308
+ }
309
+
237
310
  const startTime = Date.now();
238
311
 
239
312
  try {
240
- const cmd = [
241
- 'npx agentic-flow coordinate',
242
- `--robots '${JSON.stringify(robots)}'`,
243
- `--mission-type "${mission.type}"`,
244
- `--objectives '${JSON.stringify(mission.objectives)}'`,
245
- mission.constraints ? `--constraints '${JSON.stringify(mission.constraints)}'` : '',
246
- '--format json',
247
- ].filter(Boolean).join(' ');
313
+ const args = [
314
+ 'agentic-flow',
315
+ 'coordinate',
316
+ '--robots',
317
+ JSON.stringify(robots),
318
+ '--mission-type',
319
+ mission.type,
320
+ '--objectives',
321
+ JSON.stringify(mission.objectives),
322
+ '--format',
323
+ 'json',
324
+ ];
325
+
326
+ if (mission.constraints) {
327
+ args.push('--constraints', JSON.stringify(mission.constraints));
328
+ }
329
+
330
+ const { stdout, code } = await spawnAsync('npx', args, { timeout: 30000 });
248
331
 
249
- const { stdout } = await execAsync(cmd, { timeout: 30000 });
332
+ if (code !== 0) {
333
+ throw new Error(`Coordination failed with code ${code}`);
334
+ }
250
335
 
251
336
  const lines = stdout.trim().split('\n');
252
- const jsonLine = lines.find(line => line.startsWith('{'));
337
+ const jsonLine = lines.find((line) => line.startsWith('{'));
253
338
 
254
339
  if (jsonLine) {
255
340
  const data = JSON.parse(jsonLine);
@@ -267,20 +352,10 @@ export class FlowOrchestrator {
267
352
 
268
353
  throw new Error('No valid JSON response from coordination');
269
354
  } catch (error: any) {
270
- console.error(`❌ Coordination failed: ${error.message}`);
271
-
272
- return {
273
- success: false,
274
- assignments: {},
275
- executionPlan: {},
276
- estimatedTime: 0,
277
- };
355
+ throw new Error(`Robot coordination failed: ${error.message}`);
278
356
  }
279
357
  }
280
358
 
281
- /**
282
- * Use ReasoningBank for complex decision making
283
- */
284
359
  async reasonAboutTask(
285
360
  context: string,
286
361
  options: {
@@ -294,29 +369,29 @@ export class FlowOrchestrator {
294
369
  confidence: number;
295
370
  alternatives: string[];
296
371
  }> {
297
- const startTime = Date.now();
372
+ if (!this.initialized) {
373
+ throw new Error('FlowOrchestrator not initialized. Call initialize() first.');
374
+ }
298
375
 
299
376
  try {
300
- const cmd = [
301
- 'npx agentic-flow reason',
302
- `--context "${context}"`,
303
- options.useMemory ? '--use-memory' : '',
304
- options.synthesizeStrategy ? '--synthesize-strategy' : '',
305
- options.explainReasoning ? '--explain-reasoning' : '',
306
- '--format json',
307
- ].filter(Boolean).join(' ');
377
+ const args = ['agentic-flow', 'reason', '--context', context, '--format', 'json'];
378
+
379
+ if (options.useMemory) args.push('--use-memory');
380
+ if (options.synthesizeStrategy) args.push('--synthesize-strategy');
381
+ if (options.explainReasoning) args.push('--explain-reasoning');
308
382
 
309
- const { stdout } = await execAsync(cmd, { timeout: 15000 });
383
+ const { stdout, code } = await spawnAsync('npx', args, { timeout: 15000 });
384
+
385
+ if (code !== 0) {
386
+ throw new Error(`Reasoning failed with code ${code}`);
387
+ }
310
388
 
311
389
  const lines = stdout.trim().split('\n');
312
- const jsonLine = lines.find(line => line.startsWith('{'));
390
+ const jsonLine = lines.find((line) => line.startsWith('{'));
313
391
 
314
392
  if (jsonLine) {
315
393
  const data = JSON.parse(jsonLine);
316
394
 
317
- const reasonTime = Date.now() - startTime;
318
- console.error(`🧠 Reasoning completed in ${reasonTime}ms`);
319
-
320
395
  return {
321
396
  decision: data.decision || '',
322
397
  reasoning: data.reasoning || '',
@@ -327,26 +402,25 @@ export class FlowOrchestrator {
327
402
 
328
403
  throw new Error('No valid JSON response from reasoning');
329
404
  } catch (error: any) {
330
- console.error(`❌ Reasoning failed: ${error.message}`);
331
-
332
- return {
333
- decision: '',
334
- reasoning: error.message,
335
- confidence: 0,
336
- alternatives: [],
337
- };
405
+ throw new Error(`Reasoning failed: ${error.message}`);
338
406
  }
339
407
  }
340
408
 
341
- /**
342
- * Get available MCP tools from agentic-flow
343
- */
344
409
  async getAvailableTools(): Promise<string[]> {
345
410
  try {
346
- const { stdout } = await execAsync('npx agentic-flow list-tools --format json');
411
+ const { stdout, code } = await spawnAsync('npx', [
412
+ 'agentic-flow',
413
+ 'list-tools',
414
+ '--format',
415
+ 'json',
416
+ ]);
417
+
418
+ if (code !== 0) {
419
+ throw new Error('Failed to list tools');
420
+ }
347
421
 
348
422
  const lines = stdout.trim().split('\n');
349
- const jsonLine = lines.find(line => line.startsWith('['));
423
+ const jsonLine = lines.find((line) => line.startsWith('['));
350
424
 
351
425
  if (jsonLine) {
352
426
  const tools = JSON.parse(jsonLine);
@@ -356,38 +430,27 @@ export class FlowOrchestrator {
356
430
 
357
431
  return [];
358
432
  } catch (error: any) {
359
- console.error('⚠️ Could not list tools:', error.message);
360
- return [];
433
+ throw new Error(`Failed to list tools: ${error.message}`);
361
434
  }
362
435
  }
363
436
 
364
- /**
365
- * Get metrics and statistics
366
- */
367
437
  getMetrics(): OrchestrationMetrics {
368
438
  return {
369
439
  ...this.metrics,
370
- avgExecutionTime: this.metrics.totalTasks > 0
371
- ? this.metrics.avgExecutionTime / this.metrics.totalTasks
372
- : 0,
440
+ avgExecutionTime:
441
+ this.metrics.totalTasks > 0 ? this.metrics.avgExecutionTime / this.metrics.totalTasks : 0,
373
442
  };
374
443
  }
375
444
 
376
- /**
377
- * Update internal metrics
378
- */
379
445
  private updateMetrics(data: any, executionTime: number): void {
380
- // Update execution time
381
446
  this.metrics.avgExecutionTime += executionTime;
382
447
 
383
- // Track agent utilization
384
448
  if (data.agents_used) {
385
449
  for (const agent of data.agents_used) {
386
450
  this.metrics.agentUtilization[agent] = (this.metrics.agentUtilization[agent] || 0) + 1;
387
451
  }
388
452
  }
389
453
 
390
- // Track tool usage
391
454
  if (data.tools_used) {
392
455
  for (const tool of data.tools_used) {
393
456
  this.metrics.toolUsage[tool] = (this.metrics.toolUsage[tool] || 0) + 1;
@@ -395,9 +458,6 @@ export class FlowOrchestrator {
395
458
  }
396
459
  }
397
460
 
398
- /**
399
- * Reset metrics
400
- */
401
461
  resetMetrics(): void {
402
462
  this.metrics = {
403
463
  totalTasks: 0,
@@ -13,7 +13,7 @@ import type { Episode, Memory } from './memory.js';
13
13
  const execAsync = promisify(exec);
14
14
 
15
15
  export class HybridAgentDBMemory {
16
- private db: Database.Database;
16
+ private db!: Database.Database;
17
17
  private dbPath: string;
18
18
  private initialized: boolean = false;
19
19
  private performanceMetrics: {
@@ -363,7 +363,7 @@ export class HybridAgentDBMemory {
363
363
  COUNT(DISTINCT task_name) as unique_tasks,
364
364
  AVG(confidence) as avg_confidence
365
365
  FROM reflexion_episodes
366
- `).get();
366
+ `).get() || {};
367
367
 
368
368
  return {
369
369
  ...stats,