@sparkleideas/ruv-swarm 1.0.18-patch.1
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/README.md +1565 -0
- package/bin/ruv-swarm-clean.js +1872 -0
- package/bin/ruv-swarm-memory.js +119 -0
- package/bin/ruv-swarm-secure-heartbeat.js +1549 -0
- package/bin/ruv-swarm-secure.js +1689 -0
- package/package.json +221 -0
- package/src/agent.ts +342 -0
- package/src/benchmark.js +267 -0
- package/src/claude-flow-enhanced.js +839 -0
- package/src/claude-integration/advanced-commands.js +561 -0
- package/src/claude-integration/core.js +112 -0
- package/src/claude-integration/docs.js +1548 -0
- package/src/claude-integration/env-template.js +39 -0
- package/src/claude-integration/index.js +209 -0
- package/src/claude-integration/remote.js +408 -0
- package/src/cli-diagnostics.js +364 -0
- package/src/cognitive-pattern-evolution.js +1317 -0
- package/src/daa-cognition.js +977 -0
- package/src/daa-service.d.ts +298 -0
- package/src/daa-service.js +1116 -0
- package/src/diagnostics.js +533 -0
- package/src/errors.js +528 -0
- package/src/github-coordinator/README.md +193 -0
- package/src/github-coordinator/claude-hooks.js +162 -0
- package/src/github-coordinator/gh-cli-coordinator.js +260 -0
- package/src/hooks/cli.js +82 -0
- package/src/hooks/index.js +1900 -0
- package/src/index-enhanced.d.ts +371 -0
- package/src/index-enhanced.js +734 -0
- package/src/index.d.ts +287 -0
- package/src/index.js +405 -0
- package/src/index.ts +457 -0
- package/src/logger.js +182 -0
- package/src/logging-config.js +179 -0
- package/src/mcp-daa-tools.js +735 -0
- package/src/mcp-tools-benchmarks.js +328 -0
- package/src/mcp-tools-enhanced.js +2863 -0
- package/src/memory-config.js +42 -0
- package/src/meta-learning-framework.js +1359 -0
- package/src/neural-agent.js +830 -0
- package/src/neural-coordination-protocol.js +1363 -0
- package/src/neural-models/README.md +118 -0
- package/src/neural-models/autoencoder.js +543 -0
- package/src/neural-models/base.js +269 -0
- package/src/neural-models/cnn.js +497 -0
- package/src/neural-models/gnn.js +447 -0
- package/src/neural-models/gru.js +536 -0
- package/src/neural-models/index.js +273 -0
- package/src/neural-models/lstm.js +551 -0
- package/src/neural-models/neural-presets-complete.js +1306 -0
- package/src/neural-models/presets/graph.js +392 -0
- package/src/neural-models/presets/index.js +279 -0
- package/src/neural-models/presets/nlp.js +328 -0
- package/src/neural-models/presets/timeseries.js +368 -0
- package/src/neural-models/presets/vision.js +387 -0
- package/src/neural-models/resnet.js +534 -0
- package/src/neural-models/transformer.js +515 -0
- package/src/neural-models/vae.js +489 -0
- package/src/neural-network-manager.js +1938 -0
- package/src/neural-network.ts +296 -0
- package/src/neural.js +574 -0
- package/src/performance-benchmarks.js +898 -0
- package/src/performance.js +458 -0
- package/src/persistence-pooled.js +695 -0
- package/src/persistence.js +480 -0
- package/src/schemas.js +864 -0
- package/src/security.js +218 -0
- package/src/singleton-container.js +183 -0
- package/src/sqlite-pool.js +587 -0
- package/src/sqlite-worker.js +141 -0
- package/src/types.ts +164 -0
- package/src/utils.ts +286 -0
- package/src/wasm-loader.js +601 -0
- package/src/wasm-loader2.js +404 -0
- package/src/wasm-memory-optimizer.js +783 -0
- package/src/wasm-types.d.ts +63 -0
- package/wasm/README.md +347 -0
- package/wasm/neuro-divergent.wasm +0 -0
- package/wasm/package.json +18 -0
- package/wasm/ruv-fann.wasm +0 -0
- package/wasm/ruv_swarm_simd.wasm +0 -0
- package/wasm/ruv_swarm_wasm.d.ts +391 -0
- package/wasm/ruv_swarm_wasm.js +2164 -0
- package/wasm/ruv_swarm_wasm_bg.wasm +0 -0
- package/wasm/ruv_swarm_wasm_bg.wasm.d.ts +123 -0
- package/wasm/wasm-bindings-loader.mjs +435 -0
- package/wasm/wasm-updates.md +684 -0
|
@@ -0,0 +1,1549 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Production-ready @sparkleideas/ruv-swarm MCP server with security and stability
|
|
4
|
+
* Combines security fixes from Issue #107 with crash protection
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { spawn } from 'child_process';
|
|
8
|
+
import { setupClaudeIntegration, invokeClaudeWithSwarm } from '../src/claude-integration/index.js';
|
|
9
|
+
import { RuvSwarm } from '../src/index-enhanced.js';
|
|
10
|
+
import { EnhancedMCPTools } from '../src/mcp-tools-enhanced.js';
|
|
11
|
+
import { daaMcpTools } from '../src/mcp-daa-tools.js';
|
|
12
|
+
import mcpToolsEnhanced from '../src/mcp-tools-enhanced.js';
|
|
13
|
+
import { Logger } from '../src/logger.js';
|
|
14
|
+
import { CommandSanitizer, SecurityError } from '../src/security.js';
|
|
15
|
+
import { readFileSync } from 'fs';
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
17
|
+
import { dirname, join } from 'path';
|
|
18
|
+
|
|
19
|
+
// Get version from package.json
|
|
20
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
21
|
+
const __dirname = dirname(__filename);
|
|
22
|
+
|
|
23
|
+
async function getVersion() {
|
|
24
|
+
try {
|
|
25
|
+
const packagePath = join(__dirname, '..', 'package.json');
|
|
26
|
+
const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
27
|
+
return packageJson.version;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
return 'unknown';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Stability configuration
|
|
34
|
+
const MAX_RESTARTS = 10;
|
|
35
|
+
const RESTART_DELAY = 1000; // 1 second
|
|
36
|
+
const RESTART_RESET_TIME = 300000; // 5 minutes
|
|
37
|
+
|
|
38
|
+
let restartCount = 0;
|
|
39
|
+
let lastRestartTime = 0;
|
|
40
|
+
let isStabilityMode = false;
|
|
41
|
+
let childProcess = null;
|
|
42
|
+
|
|
43
|
+
// Input validation constants and functions
|
|
44
|
+
const VALID_TOPOLOGIES = ['mesh', 'hierarchical', 'ring', 'star'];
|
|
45
|
+
const VALID_AGENT_TYPES = ['researcher', 'coder', 'analyst', 'optimizer', 'coordinator', 'architect', 'tester'];
|
|
46
|
+
const MAX_AGENTS_LIMIT = 100;
|
|
47
|
+
const MIN_AGENTS_LIMIT = 1;
|
|
48
|
+
|
|
49
|
+
class ValidationError extends Error {
|
|
50
|
+
constructor(message, parameter = null) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.name = 'ValidationError';
|
|
53
|
+
this.parameter = parameter;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function validateTopology(topology) {
|
|
58
|
+
if (!topology || typeof topology !== 'string') {
|
|
59
|
+
throw new ValidationError('Topology must be a non-empty string', 'topology');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!VALID_TOPOLOGIES.includes(topology.toLowerCase())) {
|
|
63
|
+
throw new ValidationError(
|
|
64
|
+
`Invalid topology '${topology}'. Valid topologies are: ${VALID_TOPOLOGIES.join(', ')}`,
|
|
65
|
+
'topology'
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return topology.toLowerCase();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function validateMaxAgents(maxAgents) {
|
|
73
|
+
// Handle string input
|
|
74
|
+
if (typeof maxAgents === 'string') {
|
|
75
|
+
const parsed = parseInt(maxAgents, 10);
|
|
76
|
+
if (isNaN(parsed)) {
|
|
77
|
+
throw new ValidationError(
|
|
78
|
+
`Invalid maxAgents '${maxAgents}'. Must be a number between ${MIN_AGENTS_LIMIT} and ${MAX_AGENTS_LIMIT}`,
|
|
79
|
+
'maxAgents'
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
maxAgents = parsed;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!Number.isInteger(maxAgents) || maxAgents < MIN_AGENTS_LIMIT || maxAgents > MAX_AGENTS_LIMIT) {
|
|
86
|
+
throw new ValidationError(
|
|
87
|
+
`Invalid maxAgents '${maxAgents}'. Must be an integer between ${MIN_AGENTS_LIMIT} and ${MAX_AGENTS_LIMIT}`,
|
|
88
|
+
'maxAgents'
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return maxAgents;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function validateAgentType(type) {
|
|
96
|
+
if (!type || typeof type !== 'string') {
|
|
97
|
+
throw new ValidationError('Agent type must be a non-empty string', 'type');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!VALID_AGENT_TYPES.includes(type.toLowerCase())) {
|
|
101
|
+
throw new ValidationError(
|
|
102
|
+
`Invalid agent type '${type}'. Valid types are: ${VALID_AGENT_TYPES.join(', ')}`,
|
|
103
|
+
'type'
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return type.toLowerCase();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function validateAgentName(name) {
|
|
111
|
+
if (name !== null && name !== undefined) {
|
|
112
|
+
if (typeof name !== 'string') {
|
|
113
|
+
throw new ValidationError('Agent name must be a string', 'name');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (name.length === 0) {
|
|
117
|
+
throw new ValidationError('Agent name cannot be empty', 'name');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (name.length > 100) {
|
|
121
|
+
throw new ValidationError('Agent name cannot exceed 100 characters', 'name');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Check for invalid characters
|
|
125
|
+
if (!/^[a-zA-Z0-9\s\-_\.]+$/.test(name)) {
|
|
126
|
+
throw new ValidationError(
|
|
127
|
+
'Agent name can only contain letters, numbers, spaces, hyphens, underscores, and periods',
|
|
128
|
+
'name'
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return name;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function validateTaskDescription(task) {
|
|
137
|
+
if (!task || typeof task !== 'string') {
|
|
138
|
+
throw new ValidationError('Task description must be a non-empty string', 'task');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (task.trim().length === 0) {
|
|
142
|
+
throw new ValidationError('Task description cannot be empty or only whitespace', 'task');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (task.length > 1000) {
|
|
146
|
+
throw new ValidationError('Task description cannot exceed 1000 characters', 'task');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return task.trim();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function logValidationError(error, command) {
|
|
153
|
+
console.log(`ā Validation Error in '${command}' command:`);
|
|
154
|
+
console.log(` ${error.message}`);
|
|
155
|
+
if (error.parameter) {
|
|
156
|
+
console.log(` Parameter: ${error.parameter}`);
|
|
157
|
+
}
|
|
158
|
+
console.log(`\nš” For help with valid parameters, run: @sparkleideas/ruv-swarm help`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function stabilityLog(message) {
|
|
162
|
+
const timestamp = new Date().toISOString();
|
|
163
|
+
console.error(`[${timestamp}] [STABILITY] ${message}`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let globalRuvSwarm = null;
|
|
167
|
+
let globalMCPTools = null;
|
|
168
|
+
let globalLogger = null;
|
|
169
|
+
|
|
170
|
+
// Initialize logger based on environment
|
|
171
|
+
async function initializeLogger() {
|
|
172
|
+
if (!globalLogger) {
|
|
173
|
+
globalLogger = new Logger({
|
|
174
|
+
name: 'ruv-swarm-mcp',
|
|
175
|
+
level: process.env.LOG_LEVEL || (process.argv.includes('--debug') ? 'DEBUG' : 'INFO'),
|
|
176
|
+
enableStderr: true, // Always use stderr in MCP mode
|
|
177
|
+
enableFile: process.env.LOG_TO_FILE === 'true',
|
|
178
|
+
formatJson: process.env.LOG_FORMAT === 'json',
|
|
179
|
+
logDir: process.env.LOG_DIR || './logs',
|
|
180
|
+
metadata: {
|
|
181
|
+
pid: process.pid,
|
|
182
|
+
version: await getVersion(),
|
|
183
|
+
mode: 'mcp-stdio'
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Set up bulletproof error handlers - LOG but NEVER exit
|
|
188
|
+
process.on('uncaughtException', (error) => {
|
|
189
|
+
globalLogger.error('Uncaught exception - continuing operation', { error });
|
|
190
|
+
if (isStabilityMode) {
|
|
191
|
+
stabilityLog(`Uncaught exception: ${error.message} - continuing...`);
|
|
192
|
+
}
|
|
193
|
+
// DO NOT EXIT - bulletproof operation continues
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
197
|
+
globalLogger.error('Unhandled rejection - continuing operation', { reason, promise });
|
|
198
|
+
if (isStabilityMode) {
|
|
199
|
+
stabilityLog(`Unhandled rejection: ${reason} - continuing...`);
|
|
200
|
+
}
|
|
201
|
+
// DO NOT EXIT - bulletproof operation continues
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return globalLogger;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function initializeSystem() {
|
|
208
|
+
if (!globalRuvSwarm) {
|
|
209
|
+
// RuvSwarm.initialize already prints initialization messages
|
|
210
|
+
globalRuvSwarm = await RuvSwarm.initialize({
|
|
211
|
+
loadingStrategy: 'progressive',
|
|
212
|
+
enablePersistence: true,
|
|
213
|
+
enableNeuralNetworks: true,
|
|
214
|
+
enableForecasting: true,
|
|
215
|
+
useSIMD: RuvSwarm.detectSIMDSupport(),
|
|
216
|
+
debug: process.argv.includes('--debug')
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (!globalMCPTools) {
|
|
221
|
+
// Pass the already initialized RuvSwarm instance to avoid duplicate initialization
|
|
222
|
+
globalMCPTools = new EnhancedMCPTools(globalRuvSwarm);
|
|
223
|
+
await globalMCPTools.initialize(globalRuvSwarm);
|
|
224
|
+
|
|
225
|
+
// Initialize DAA MCP tools with the same instance
|
|
226
|
+
daaMcpTools.mcpTools = globalMCPTools;
|
|
227
|
+
await daaMcpTools.ensureInitialized();
|
|
228
|
+
|
|
229
|
+
// Add DAA tool methods to the MCP tools object
|
|
230
|
+
const daaToolNames = [
|
|
231
|
+
'daa_init', 'daa_agent_create', 'daa_agent_adapt', 'daa_workflow_create',
|
|
232
|
+
'daa_workflow_execute', 'daa_knowledge_share', 'daa_learning_status',
|
|
233
|
+
'daa_cognitive_pattern', 'daa_meta_learning', 'daa_performance_metrics'
|
|
234
|
+
];
|
|
235
|
+
|
|
236
|
+
for (const toolName of daaToolNames) {
|
|
237
|
+
if (typeof daaMcpTools[toolName] === 'function') {
|
|
238
|
+
globalMCPTools[toolName] = daaMcpTools[toolName].bind(daaMcpTools);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return { ruvSwarm: globalRuvSwarm, mcpTools: globalMCPTools };
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function handleInit(args) {
|
|
247
|
+
try {
|
|
248
|
+
const { mcpTools } = await initializeSystem();
|
|
249
|
+
|
|
250
|
+
// Filter out flags to get positional arguments
|
|
251
|
+
const positionalArgs = args.filter(arg => !arg.startsWith('--'));
|
|
252
|
+
const rawTopology = positionalArgs[0] || 'mesh';
|
|
253
|
+
const rawMaxAgents = positionalArgs[1] || '5';
|
|
254
|
+
const setupClaude = args.includes('--claude') || args.includes('--setup-claude');
|
|
255
|
+
const forceSetup = args.includes('--force');
|
|
256
|
+
const mergeSetup = args.includes('--merge');
|
|
257
|
+
const noInteractive = args.includes('--no-interactive');
|
|
258
|
+
const noBackup = args.includes('--no-backup');
|
|
259
|
+
|
|
260
|
+
// Validate inputs
|
|
261
|
+
const topology = validateTopology(rawTopology);
|
|
262
|
+
const maxAgents = validateMaxAgents(rawMaxAgents);
|
|
263
|
+
|
|
264
|
+
console.log('š Initializing @sparkleideas/ruv-swarm...');
|
|
265
|
+
|
|
266
|
+
const result = await mcpTools.swarm_init({
|
|
267
|
+
topology,
|
|
268
|
+
maxAgents,
|
|
269
|
+
strategy: 'balanced',
|
|
270
|
+
enableCognitiveDiversity: true,
|
|
271
|
+
enableNeuralAgents: true,
|
|
272
|
+
enableForecasting: args.includes('--forecasting')
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
console.log('š Swarm initialized:');
|
|
276
|
+
console.log(' ID: ' + result.id);
|
|
277
|
+
console.log(' Topology: ' + result.topology);
|
|
278
|
+
console.log(' Max Agents: ' + result.maxAgents);
|
|
279
|
+
console.log(' Features: ' + Object.entries(result.features).filter(([k,v]) => v).map(([k,v]) => k).join(', '));
|
|
280
|
+
console.log(' Performance: ' + result.performance.initialization_time_ms.toFixed(1) + 'ms');
|
|
281
|
+
|
|
282
|
+
// Setup Claude integration using modular approach
|
|
283
|
+
if (setupClaude || forceSetup || mergeSetup) {
|
|
284
|
+
console.log('\nš Setting up modular Claude Code integration...');
|
|
285
|
+
try {
|
|
286
|
+
await setupClaudeIntegration({
|
|
287
|
+
autoSetup: setupClaude,
|
|
288
|
+
forceSetup: forceSetup,
|
|
289
|
+
mergeSetup: mergeSetup,
|
|
290
|
+
noBackup: noBackup,
|
|
291
|
+
interactive: !noInteractive,
|
|
292
|
+
workingDir: process.cwd(),
|
|
293
|
+
packageName: '@sparkleideas/ruv-swarm'
|
|
294
|
+
});
|
|
295
|
+
} catch (error) {
|
|
296
|
+
console.log('ā ļø Claude integration setup had issues:', error.message);
|
|
297
|
+
console.log('š” Manual setup: claude mcp add @sparkleideas/ruv-swarm npx @sparkleideas/ruv-swarm mcp start');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
console.log('\nā
Initialization complete!');
|
|
302
|
+
console.log('\nš Next steps:');
|
|
303
|
+
console.log(' 1. Test with MCP tools: mcp__ruv-swarm__agent_spawn');
|
|
304
|
+
console.log(' 2. Use wrapper scripts for remote execution');
|
|
305
|
+
console.log(' 3. Check .claude/commands/ for detailed guides');
|
|
306
|
+
|
|
307
|
+
if (forceSetup) {
|
|
308
|
+
console.log('\nš Files regenerated with --force flag');
|
|
309
|
+
} else if (mergeSetup) {
|
|
310
|
+
console.log('\nš Configuration merged with existing files');
|
|
311
|
+
}
|
|
312
|
+
} catch (error) {
|
|
313
|
+
if (error instanceof ValidationError) {
|
|
314
|
+
logValidationError(error, 'init');
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
throw error;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
async function handleSpawn(args) {
|
|
322
|
+
try {
|
|
323
|
+
const { mcpTools } = await initializeSystem();
|
|
324
|
+
|
|
325
|
+
const rawType = args[0] || 'researcher';
|
|
326
|
+
const rawName = args[1] || null;
|
|
327
|
+
|
|
328
|
+
// Validate inputs
|
|
329
|
+
const type = validateAgentType(rawType);
|
|
330
|
+
const name = validateAgentName(rawName);
|
|
331
|
+
|
|
332
|
+
const result = await mcpTools.agent_spawn({
|
|
333
|
+
type,
|
|
334
|
+
name,
|
|
335
|
+
enableNeuralNetwork: !args.includes('--no-neural')
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
console.log('š¤ Agent spawned:');
|
|
339
|
+
console.log(' ID: ' + result.agent.id);
|
|
340
|
+
console.log(' Name: ' + result.agent.name);
|
|
341
|
+
console.log(' Type: ' + result.agent.type);
|
|
342
|
+
console.log(' Cognitive Pattern: ' + result.agent.cognitive_pattern);
|
|
343
|
+
if (result.agent.neural_network_id) {
|
|
344
|
+
console.log(' Neural Network: ' + result.agent.neural_network_id);
|
|
345
|
+
}
|
|
346
|
+
console.log(' Swarm Capacity: ' + result.swarm_info.capacity);
|
|
347
|
+
} catch (error) {
|
|
348
|
+
if (error instanceof ValidationError) {
|
|
349
|
+
logValidationError(error, 'spawn');
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
throw error;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
async function handleOrchestrate(args) {
|
|
357
|
+
try {
|
|
358
|
+
const { mcpTools } = await initializeSystem();
|
|
359
|
+
|
|
360
|
+
const rawTask = args.join(' ');
|
|
361
|
+
if (!rawTask) {
|
|
362
|
+
console.log('ā No task provided');
|
|
363
|
+
console.log('Usage: @sparkleideas/ruv-swarm orchestrate "task description"');
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Validate task description
|
|
368
|
+
const task = validateTaskDescription(rawTask);
|
|
369
|
+
|
|
370
|
+
const result = await mcpTools.task_orchestrate({
|
|
371
|
+
task: task,
|
|
372
|
+
strategy: 'adaptive'
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
console.log('š Task orchestrated:');
|
|
376
|
+
console.log(' ID: ' + result.taskId);
|
|
377
|
+
console.log(' Description: ' + result.description);
|
|
378
|
+
console.log(' Assigned Agents: ' + result.assigned_agents.length);
|
|
379
|
+
console.log(' Status: ' + result.status);
|
|
380
|
+
console.log(' Estimated Completion: ' + result.performance.estimated_completion_ms + 'ms');
|
|
381
|
+
} catch (error) {
|
|
382
|
+
if (error instanceof ValidationError) {
|
|
383
|
+
logValidationError(error, 'orchestrate');
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
throw error;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
async function handleClaudeInvoke(args) {
|
|
391
|
+
const prompt = args.join(' ');
|
|
392
|
+
|
|
393
|
+
if (!prompt.trim()) {
|
|
394
|
+
console.log('ā No prompt provided');
|
|
395
|
+
console.log('Usage: @sparkleideas/ruv-swarm claude-invoke "your swarm prompt"');
|
|
396
|
+
console.log('Note: Use --dangerously-skip-permissions explicitly if needed');
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Security: validate prompt for dangerous patterns
|
|
401
|
+
try {
|
|
402
|
+
CommandSanitizer.validateArgument(prompt.trim());
|
|
403
|
+
} catch (error) {
|
|
404
|
+
if (error instanceof SecurityError) {
|
|
405
|
+
console.error('ā Security validation failed:', error.message);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
throw error;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
console.log('š Invoking Claude Code with @sparkleideas/ruv-swarm integration...');
|
|
412
|
+
console.log('Prompt: ' + prompt.trim());
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
// Create orchestrator with secure mode
|
|
416
|
+
const { ClaudeIntegrationOrchestrator } = await import('../src/claude-integration/index.js');
|
|
417
|
+
const orchestrator = new ClaudeIntegrationOrchestrator({
|
|
418
|
+
workingDir: process.cwd()
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
// Use secure mode (no automatic permissions)
|
|
422
|
+
await orchestrator.core.invokeClaudeWithPrompt(prompt, { secure: true });
|
|
423
|
+
} catch (error) {
|
|
424
|
+
console.error('ā Claude invocation failed:', error.message);
|
|
425
|
+
console.error('Make sure Claude Code CLI is installed and in your PATH');
|
|
426
|
+
process.exit(1);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
async function handleStatus(args) {
|
|
431
|
+
const { mcpTools } = await initializeSystem();
|
|
432
|
+
|
|
433
|
+
const verbose = args.includes('--verbose') || args.includes('-v');
|
|
434
|
+
const swarmId = args.find(arg => !arg.startsWith('-'));
|
|
435
|
+
|
|
436
|
+
const result = await mcpTools.swarm_status({ verbose });
|
|
437
|
+
|
|
438
|
+
if (swarmId) {
|
|
439
|
+
console.log(`š Swarm Status (${swarmId}):`);
|
|
440
|
+
console.log(` Agents: ${result.agents.total} (${result.agents.active} active, ${result.agents.idle} idle)`);
|
|
441
|
+
console.log(` Tasks: ${result.tasks.total} (${result.tasks.pending} pending, ${result.tasks.in_progress} in progress)`);
|
|
442
|
+
} else {
|
|
443
|
+
console.log('š Global Status:');
|
|
444
|
+
console.log(` Active Swarms: ${result.active_swarms}`);
|
|
445
|
+
console.log(` Total Agents: ${result.global_metrics.totalAgents}`);
|
|
446
|
+
console.log(` Total Tasks: ${result.global_metrics.totalTasks}`);
|
|
447
|
+
console.log(` Memory Usage: ${result.global_metrics.memoryUsage / (1024 * 1024)}MB`);
|
|
448
|
+
|
|
449
|
+
if (verbose) {
|
|
450
|
+
console.log('\nš WASM Modules:');
|
|
451
|
+
Object.entries(result.runtime_info.wasm_modules).forEach(([name, status]) => {
|
|
452
|
+
console.log(` ${name}: ${status.loaded ? 'ā
Loaded' : 'ā³ Not loaded'} (${(status.size / 1024).toFixed(0)}KB)`);
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
async function handleMonitor(args) {
|
|
459
|
+
const { mcpTools } = await initializeSystem();
|
|
460
|
+
|
|
461
|
+
const duration = parseInt(args.find(arg => arg.match(/^\d+$/))) || 10000;
|
|
462
|
+
|
|
463
|
+
console.log(`š Monitoring for ${duration}ms...`);
|
|
464
|
+
console.log('Press Ctrl+C to stop\n');
|
|
465
|
+
|
|
466
|
+
const interval = setInterval(async () => {
|
|
467
|
+
const status = await mcpTools.swarm_status({ verbose: false });
|
|
468
|
+
process.stdout.write('\r');
|
|
469
|
+
process.stdout.write(`Swarms: ${status.active_swarms} | Agents: ${status.global_metrics.totalAgents} | Tasks: ${status.global_metrics.totalTasks} | Memory: ${(status.global_metrics.memoryUsage / (1024 * 1024)).toFixed(1)}MB`);
|
|
470
|
+
}, 1000);
|
|
471
|
+
|
|
472
|
+
setTimeout(() => {
|
|
473
|
+
clearInterval(interval);
|
|
474
|
+
console.log('\n\nā
Monitoring complete');
|
|
475
|
+
}, duration);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
async function handleMcp(args) {
|
|
479
|
+
const subcommand = args[0] || 'help';
|
|
480
|
+
|
|
481
|
+
switch (subcommand) {
|
|
482
|
+
case 'start':
|
|
483
|
+
await startMcpServer(args.slice(1));
|
|
484
|
+
break;
|
|
485
|
+
case 'status':
|
|
486
|
+
await getMcpStatus();
|
|
487
|
+
break;
|
|
488
|
+
case 'stop':
|
|
489
|
+
await stopMcpServer();
|
|
490
|
+
break;
|
|
491
|
+
case 'tools':
|
|
492
|
+
await listMcpTools();
|
|
493
|
+
break;
|
|
494
|
+
case 'config':
|
|
495
|
+
await configureMcp(args.slice(1));
|
|
496
|
+
break;
|
|
497
|
+
case 'help':
|
|
498
|
+
default:
|
|
499
|
+
showMcpHelp();
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
async function startMcpServer(args) {
|
|
504
|
+
const protocol = args.find(arg => arg.startsWith('--protocol='))?.split('=')[1] || 'stdio';
|
|
505
|
+
const enableStability = args.includes('--stability') || process.env.MCP_STABILITY === 'true';
|
|
506
|
+
|
|
507
|
+
if (enableStability) {
|
|
508
|
+
isStabilityMode = true;
|
|
509
|
+
stabilityLog('Starting MCP server with stability mode enabled');
|
|
510
|
+
return startStableMcpServer(args);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Initialize logger first
|
|
514
|
+
const logger = await initializeLogger();
|
|
515
|
+
const sessionId = logger.setCorrelationId();
|
|
516
|
+
|
|
517
|
+
try {
|
|
518
|
+
if (protocol === 'stdio') {
|
|
519
|
+
// In stdio mode, only JSON-RPC messages should go to stdout
|
|
520
|
+
logger.info('@sparkleideas/ruv-swarm MCP server starting in stdio mode', {
|
|
521
|
+
protocol,
|
|
522
|
+
sessionId,
|
|
523
|
+
nodeVersion: process.version,
|
|
524
|
+
platform: process.platform,
|
|
525
|
+
arch: process.arch
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
// Log connection establishment
|
|
529
|
+
logger.logConnection('established', sessionId, {
|
|
530
|
+
protocol: 'stdio',
|
|
531
|
+
transport: 'stdin/stdout',
|
|
532
|
+
timestamp: new Date().toISOString()
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
// Initialize WASM if needed
|
|
536
|
+
const initOpId = logger.startOperation('initialize-system');
|
|
537
|
+
const { ruvSwarm, mcpTools } = await initializeSystem();
|
|
538
|
+
logger.endOperation(initOpId, true, { modulesLoaded: true });
|
|
539
|
+
|
|
540
|
+
// Start stdio MCP server loop
|
|
541
|
+
process.stdin.setEncoding('utf8');
|
|
542
|
+
|
|
543
|
+
// Signal server readiness for testing
|
|
544
|
+
if (process.env.MCP_TEST_MODE === 'true') {
|
|
545
|
+
console.error('MCP server ready'); // Use stderr so it doesn't interfere with JSON-RPC
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
let buffer = '';
|
|
549
|
+
let messageCount = 0;
|
|
550
|
+
|
|
551
|
+
process.stdin.on('data', (chunk) => {
|
|
552
|
+
logger.trace('Received stdin data', { bytes: chunk.length });
|
|
553
|
+
buffer += chunk;
|
|
554
|
+
|
|
555
|
+
// Process complete JSON messages
|
|
556
|
+
const lines = buffer.split('\n');
|
|
557
|
+
buffer = lines.pop() || '';
|
|
558
|
+
|
|
559
|
+
for (const line of lines) {
|
|
560
|
+
if (line.trim()) {
|
|
561
|
+
messageCount++;
|
|
562
|
+
const messageId = `msg-${sessionId}-${messageCount}`;
|
|
563
|
+
|
|
564
|
+
try {
|
|
565
|
+
const request = JSON.parse(line);
|
|
566
|
+
logger.logMcp('in', request.method || 'unknown', {
|
|
567
|
+
method: request.method,
|
|
568
|
+
id: request.id,
|
|
569
|
+
params: request.params,
|
|
570
|
+
messageId
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
const opId = logger.startOperation(`mcp-${request.method}`, {
|
|
574
|
+
requestId: request.id,
|
|
575
|
+
messageId
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
handleMcpRequest(request, mcpTools, logger).then(response => {
|
|
579
|
+
logger.endOperation(opId, !response.error, {
|
|
580
|
+
hasError: !!response.error
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
logger.logMcp('out', request.method || 'response', {
|
|
584
|
+
method: request.method,
|
|
585
|
+
id: response.id,
|
|
586
|
+
result: response.result,
|
|
587
|
+
error: response.error,
|
|
588
|
+
messageId
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
try {
|
|
592
|
+
process.stdout.write(JSON.stringify(response) + '\n');
|
|
593
|
+
} catch (writeError) {
|
|
594
|
+
logger.error('Failed to write response to stdout', { writeError, response });
|
|
595
|
+
process.exit(1);
|
|
596
|
+
}
|
|
597
|
+
}).catch(error => {
|
|
598
|
+
logger.endOperation(opId, false, { error });
|
|
599
|
+
logger.error('Request handler error', { error, request });
|
|
600
|
+
|
|
601
|
+
const errorResponse = {
|
|
602
|
+
jsonrpc: '2.0',
|
|
603
|
+
error: {
|
|
604
|
+
code: -32603,
|
|
605
|
+
message: 'Internal error',
|
|
606
|
+
data: error.message
|
|
607
|
+
},
|
|
608
|
+
id: request.id
|
|
609
|
+
};
|
|
610
|
+
process.stdout.write(JSON.stringify(errorResponse) + '\n');
|
|
611
|
+
});
|
|
612
|
+
} catch (error) {
|
|
613
|
+
logger.error('JSON parse error', {
|
|
614
|
+
error,
|
|
615
|
+
line: line.substring(0, 100),
|
|
616
|
+
messageId
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
const errorResponse = {
|
|
620
|
+
jsonrpc: '2.0',
|
|
621
|
+
error: {
|
|
622
|
+
code: -32700,
|
|
623
|
+
message: 'Parse error',
|
|
624
|
+
data: error.message
|
|
625
|
+
},
|
|
626
|
+
id: null
|
|
627
|
+
};
|
|
628
|
+
process.stdout.write(JSON.stringify(errorResponse) + '\n');
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
// Set up connection monitoring
|
|
635
|
+
const monitorInterval = setInterval(() => {
|
|
636
|
+
logger.logMemoryUsage('mcp-server');
|
|
637
|
+
logger.debug('Connection metrics', logger.getConnectionMetrics());
|
|
638
|
+
}, 60000); // Every minute
|
|
639
|
+
|
|
640
|
+
// Handle stdin close
|
|
641
|
+
process.stdin.on('end', () => {
|
|
642
|
+
logger.logConnection('closed', sessionId, {
|
|
643
|
+
messagesProcessed: messageCount,
|
|
644
|
+
uptime: process.uptime()
|
|
645
|
+
});
|
|
646
|
+
logger.info('MCP: stdin closed, shutting down...');
|
|
647
|
+
clearInterval(monitorInterval);
|
|
648
|
+
process.exit(0);
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
process.stdin.on('error', (error) => {
|
|
652
|
+
logger.logConnection('failed', sessionId, { error });
|
|
653
|
+
logger.error('MCP: stdin error, but continuing operation...', { error });
|
|
654
|
+
// DO NOT exit - bulletproof operation continues
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
// Handle process termination signals gracefully
|
|
658
|
+
process.on('SIGTERM', () => {
|
|
659
|
+
logger.info('MCP: Received SIGTERM, shutting down gracefully...');
|
|
660
|
+
clearInterval(monitorInterval);
|
|
661
|
+
process.exit(0);
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
process.on('SIGINT', () => {
|
|
665
|
+
logger.info('MCP: Received SIGINT, shutting down gracefully...');
|
|
666
|
+
clearInterval(monitorInterval);
|
|
667
|
+
process.exit(0);
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
// Send initialization message
|
|
671
|
+
const version = await getVersion();
|
|
672
|
+
const initMessage = {
|
|
673
|
+
jsonrpc: '2.0',
|
|
674
|
+
method: 'server.initialized',
|
|
675
|
+
params: {
|
|
676
|
+
serverInfo: {
|
|
677
|
+
name: '@sparkleideas/ruv-swarm',
|
|
678
|
+
version: version,
|
|
679
|
+
capabilities: {
|
|
680
|
+
tools: true,
|
|
681
|
+
prompts: false,
|
|
682
|
+
resources: true
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
process.stdout.write(JSON.stringify(initMessage) + '\n');
|
|
688
|
+
|
|
689
|
+
// NO TIMEOUT MECHANISM - Bulletproof infinite runtime
|
|
690
|
+
// Security preserved, but NO heartbeats or timeouts whatsoever
|
|
691
|
+
logger.info('MCP server configured for infinite runtime', {
|
|
692
|
+
timeouts: 'DISABLED',
|
|
693
|
+
heartbeats: 'DISABLED',
|
|
694
|
+
mode: 'bulletproof-infinite'
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
} else {
|
|
698
|
+
logger.error('WebSocket protocol not yet implemented', { protocol });
|
|
699
|
+
console.log('ā WebSocket protocol not yet implemented in production version');
|
|
700
|
+
console.log('Use stdio mode for Claude Code integration');
|
|
701
|
+
}
|
|
702
|
+
} catch (error) {
|
|
703
|
+
logger.fatal('Failed to start MCP server', { error, protocol });
|
|
704
|
+
console.error('ā Failed to start MCP server:', error.message);
|
|
705
|
+
process.exit(1);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
async function startStableMcpServer(args) {
|
|
710
|
+
const now = Date.now();
|
|
711
|
+
|
|
712
|
+
// Reset restart count if it's been more than 5 minutes
|
|
713
|
+
if (now - lastRestartTime > RESTART_RESET_TIME) {
|
|
714
|
+
restartCount = 0;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
if (restartCount >= MAX_RESTARTS) {
|
|
718
|
+
stabilityLog(`Maximum restarts (${MAX_RESTARTS}) reached. Server may have persistent issues.`);
|
|
719
|
+
stabilityLog('Please check logs and restart manually if needed.');
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
restartCount++;
|
|
724
|
+
lastRestartTime = now;
|
|
725
|
+
|
|
726
|
+
stabilityLog(`Starting MCP server (attempt ${restartCount}/${MAX_RESTARTS})`);
|
|
727
|
+
|
|
728
|
+
// Create new process args without --stability flag
|
|
729
|
+
const processArgs = ['mcp', 'start', ...args.filter(arg => arg !== '--stability')];
|
|
730
|
+
|
|
731
|
+
childProcess = spawn('node', [__filename, ...processArgs], {
|
|
732
|
+
stdio: ['inherit', 'inherit', 'inherit'],
|
|
733
|
+
env: { ...process.env, MCP_STABILITY: 'false' }
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
childProcess.on('exit', (code, signal) => {
|
|
737
|
+
if (code === 0) {
|
|
738
|
+
stabilityLog('MCP server exited normally');
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
stabilityLog(`MCP server crashed with code ${code} and signal ${signal}`);
|
|
743
|
+
stabilityLog(`Restarting in ${RESTART_DELAY}ms...`);
|
|
744
|
+
|
|
745
|
+
setTimeout(() => {
|
|
746
|
+
startStableMcpServer(args);
|
|
747
|
+
}, RESTART_DELAY);
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
childProcess.on('error', (error) => {
|
|
751
|
+
stabilityLog(`Failed to start MCP server: ${error.message}`);
|
|
752
|
+
stabilityLog(`Restarting in ${RESTART_DELAY}ms...`);
|
|
753
|
+
|
|
754
|
+
setTimeout(() => {
|
|
755
|
+
startStableMcpServer(args);
|
|
756
|
+
}, RESTART_DELAY);
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
// Handle process termination signals
|
|
760
|
+
process.on('SIGTERM', () => {
|
|
761
|
+
stabilityLog('Received SIGTERM, shutting down...');
|
|
762
|
+
if (childProcess) {
|
|
763
|
+
childProcess.kill('SIGTERM');
|
|
764
|
+
}
|
|
765
|
+
process.exit(0);
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
process.on('SIGINT', () => {
|
|
769
|
+
stabilityLog('Received SIGINT, shutting down...');
|
|
770
|
+
if (childProcess) {
|
|
771
|
+
childProcess.kill('SIGINT');
|
|
772
|
+
}
|
|
773
|
+
process.exit(0);
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
async function getMcpStatus() {
|
|
778
|
+
console.log('š MCP Server Status:');
|
|
779
|
+
console.log(' Protocol: stdio (for Claude Code integration)');
|
|
780
|
+
console.log(' Status: Ready to start');
|
|
781
|
+
console.log(' Usage: npx @sparkleideas/ruv-swarm mcp start [--stability]');
|
|
782
|
+
console.log(' Runtime: Infinite (no timeouts)');
|
|
783
|
+
console.log(' Stability: Auto-restart on crashes (use --stability flag)');
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
async function stopMcpServer() {
|
|
787
|
+
if (childProcess) {
|
|
788
|
+
stabilityLog('Stopping MCP server...');
|
|
789
|
+
childProcess.kill('SIGTERM');
|
|
790
|
+
childProcess = null;
|
|
791
|
+
}
|
|
792
|
+
console.log('ā
MCP server stopped');
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
async function listMcpTools() {
|
|
796
|
+
console.log('š ļø Available MCP Tools:');
|
|
797
|
+
console.log('\nš Core Swarm Tools:');
|
|
798
|
+
console.log(' mcp__ruv-swarm__swarm_init - Initialize a new swarm');
|
|
799
|
+
console.log(' mcp__ruv-swarm__agent_spawn - Spawn new agents');
|
|
800
|
+
console.log(' mcp__ruv-swarm__task_orchestrate - Orchestrate tasks');
|
|
801
|
+
console.log(' mcp__ruv-swarm__swarm_status - Get swarm status');
|
|
802
|
+
console.log(' ... and 11 more core tools');
|
|
803
|
+
console.log('\nš¤ DAA (Decentralized Autonomous Agents) Tools:');
|
|
804
|
+
console.log(' mcp__ruv-swarm__daa_init - Initialize DAA service');
|
|
805
|
+
console.log(' mcp__ruv-swarm__daa_agent_create - Create autonomous agents');
|
|
806
|
+
console.log(' mcp__ruv-swarm__daa_workflow_create - Create DAA workflows');
|
|
807
|
+
console.log(' mcp__ruv-swarm__daa_learning_status - Get learning progress');
|
|
808
|
+
console.log(' ... and 6 more DAA tools');
|
|
809
|
+
console.log('\nFor full documentation, run: @sparkleideas/ruv-swarm init --claude');
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
function showMcpHelp() {
|
|
813
|
+
console.log(`
|
|
814
|
+
š MCP (Model Context Protocol) Commands
|
|
815
|
+
|
|
816
|
+
Usage: @sparkleideas/ruv-swarm mcp <subcommand> [options]
|
|
817
|
+
|
|
818
|
+
Subcommands:
|
|
819
|
+
start [--protocol=stdio] [--stability] Start MCP server
|
|
820
|
+
status Show MCP server status
|
|
821
|
+
stop Stop MCP server
|
|
822
|
+
tools List available MCP tools
|
|
823
|
+
help Show this help message
|
|
824
|
+
|
|
825
|
+
Options:
|
|
826
|
+
--stability Enable auto-restart on crashes
|
|
827
|
+
--protocol=stdio Use stdio protocol (default)
|
|
828
|
+
|
|
829
|
+
Environment Variables:
|
|
830
|
+
LOG_LEVEL Log level (DEBUG, INFO, WARN, ERROR)
|
|
831
|
+
MCP_TEST_MODE Enable test mode (true/false)
|
|
832
|
+
|
|
833
|
+
Examples:
|
|
834
|
+
@sparkleideas/ruv-swarm mcp start # Start stdio MCP server (infinite runtime)
|
|
835
|
+
@sparkleideas/ruv-swarm mcp start --stability # Start with crash protection
|
|
836
|
+
LOG_LEVEL=DEBUG @sparkleideas/ruv-swarm mcp start # Enable debug logging
|
|
837
|
+
@sparkleideas/ruv-swarm mcp tools # List available tools
|
|
838
|
+
|
|
839
|
+
For Claude Code integration:
|
|
840
|
+
claude mcp add @sparkleideas/ruv-swarm npx @sparkleideas/ruv-swarm mcp start --stability
|
|
841
|
+
`);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
async function configureMcp(args) {
|
|
845
|
+
console.log('š§ MCP configuration is managed through Claude Code');
|
|
846
|
+
console.log('Run: @sparkleideas/ruv-swarm init --claude');
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
async function getResourceContent(uri) {
|
|
850
|
+
const resources = {
|
|
851
|
+
'swarm://docs/getting-started': {
|
|
852
|
+
contents: [{
|
|
853
|
+
uri,
|
|
854
|
+
mimeType: 'text/markdown',
|
|
855
|
+
text: `# Getting Started with @sparkleideas/ruv-swarm
|
|
856
|
+
|
|
857
|
+
## Introduction
|
|
858
|
+
@sparkleideas/ruv-swarm is a powerful WASM-powered neural swarm orchestration system that enhances Claude Code's capabilities through intelligent agent coordination.
|
|
859
|
+
|
|
860
|
+
## Quick Start
|
|
861
|
+
|
|
862
|
+
1. **Initialize a swarm:**
|
|
863
|
+
\`\`\`bash
|
|
864
|
+
mcp__ruv-swarm__swarm_init { topology: "mesh", maxAgents: 5 }
|
|
865
|
+
\`\`\`
|
|
866
|
+
|
|
867
|
+
2. **Spawn agents:**
|
|
868
|
+
\`\`\`bash
|
|
869
|
+
mcp__ruv-swarm__agent_spawn { type: "researcher", name: "Doc Analyzer" }
|
|
870
|
+
mcp__ruv-swarm__agent_spawn { type: "coder", name: "Implementation Expert" }
|
|
871
|
+
\`\`\`
|
|
872
|
+
|
|
873
|
+
3. **Orchestrate tasks:**
|
|
874
|
+
\`\`\`bash
|
|
875
|
+
mcp__ruv-swarm__task_orchestrate { task: "Build a REST API", strategy: "adaptive" }
|
|
876
|
+
\`\`\`
|
|
877
|
+
|
|
878
|
+
## Key Concepts
|
|
879
|
+
|
|
880
|
+
- **Agents**: Cognitive patterns that guide Claude Code's approach
|
|
881
|
+
- **Topologies**: Organizational structures for agent coordination
|
|
882
|
+
- **Memory**: Persistent state across sessions
|
|
883
|
+
- **Neural Training**: Continuous improvement through learning
|
|
884
|
+
|
|
885
|
+
## Best Practices
|
|
886
|
+
|
|
887
|
+
1. Always batch operations in a single message
|
|
888
|
+
2. Use memory for cross-agent coordination
|
|
889
|
+
3. Monitor progress with status tools
|
|
890
|
+
4. Train neural patterns for better results`
|
|
891
|
+
}]
|
|
892
|
+
},
|
|
893
|
+
'swarm://docs/stability': {
|
|
894
|
+
contents: [{
|
|
895
|
+
uri,
|
|
896
|
+
mimeType: 'text/markdown',
|
|
897
|
+
text: `# Stability Features
|
|
898
|
+
|
|
899
|
+
## Auto-Restart Protection
|
|
900
|
+
The production version includes built-in crash protection:
|
|
901
|
+
|
|
902
|
+
- **Maximum restarts**: 10 attempts
|
|
903
|
+
- **Restart delay**: 1 second between attempts
|
|
904
|
+
- **Reset window**: 5 minutes (restart count resets)
|
|
905
|
+
- **Graceful shutdown**: SIGTERM/SIGINT handling
|
|
906
|
+
|
|
907
|
+
## Usage
|
|
908
|
+
\`\`\`bash
|
|
909
|
+
# Enable stability mode
|
|
910
|
+
@sparkleideas/ruv-swarm mcp start --stability
|
|
911
|
+
|
|
912
|
+
# For Claude Code integration
|
|
913
|
+
claude mcp add @sparkleideas/ruv-swarm npx @sparkleideas/ruv-swarm mcp start --stability
|
|
914
|
+
\`\`\`
|
|
915
|
+
|
|
916
|
+
## Features
|
|
917
|
+
- Automatic process restart on crashes
|
|
918
|
+
- Proper signal handling
|
|
919
|
+
- Detailed logging of restart attempts
|
|
920
|
+
- Circuit breaker pattern to prevent infinite loops`
|
|
921
|
+
}]
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
const resource = resources[uri];
|
|
926
|
+
if (!resource) {
|
|
927
|
+
throw new Error(`Resource not found: ${uri}`);
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
return resource;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
async function handleMcpRequest(request, mcpTools, logger = null) {
|
|
934
|
+
const response = {
|
|
935
|
+
jsonrpc: '2.0',
|
|
936
|
+
id: request.id
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
// Use default logger if not provided
|
|
940
|
+
if (!logger) {
|
|
941
|
+
logger = await initializeLogger();
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
try {
|
|
945
|
+
logger.debug('Processing MCP request', {
|
|
946
|
+
method: request.method,
|
|
947
|
+
hasParams: !!request.params,
|
|
948
|
+
requestId: request.id
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
switch (request.method) {
|
|
952
|
+
case 'initialize':
|
|
953
|
+
const version = await getVersion();
|
|
954
|
+
response.result = {
|
|
955
|
+
protocolVersion: '2024-11-05',
|
|
956
|
+
capabilities: {
|
|
957
|
+
tools: {},
|
|
958
|
+
resources: {
|
|
959
|
+
list: true,
|
|
960
|
+
read: true
|
|
961
|
+
}
|
|
962
|
+
},
|
|
963
|
+
serverInfo: {
|
|
964
|
+
name: '@sparkleideas/ruv-swarm',
|
|
965
|
+
version: version
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
break;
|
|
969
|
+
|
|
970
|
+
case 'tools/list':
|
|
971
|
+
response.result = {
|
|
972
|
+
tools: [
|
|
973
|
+
{
|
|
974
|
+
name: 'swarm_init',
|
|
975
|
+
description: 'Initialize a new swarm with specified topology',
|
|
976
|
+
inputSchema: {
|
|
977
|
+
type: 'object',
|
|
978
|
+
properties: {
|
|
979
|
+
topology: { type: 'string', enum: ['mesh', 'hierarchical', 'ring', 'star'], description: 'Swarm topology type' },
|
|
980
|
+
maxAgents: { type: 'number', minimum: 1, maximum: 100, default: 5, description: 'Maximum number of agents' },
|
|
981
|
+
strategy: { type: 'string', enum: ['balanced', 'specialized', 'adaptive'], default: 'balanced', description: 'Distribution strategy' }
|
|
982
|
+
},
|
|
983
|
+
required: ['topology']
|
|
984
|
+
}
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
name: 'swarm_status',
|
|
988
|
+
description: 'Get current swarm status and agent information',
|
|
989
|
+
inputSchema: {
|
|
990
|
+
type: 'object',
|
|
991
|
+
properties: {
|
|
992
|
+
verbose: { type: 'boolean', default: false, description: 'Include detailed agent information' }
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
},
|
|
996
|
+
{
|
|
997
|
+
name: 'swarm_monitor',
|
|
998
|
+
description: 'Monitor swarm activity in real-time',
|
|
999
|
+
inputSchema: {
|
|
1000
|
+
type: 'object',
|
|
1001
|
+
properties: {
|
|
1002
|
+
duration: { type: 'number', default: 10, description: 'Monitoring duration in seconds' },
|
|
1003
|
+
interval: { type: 'number', default: 1, description: 'Update interval in seconds' }
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
name: 'agent_spawn',
|
|
1009
|
+
description: 'Spawn a new agent in the swarm',
|
|
1010
|
+
inputSchema: {
|
|
1011
|
+
type: 'object',
|
|
1012
|
+
properties: {
|
|
1013
|
+
type: { type: 'string', enum: ['researcher', 'coder', 'analyst', 'optimizer', 'coordinator'], description: 'Agent type' },
|
|
1014
|
+
name: { type: 'string', description: 'Custom agent name' },
|
|
1015
|
+
capabilities: { type: 'array', items: { type: 'string' }, description: 'Agent capabilities' }
|
|
1016
|
+
},
|
|
1017
|
+
required: ['type']
|
|
1018
|
+
}
|
|
1019
|
+
},
|
|
1020
|
+
{
|
|
1021
|
+
name: 'agent_list',
|
|
1022
|
+
description: 'List all active agents in the swarm',
|
|
1023
|
+
inputSchema: {
|
|
1024
|
+
type: 'object',
|
|
1025
|
+
properties: {
|
|
1026
|
+
filter: { type: 'string', enum: ['all', 'active', 'idle', 'busy'], default: 'all', description: 'Filter agents by status' }
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
},
|
|
1030
|
+
{
|
|
1031
|
+
name: 'agent_metrics',
|
|
1032
|
+
description: 'Get performance metrics for agents',
|
|
1033
|
+
inputSchema: {
|
|
1034
|
+
type: 'object',
|
|
1035
|
+
properties: {
|
|
1036
|
+
agentId: { type: 'string', description: 'Specific agent ID (optional)' },
|
|
1037
|
+
metric: { type: 'string', enum: ['all', 'cpu', 'memory', 'tasks', 'performance'], default: 'all' }
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
},
|
|
1041
|
+
{
|
|
1042
|
+
name: 'task_orchestrate',
|
|
1043
|
+
description: 'Orchestrate a task across the swarm',
|
|
1044
|
+
inputSchema: {
|
|
1045
|
+
type: 'object',
|
|
1046
|
+
properties: {
|
|
1047
|
+
task: { type: 'string', description: 'Task description or instructions' },
|
|
1048
|
+
strategy: { type: 'string', enum: ['parallel', 'sequential', 'adaptive'], default: 'adaptive', description: 'Execution strategy' },
|
|
1049
|
+
priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'], default: 'medium', description: 'Task priority' },
|
|
1050
|
+
maxAgents: { type: 'number', minimum: 1, maximum: 10, description: 'Maximum agents to use' }
|
|
1051
|
+
},
|
|
1052
|
+
required: ['task']
|
|
1053
|
+
}
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
name: 'task_status',
|
|
1057
|
+
description: 'Check progress of running tasks',
|
|
1058
|
+
inputSchema: {
|
|
1059
|
+
type: 'object',
|
|
1060
|
+
properties: {
|
|
1061
|
+
taskId: { type: 'string', description: 'Specific task ID (optional)' },
|
|
1062
|
+
detailed: { type: 'boolean', default: false, description: 'Include detailed progress' }
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
},
|
|
1066
|
+
{
|
|
1067
|
+
name: 'task_results',
|
|
1068
|
+
description: 'Retrieve results from completed tasks',
|
|
1069
|
+
inputSchema: {
|
|
1070
|
+
type: 'object',
|
|
1071
|
+
properties: {
|
|
1072
|
+
taskId: { type: 'string', description: 'Task ID to retrieve results for' },
|
|
1073
|
+
format: { type: 'string', enum: ['summary', 'detailed', 'raw'], default: 'summary', description: 'Result format' }
|
|
1074
|
+
},
|
|
1075
|
+
required: ['taskId']
|
|
1076
|
+
}
|
|
1077
|
+
},
|
|
1078
|
+
{
|
|
1079
|
+
name: 'benchmark_run',
|
|
1080
|
+
description: 'Execute performance benchmarks',
|
|
1081
|
+
inputSchema: {
|
|
1082
|
+
type: 'object',
|
|
1083
|
+
properties: {
|
|
1084
|
+
type: { type: 'string', enum: ['all', 'wasm', 'swarm', 'agent', 'task'], default: 'all', description: 'Benchmark type' },
|
|
1085
|
+
iterations: { type: 'number', minimum: 1, maximum: 100, default: 10, description: 'Number of iterations' }
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
},
|
|
1089
|
+
{
|
|
1090
|
+
name: 'features_detect',
|
|
1091
|
+
description: 'Detect runtime features and capabilities',
|
|
1092
|
+
inputSchema: {
|
|
1093
|
+
type: 'object',
|
|
1094
|
+
properties: {
|
|
1095
|
+
category: { type: 'string', enum: ['all', 'wasm', 'simd', 'memory', 'platform'], default: 'all', description: 'Feature category' }
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
},
|
|
1099
|
+
{
|
|
1100
|
+
name: 'memory_usage',
|
|
1101
|
+
description: 'Get current memory usage statistics',
|
|
1102
|
+
inputSchema: {
|
|
1103
|
+
type: 'object',
|
|
1104
|
+
properties: {
|
|
1105
|
+
detail: { type: 'string', enum: ['summary', 'detailed', 'by-agent'], default: 'summary', description: 'Detail level' }
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
1110
|
+
name: 'neural_status',
|
|
1111
|
+
description: 'Get neural agent status and performance metrics',
|
|
1112
|
+
inputSchema: {
|
|
1113
|
+
type: 'object',
|
|
1114
|
+
properties: {
|
|
1115
|
+
agentId: { type: 'string', description: 'Specific agent ID (optional)' }
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
name: 'neural_train',
|
|
1121
|
+
description: 'Train neural agents with sample tasks',
|
|
1122
|
+
inputSchema: {
|
|
1123
|
+
type: 'object',
|
|
1124
|
+
properties: {
|
|
1125
|
+
agentId: { type: 'string', description: 'Specific agent ID to train (optional)' },
|
|
1126
|
+
iterations: { type: 'number', minimum: 1, maximum: 100, default: 10, description: 'Number of training iterations' }
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
},
|
|
1130
|
+
{
|
|
1131
|
+
name: 'neural_patterns',
|
|
1132
|
+
description: 'Get cognitive pattern information',
|
|
1133
|
+
inputSchema: {
|
|
1134
|
+
type: 'object',
|
|
1135
|
+
properties: {
|
|
1136
|
+
pattern: { type: 'string', enum: ['all', 'convergent', 'divergent', 'lateral', 'systems', 'critical', 'abstract'], default: 'all', description: 'Cognitive pattern type' }
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
},
|
|
1140
|
+
// Add DAA tools
|
|
1141
|
+
...daaMcpTools.getToolDefinitions()
|
|
1142
|
+
]
|
|
1143
|
+
};
|
|
1144
|
+
break;
|
|
1145
|
+
|
|
1146
|
+
case 'tools/call':
|
|
1147
|
+
const toolName = request.params.name;
|
|
1148
|
+
const toolArgs = request.params.arguments || {};
|
|
1149
|
+
|
|
1150
|
+
logger.info('Tool call requested', {
|
|
1151
|
+
tool: toolName,
|
|
1152
|
+
hasArgs: Object.keys(toolArgs).length > 0,
|
|
1153
|
+
requestId: request.id
|
|
1154
|
+
});
|
|
1155
|
+
|
|
1156
|
+
let result = null;
|
|
1157
|
+
let toolFound = false;
|
|
1158
|
+
const toolOpId = logger.startOperation(`tool-${toolName}`, {
|
|
1159
|
+
tool: toolName,
|
|
1160
|
+
requestId: request.id
|
|
1161
|
+
});
|
|
1162
|
+
|
|
1163
|
+
// Try regular MCP tools first (use mcpToolsEnhanced.tools)
|
|
1164
|
+
if (mcpToolsEnhanced.tools && typeof mcpToolsEnhanced.tools[toolName] === 'function') {
|
|
1165
|
+
try {
|
|
1166
|
+
logger.debug('Executing MCP tool', { tool: toolName, args: toolArgs });
|
|
1167
|
+
result = await mcpToolsEnhanced.tools[toolName](toolArgs);
|
|
1168
|
+
toolFound = true;
|
|
1169
|
+
logger.endOperation(toolOpId, true, { resultType: typeof result });
|
|
1170
|
+
} catch (error) {
|
|
1171
|
+
logger.endOperation(toolOpId, false, { error });
|
|
1172
|
+
logger.error('MCP tool execution failed', {
|
|
1173
|
+
tool: toolName,
|
|
1174
|
+
error,
|
|
1175
|
+
args: toolArgs
|
|
1176
|
+
});
|
|
1177
|
+
response.error = {
|
|
1178
|
+
code: -32603,
|
|
1179
|
+
message: `MCP tool error: ${error.message}`,
|
|
1180
|
+
data: { tool: toolName, error: error.message }
|
|
1181
|
+
};
|
|
1182
|
+
break;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
// Try DAA tools if not found in regular tools
|
|
1186
|
+
else if (typeof daaMcpTools[toolName] === 'function') {
|
|
1187
|
+
try {
|
|
1188
|
+
logger.debug('Executing DAA tool', { tool: toolName, args: toolArgs });
|
|
1189
|
+
result = await daaMcpTools[toolName](toolArgs);
|
|
1190
|
+
toolFound = true;
|
|
1191
|
+
logger.endOperation(toolOpId, true, { resultType: typeof result });
|
|
1192
|
+
} catch (error) {
|
|
1193
|
+
logger.endOperation(toolOpId, false, { error });
|
|
1194
|
+
logger.error('DAA tool execution failed', {
|
|
1195
|
+
tool: toolName,
|
|
1196
|
+
error,
|
|
1197
|
+
args: toolArgs
|
|
1198
|
+
});
|
|
1199
|
+
response.error = {
|
|
1200
|
+
code: -32603,
|
|
1201
|
+
message: `DAA tool error: ${error.message}`,
|
|
1202
|
+
data: { tool: toolName, error: error.message }
|
|
1203
|
+
};
|
|
1204
|
+
break;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
if (toolFound) {
|
|
1209
|
+
// Format response with content array as required by Claude Code
|
|
1210
|
+
response.result = {
|
|
1211
|
+
content: [{
|
|
1212
|
+
type: 'text',
|
|
1213
|
+
text: typeof result === 'string' ? result : JSON.stringify(result, null, 2)
|
|
1214
|
+
}]
|
|
1215
|
+
};
|
|
1216
|
+
} else {
|
|
1217
|
+
response.error = {
|
|
1218
|
+
code: -32601,
|
|
1219
|
+
message: 'Method not found',
|
|
1220
|
+
data: `Unknown tool: ${toolName}`
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
break;
|
|
1224
|
+
|
|
1225
|
+
case 'resources/list':
|
|
1226
|
+
response.result = {
|
|
1227
|
+
resources: [
|
|
1228
|
+
{
|
|
1229
|
+
uri: 'swarm://docs/getting-started',
|
|
1230
|
+
name: 'Getting Started Guide',
|
|
1231
|
+
description: 'Introduction to @sparkleideas/ruv-swarm and basic usage',
|
|
1232
|
+
mimeType: 'text/markdown'
|
|
1233
|
+
},
|
|
1234
|
+
{
|
|
1235
|
+
uri: 'swarm://docs/stability',
|
|
1236
|
+
name: 'Stability Features',
|
|
1237
|
+
description: 'Auto-restart and crash protection features',
|
|
1238
|
+
mimeType: 'text/markdown'
|
|
1239
|
+
}
|
|
1240
|
+
]
|
|
1241
|
+
};
|
|
1242
|
+
break;
|
|
1243
|
+
|
|
1244
|
+
case 'resources/read':
|
|
1245
|
+
const resourceUri = request.params.uri;
|
|
1246
|
+
response.result = await getResourceContent(resourceUri);
|
|
1247
|
+
break;
|
|
1248
|
+
|
|
1249
|
+
default:
|
|
1250
|
+
response.error = {
|
|
1251
|
+
code: -32601,
|
|
1252
|
+
message: 'Method not found',
|
|
1253
|
+
data: `Unknown method: ${request.method}`
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
} catch (error) {
|
|
1257
|
+
response.error = {
|
|
1258
|
+
code: -32603,
|
|
1259
|
+
message: 'Internal error',
|
|
1260
|
+
data: error.message
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
return response;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
async function handleHook(args) {
|
|
1268
|
+
// Hook handler for Claude Code integration
|
|
1269
|
+
const { main: hooksCLIMain } = await import('../src/hooks/cli.js');
|
|
1270
|
+
|
|
1271
|
+
// Pass through to hooks CLI with 'hook' already consumed
|
|
1272
|
+
process.argv = ['node', '@sparkleideas/ruv-swarm', 'hook', ...args];
|
|
1273
|
+
|
|
1274
|
+
return hooksCLIMain();
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
async function handleNeural(args) {
|
|
1278
|
+
const { neuralCLI } = await import('../src/neural.js');
|
|
1279
|
+
const subcommand = args[0] || 'help';
|
|
1280
|
+
|
|
1281
|
+
try {
|
|
1282
|
+
switch (subcommand) {
|
|
1283
|
+
case 'status':
|
|
1284
|
+
return await neuralCLI.status(args.slice(1));
|
|
1285
|
+
case 'train':
|
|
1286
|
+
return await neuralCLI.train(args.slice(1));
|
|
1287
|
+
case 'patterns':
|
|
1288
|
+
return await neuralCLI.patterns(args.slice(1));
|
|
1289
|
+
case 'export':
|
|
1290
|
+
return await neuralCLI.export(args.slice(1));
|
|
1291
|
+
case 'help':
|
|
1292
|
+
default:
|
|
1293
|
+
console.log(`Neural Network Commands:
|
|
1294
|
+
neural status Show neural network status
|
|
1295
|
+
neural train [options] Train neural models
|
|
1296
|
+
neural patterns [model] View learned patterns
|
|
1297
|
+
neural export [options] Export neural weights
|
|
1298
|
+
|
|
1299
|
+
Examples:
|
|
1300
|
+
@sparkleideas/ruv-swarm neural status
|
|
1301
|
+
@sparkleideas/ruv-swarm neural train --model attention --iterations 100
|
|
1302
|
+
@sparkleideas/ruv-swarm neural patterns --model attention
|
|
1303
|
+
@sparkleideas/ruv-swarm neural export --model all --output ./weights.json`);
|
|
1304
|
+
break;
|
|
1305
|
+
}
|
|
1306
|
+
} catch (error) {
|
|
1307
|
+
console.error('ā Neural command error:', error.message);
|
|
1308
|
+
process.exit(1);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
async function handleBenchmark(args) {
|
|
1313
|
+
const { benchmarkCLI } = await import('../src/benchmark.js');
|
|
1314
|
+
const subcommand = args[0] || 'help';
|
|
1315
|
+
|
|
1316
|
+
try {
|
|
1317
|
+
switch (subcommand) {
|
|
1318
|
+
case 'run':
|
|
1319
|
+
return await benchmarkCLI.run(args.slice(1));
|
|
1320
|
+
case 'compare':
|
|
1321
|
+
return await benchmarkCLI.compare(args.slice(1));
|
|
1322
|
+
case 'help':
|
|
1323
|
+
default:
|
|
1324
|
+
console.log(`Benchmark Commands:
|
|
1325
|
+
benchmark run [options] Run performance benchmarks
|
|
1326
|
+
benchmark compare [files] Compare benchmark results
|
|
1327
|
+
|
|
1328
|
+
Examples:
|
|
1329
|
+
@sparkleideas/ruv-swarm benchmark run --iterations 10
|
|
1330
|
+
@sparkleideas/ruv-swarm benchmark run --test swarm-coordination
|
|
1331
|
+
@sparkleideas/ruv-swarm benchmark compare results-1.json results-2.json`);
|
|
1332
|
+
break;
|
|
1333
|
+
}
|
|
1334
|
+
} catch (error) {
|
|
1335
|
+
console.error('ā Benchmark command error:', error.message);
|
|
1336
|
+
process.exit(1);
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
async function handlePerformance(args) {
|
|
1341
|
+
const { performanceCLI } = await import('../src/performance.js');
|
|
1342
|
+
const subcommand = args[0] || 'help';
|
|
1343
|
+
|
|
1344
|
+
try {
|
|
1345
|
+
switch (subcommand) {
|
|
1346
|
+
case 'analyze':
|
|
1347
|
+
return await performanceCLI.analyze(args.slice(1));
|
|
1348
|
+
case 'optimize':
|
|
1349
|
+
return await performanceCLI.optimize(args.slice(1));
|
|
1350
|
+
case 'suggest':
|
|
1351
|
+
return await performanceCLI.suggest(args.slice(1));
|
|
1352
|
+
case 'help':
|
|
1353
|
+
default:
|
|
1354
|
+
console.log(`Performance Commands:
|
|
1355
|
+
performance analyze [options] Analyze performance bottlenecks
|
|
1356
|
+
performance optimize [target] Optimize swarm configuration
|
|
1357
|
+
performance suggest Get optimization suggestions
|
|
1358
|
+
|
|
1359
|
+
Examples:
|
|
1360
|
+
@sparkleideas/ruv-swarm performance analyze --task-id recent
|
|
1361
|
+
@sparkleideas/ruv-swarm performance optimize --target speed
|
|
1362
|
+
@sparkleideas/ruv-swarm performance suggest`);
|
|
1363
|
+
break;
|
|
1364
|
+
}
|
|
1365
|
+
} catch (error) {
|
|
1366
|
+
console.error('ā Performance command error:', error.message);
|
|
1367
|
+
process.exit(1);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
async function handleDiagnose(args) {
|
|
1372
|
+
const { diagnosticsCLI } = await import('../src/cli-diagnostics.js');
|
|
1373
|
+
return diagnosticsCLI(args);
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
async function showHelp() {
|
|
1377
|
+
const version = await getVersion();
|
|
1378
|
+
console.log(`
|
|
1379
|
+
š @sparkleideas/ruv-swarm v${version} - Production-ready WASM-powered neural swarm orchestration
|
|
1380
|
+
|
|
1381
|
+
Usage: @sparkleideas/ruv-swarm <command> [options]
|
|
1382
|
+
|
|
1383
|
+
Commands:
|
|
1384
|
+
init [topology] [maxAgents] Initialize swarm (--claude for integration)
|
|
1385
|
+
Options for --claude:
|
|
1386
|
+
--force Overwrite existing CLAUDE.md (creates backup)
|
|
1387
|
+
--merge Merge with existing CLAUDE.md content
|
|
1388
|
+
--no-backup Disable automatic backup creation
|
|
1389
|
+
--no-interactive Skip interactive prompts (fail on conflicts)
|
|
1390
|
+
spawn <type> [name] Spawn an agent (researcher, coder, analyst, etc.)
|
|
1391
|
+
orchestrate <task> Orchestrate a task across agents
|
|
1392
|
+
status [--verbose] Show swarm status
|
|
1393
|
+
monitor [duration] Monitor swarm activity
|
|
1394
|
+
mcp <subcommand> MCP server management
|
|
1395
|
+
Options for mcp start:
|
|
1396
|
+
--stability Enable auto-restart on crashes
|
|
1397
|
+
hook <type> [options] Claude Code hooks integration
|
|
1398
|
+
claude-invoke <prompt> Invoke Claude with swarm integration
|
|
1399
|
+
neural <subcommand> Neural network training and analysis
|
|
1400
|
+
benchmark <subcommand> Performance benchmarking tools
|
|
1401
|
+
performance <subcommand> Performance analysis and optimization
|
|
1402
|
+
diagnose <subcommand> Run diagnostics and analyze logs
|
|
1403
|
+
version Show version information
|
|
1404
|
+
help Show this help message
|
|
1405
|
+
|
|
1406
|
+
Examples:
|
|
1407
|
+
@sparkleideas/ruv-swarm init mesh 5 --claude # Create CLAUDE.md (fails if exists)
|
|
1408
|
+
@sparkleideas/ruv-swarm init mesh 5 --claude --force # Overwrite CLAUDE.md (creates backup)
|
|
1409
|
+
@sparkleideas/ruv-swarm spawn researcher "AI Research Specialist"
|
|
1410
|
+
@sparkleideas/ruv-swarm orchestrate "Build a REST API with authentication"
|
|
1411
|
+
@sparkleideas/ruv-swarm mcp start --stability # Start with crash protection
|
|
1412
|
+
@sparkleideas/ruv-swarm hook pre-edit --file app.js --ensure-coordination
|
|
1413
|
+
@sparkleideas/ruv-swarm claude-invoke "Create a development swarm for my project"
|
|
1414
|
+
|
|
1415
|
+
š Security Features:
|
|
1416
|
+
⢠Input validation and sanitization
|
|
1417
|
+
⢠Explicit permission control for Claude invocation
|
|
1418
|
+
⢠Command injection prevention
|
|
1419
|
+
⢠WASM integrity verification
|
|
1420
|
+
|
|
1421
|
+
š”ļø Stability Features:
|
|
1422
|
+
⢠Auto-restart on crashes (--stability flag)
|
|
1423
|
+
⢠Circuit breaker pattern
|
|
1424
|
+
⢠Graceful shutdown handling
|
|
1425
|
+
⢠Process supervision
|
|
1426
|
+
|
|
1427
|
+
Production Features:
|
|
1428
|
+
š Automatic documentation generation
|
|
1429
|
+
š Cross-platform remote execution support
|
|
1430
|
+
š¤ Seamless Claude Code MCP integration
|
|
1431
|
+
š§ Advanced hooks for automation
|
|
1432
|
+
š§ Neural pattern learning
|
|
1433
|
+
š¾ Cross-session memory persistence
|
|
1434
|
+
š”ļø Security and stability hardening
|
|
1435
|
+
|
|
1436
|
+
For detailed documentation, check .claude/commands/ after running init --claude
|
|
1437
|
+
`);
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
async function main() {
|
|
1441
|
+
const args = process.argv.slice(2);
|
|
1442
|
+
|
|
1443
|
+
// Handle --version flag
|
|
1444
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
1445
|
+
const version = await getVersion();
|
|
1446
|
+
console.log(version);
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
const command = args[0] || 'help';
|
|
1451
|
+
|
|
1452
|
+
try {
|
|
1453
|
+
switch (command) {
|
|
1454
|
+
case 'init':
|
|
1455
|
+
await handleInit(args.slice(1));
|
|
1456
|
+
break;
|
|
1457
|
+
case 'spawn':
|
|
1458
|
+
await handleSpawn(args.slice(1));
|
|
1459
|
+
break;
|
|
1460
|
+
case 'orchestrate':
|
|
1461
|
+
await handleOrchestrate(args.slice(1));
|
|
1462
|
+
break;
|
|
1463
|
+
case 'mcp':
|
|
1464
|
+
await handleMcp(args.slice(1));
|
|
1465
|
+
break;
|
|
1466
|
+
case 'status':
|
|
1467
|
+
await handleStatus(args.slice(1));
|
|
1468
|
+
break;
|
|
1469
|
+
case 'monitor':
|
|
1470
|
+
await handleMonitor(args.slice(1));
|
|
1471
|
+
break;
|
|
1472
|
+
case 'hook':
|
|
1473
|
+
await handleHook(args.slice(1));
|
|
1474
|
+
break;
|
|
1475
|
+
case 'claude-invoke':
|
|
1476
|
+
case 'claude':
|
|
1477
|
+
await handleClaudeInvoke(args.slice(1));
|
|
1478
|
+
break;
|
|
1479
|
+
case 'neural':
|
|
1480
|
+
await handleNeural(args.slice(1));
|
|
1481
|
+
break;
|
|
1482
|
+
case 'benchmark':
|
|
1483
|
+
await handleBenchmark(args.slice(1));
|
|
1484
|
+
break;
|
|
1485
|
+
case 'performance':
|
|
1486
|
+
await handlePerformance(args.slice(1));
|
|
1487
|
+
break;
|
|
1488
|
+
case 'diagnose':
|
|
1489
|
+
await handleDiagnose(args.slice(1));
|
|
1490
|
+
break;
|
|
1491
|
+
case 'version':
|
|
1492
|
+
const version = await getVersion();
|
|
1493
|
+
console.log('@sparkleideas/ruv-swarm v' + version);
|
|
1494
|
+
console.log('Production-ready WASM-powered neural swarm orchestration');
|
|
1495
|
+
console.log('Security & Stability Enhanced Edition');
|
|
1496
|
+
console.log('\nš Security Features:');
|
|
1497
|
+
console.log(' ⢠Input validation and sanitization');
|
|
1498
|
+
console.log(' ⢠Explicit permission control for Claude invocation');
|
|
1499
|
+
console.log(' ⢠Command injection prevention');
|
|
1500
|
+
console.log(' ⢠WASM integrity verification');
|
|
1501
|
+
console.log('\nš”ļø Stability Features:');
|
|
1502
|
+
console.log(' ⢠Auto-restart on crashes (use --stability flag)');
|
|
1503
|
+
console.log(' ⢠Circuit breaker pattern');
|
|
1504
|
+
console.log(' ⢠Graceful shutdown handling');
|
|
1505
|
+
console.log(' ⢠Process supervision');
|
|
1506
|
+
console.log('\nā
Security Status: All vulnerabilities from Issue #107 resolved');
|
|
1507
|
+
console.log('š Production Status: Ready for deployment');
|
|
1508
|
+
break;
|
|
1509
|
+
case 'help':
|
|
1510
|
+
default:
|
|
1511
|
+
await showHelp();
|
|
1512
|
+
break;
|
|
1513
|
+
}
|
|
1514
|
+
} catch (error) {
|
|
1515
|
+
console.error('ā Error:', error.message);
|
|
1516
|
+
if (process.argv.includes('--debug')) {
|
|
1517
|
+
console.error(error.stack);
|
|
1518
|
+
}
|
|
1519
|
+
process.exit(1);
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
// Bulletproof error handling - LOG but NEVER exit
|
|
1524
|
+
process.on('uncaughtException', (error) => {
|
|
1525
|
+
console.error('ā ļø Uncaught Exception (continuing operation):', error.message);
|
|
1526
|
+
if (process.argv.includes('--debug')) {
|
|
1527
|
+
console.error(error.stack);
|
|
1528
|
+
}
|
|
1529
|
+
if (isStabilityMode) {
|
|
1530
|
+
stabilityLog(`Uncaught exception: ${error.message} - continuing...`);
|
|
1531
|
+
}
|
|
1532
|
+
// DO NOT EXIT - bulletproof operation continues
|
|
1533
|
+
});
|
|
1534
|
+
|
|
1535
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
1536
|
+
console.error('ā ļø Unhandled Rejection (continuing operation):', reason);
|
|
1537
|
+
if (process.argv.includes('--debug')) {
|
|
1538
|
+
console.error('Promise:', promise);
|
|
1539
|
+
}
|
|
1540
|
+
if (isStabilityMode) {
|
|
1541
|
+
stabilityLog(`Unhandled rejection: ${reason} - continuing...`);
|
|
1542
|
+
}
|
|
1543
|
+
// DO NOT EXIT - bulletproof operation continues
|
|
1544
|
+
});
|
|
1545
|
+
|
|
1546
|
+
// In ES modules, this file is always the main module when run directly
|
|
1547
|
+
main();
|
|
1548
|
+
|
|
1549
|
+
export { main, initializeSystem };
|