UNPKG

claude-flow-tbowman01

Version:

Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)

641 lines (554 loc) • 19.2 kB
/** * ruv-swarm CLI commands for Claude Code integration * * This module provides CLI commands that interact with the ruv-swarm * package to enable advanced swarm coordination and neural capabilities. */ import { success, error, warning, info } from '../cli-core.js'; import type { CommandContext } from '../cli-core.js'; import { getRuvSwarmConfigManager } from '../../config/ruv-swarm-config.js'; import { execAsync } from '../../utils/helpers.js'; import { Logger } from '../../core/logger.js'; import { isRuvSwarmAvailable, initializeRuvSwarmIntegration } from '../../mcp/ruv-swarm-tools.js'; // Create logger for CLI commands const logger = new Logger({ level: 'info', format: 'text', destination: 'console' }); /** * Main ruv-swarm command handler */ export async function ruvSwarmAction(ctx: CommandContext) { if (ctx.flags.help || ctx.flags.h || ctx.args.length === 0) { showRuvSwarmHelp(); return; } const subcommand = ctx.args[0]; const subArgs = ctx.args.slice(1); const subCtx: CommandContext = { ...ctx, args: subArgs, }; try { // Check if ruv-swarm is available first const available = await isRuvSwarmAvailable(logger); if (!available) { error('ruv-swarm is not available'); console.log('Install it with: npm install -g ruv-swarm'); console.log('Or locally: npm install ruv-swarm'); return; } switch (subcommand) { case 'init': await handleInit(subCtx); break; case 'status': await handleStatus(subCtx); break; case 'spawn': await handleSpawn(subCtx); break; case 'list': await handleList(subCtx); break; case 'orchestrate': await handleOrchestrate(subCtx); break; case 'monitor': await handleMonitor(subCtx); break; case 'neural': await handleNeural(subCtx); break; case 'benchmark': await handleBenchmark(subCtx); break; case 'config': await handleConfig(subCtx); break; case 'memory': await handleMemory(subCtx); break; default: error(`Unknown ruv-swarm subcommand: ${subcommand}`); showRuvSwarmHelp(); break; } } catch (err) { error(`ruv-swarm command failed: ${(err as Error).message}`); } } /** * Show ruv-swarm help */ function showRuvSwarmHelp() { console.log( 'ruv-swarm - Advanced AI swarm coordination with neural capabilities\ ', ); console.log('Usage:'); console.log( ' claude-flow ruv-swarm <command> [options]\ ', ); console.log('Commands:'); console.log(' init Initialize a new ruv-swarm'); console.log(' status [--verbose] Get swarm status'); console.log(' spawn <type> [--name] Spawn a new agent'); console.log(' list [--filter] List all agents'); console.log(' orchestrate <task> Orchestrate a task across the swarm'); console.log(' monitor [--duration] Monitor swarm activity'); console.log(' neural <subcommand> Neural capabilities management'); console.log(' benchmark [--type] Run performance benchmarks'); console.log(' config <subcommand> Configuration management'); console.log( ' memory [--detail] Memory usage and management\ ', ); console.log('Examples:'); console.log(' claude-flow ruv-swarm init --topology mesh --max-agents 8'); console.log(' claude-flow ruv-swarm spawn researcher --name \"AI Researcher\"'); console.log(' claude-flow ruv-swarm orchestrate \"Build a REST API\"'); console.log(' claude-flow ruv-swarm neural train --iterations 20'); console.log(' claude-flow ruv-swarm benchmark --type swarm'); } /** * Handle swarm initialization */ async function handleInit(ctx: CommandContext) { const topology = (ctx.flags.topology as string) || 'mesh'; const maxAgents = (ctx.flags.maxAgents as number) || (ctx.flags['max-agents'] as number) || 5; const strategy = (ctx.flags.strategy as string) || 'balanced'; if (!['mesh', 'hierarchical', 'ring', 'star'].includes(topology)) { error('Invalid topology. Use: mesh, hierarchical, ring, or star'); return; } if (maxAgents < 1 || maxAgents > 100) { error('Max agents must be between 1 and 100'); return; } info(`Initializing ruv-swarm with ${topology} topology...`); try { const command = `npx ruv-swarm swarm init --topology ${topology} --max-agents ${maxAgents} --strategy ${strategy}`; const result = await execAsync(command); if (result.stdout) { success('Swarm initialized successfully!'); console.log(result.stdout); } // Initialize integration const integration = await initializeRuvSwarmIntegration(process.cwd(), logger); if (integration.success) { info('Claude Code integration enabled'); } else { warning(`Integration warning: ${integration.error}`); } } catch (err) { error(`Failed to initialize swarm: ${(err as Error).message}`); } } /** * Handle swarm status */ async function handleStatus(ctx: CommandContext) { const verbose = (ctx.flags.verbose as boolean) || (ctx.flags.v as boolean) || false; try { const command = `npx ruv-swarm swarm status${verbose ? ' --verbose' : ''}`; const result = await execAsync(command); if (result.stdout) { // Try to parse as JSON for better formatting try { const statusData = JSON.parse(result.stdout); if (statusData.success && statusData.data) { console.log( 'šŸ Swarm Status:\ ', ); const data = statusData.data; if (data.swarmId) { console.log(` Swarm ID: ${data.swarmId}`); } if (data.topology) { console.log(` Topology: ${data.topology}`); } if (data.agents !== undefined) { console.log(` Active Agents: ${data.agents.active || 0}/${data.agents.total || 0}`); } if (data.tasks !== undefined) { console.log( ` Tasks: ${data.tasks.completed || 0} completed, ${data.tasks.running || 0} running`, ); } if (data.memory) { console.log(` Memory Usage: ${data.memory.used || 'N/A'}`); } if (verbose && data.details) { console.log( '\ šŸ“‹ Detailed Status:', ); console.log(JSON.stringify(data.details, null, 2)); } } else { console.log(result.stdout); } } catch { // Not JSON, display as-is console.log(result.stdout); } } if (result.stderr) { warning(result.stderr); } } catch (err) { error(`Failed to get swarm status: ${(err as Error).message}`); } } /** * Handle agent spawning */ async function handleSpawn(ctx: CommandContext) { if (ctx.args.length === 0) { error('Agent type is required'); console.log('Usage: claude-flow ruv-swarm spawn <type> [--name <name>]'); console.log('Types: researcher, coder, analyst, optimizer, coordinator'); return; } const type = ctx.args[0]; const name = ctx.flags.name as string; const capabilities = ctx.flags.capabilities as string; if (!['researcher', 'coder', 'analyst', 'optimizer', 'coordinator'].includes(type)) { error('Invalid agent type'); console.log('Valid types: researcher, coder, analyst, optimizer, coordinator'); return; } info(`Spawning ${type} agent...`); try { let command = `npx ruv-swarm agent spawn --type ${type}`; if (name) { command += ` --name \"${name}\"`; } if (capabilities) { command += ` --capabilities \"${capabilities}\"`; } const result = await execAsync(command); if (result.stdout) { try { const spawnData = JSON.parse(result.stdout); if (spawnData.success) { success(`Agent spawned successfully!`); console.log(` Agent ID: ${spawnData.data.agentId}`); if (spawnData.data.agentName) { console.log(` Name: ${spawnData.data.agentName}`); } console.log(` Type: ${type}`); } else { error(`Failed to spawn agent: ${spawnData.error}`); } } catch { console.log(result.stdout); } } } catch (err) { error(`Failed to spawn agent: ${(err as Error).message}`); } } /** * Handle agent listing */ async function handleList(ctx: CommandContext) { const filter = (ctx.flags.filter as string) || 'all'; try { const command = `npx ruv-swarm agent list --filter ${filter}`; const result = await execAsync(command); if (result.stdout) { try { const listData = JSON.parse(result.stdout); if (listData.success && listData.data.agents) { console.log(`šŸ¤– Agents (${listData.data.count}):`); if (listData.data.count === 0) { console.log(' No agents found'); return; } listData.data.agents.forEach((agent: any, index: number) => { console.log(`\ ${index + 1}. ${agent.id || agent.agentId}`); console.log(` Type: ${agent.type}`); console.log(` Status: ${agent.status}`); if (agent.name && agent.name !== agent.id) { console.log(` Name: ${agent.name}`); } if (agent.capabilities && agent.capabilities.length > 0) { console.log(` Capabilities: ${agent.capabilities.join(', ')}`); } }); } else { console.log(result.stdout); } } catch { console.log(result.stdout); } } } catch (err) { error(`Failed to list agents: ${(err as Error).message}`); } } /** * Handle task orchestration */ async function handleOrchestrate(ctx: CommandContext) { if (ctx.args.length === 0) { error('Task description is required'); console.log('Usage: claude-flow ruv-swarm orchestrate \"<task description>\" [options]'); return; } const task = ctx.args.join(' '); const strategy = (ctx.flags.strategy as string) || 'adaptive'; const priority = (ctx.flags.priority as string) || 'medium'; const maxAgents = (ctx.flags.maxAgents as number) || (ctx.flags['max-agents'] as number); info(`Orchestrating task: ${task}`); try { let command = `npx ruv-swarm task orchestrate --task \"${task}\" --strategy ${strategy} --priority ${priority}`; if (maxAgents) { command += ` --max-agents ${maxAgents}`; } const result = await execAsync(command); if (result.stdout) { try { const taskData = JSON.parse(result.stdout); if (taskData.success) { success('Task orchestration started!'); console.log(` Task ID: ${taskData.data.taskId}`); console.log(` Strategy: ${strategy}`); console.log(` Priority: ${priority}`); if (taskData.data.assignedAgents) { console.log(` Assigned Agents: ${taskData.data.assignedAgents}`); } } else { error(`Failed to orchestrate task: ${taskData.error}`); } } catch { console.log(result.stdout); } } } catch (err) { error(`Failed to orchestrate task: ${(err as Error).message}`); } } /** * Handle swarm monitoring */ async function handleMonitor(ctx: CommandContext) { const duration = (ctx.flags.duration as number) || 30; const interval = (ctx.flags.interval as number) || 5; info(`Monitoring swarm for ${duration} seconds...`); try { const command = `npx ruv-swarm swarm monitor --duration ${duration} --interval ${interval}`; const result = await execAsync(command); if (result.stdout) { console.log(result.stdout); } } catch (err) { error(`Failed to monitor swarm: ${(err as Error).message}`); } } /** * Handle neural capabilities */ async function handleNeural(ctx: CommandContext) { if (ctx.args.length === 0) { console.log('Neural subcommands:'); console.log(' status - Get neural agent status'); console.log(' train - Train neural agents'); console.log(' patterns - View cognitive patterns'); return; } const subcommand = ctx.args[0]; try { switch (subcommand) { case 'status': { const agentId = (ctx.flags.agentId as string) || (ctx.flags['agent-id'] as string); let command = 'npx ruv-swarm neural status'; if (agentId) { command += ` --agent-id ${agentId}`; } const result = await execAsync(command); if (result.stdout) { console.log(result.stdout); } break; } case 'train': { const agentId = (ctx.flags.agentId as string) || (ctx.flags['agent-id'] as string); const iterations = (ctx.flags.iterations as number) || 10; let command = `npx ruv-swarm neural train --iterations ${iterations}`; if (agentId) { command += ` --agent-id ${agentId}`; } info(`Training neural agents for ${iterations} iterations...`); const result = await execAsync(command); if (result.stdout) { console.log(result.stdout); } break; } case 'patterns': { const pattern = (ctx.flags.pattern as string) || 'all'; const command = `npx ruv-swarm neural patterns --pattern ${pattern}`; const result = await execAsync(command); if (result.stdout) { console.log(result.stdout); } break; } default: error(`Unknown neural subcommand: ${subcommand}`); break; } } catch (err) { error(`Neural command failed: ${(err as Error).message}`); } } /** * Handle benchmarking */ async function handleBenchmark(ctx: CommandContext) { const type = (ctx.flags.type as string) || 'all'; const iterations = (ctx.flags.iterations as number) || 10; info(`Running ${type} benchmark with ${iterations} iterations...`); try { const command = `npx ruv-swarm benchmark run --type ${type} --iterations ${iterations}`; const result = await execAsync(command); if (result.stdout) { console.log(result.stdout); } } catch (err) { error(`Benchmark failed: ${(err as Error).message}`); } } /** * Handle configuration management */ async function handleConfig(ctx: CommandContext) { if (ctx.args.length === 0) { console.log('Config subcommands:'); console.log(' show - Show current configuration'); console.log(' set - Set configuration value'); console.log(' reset - Reset to defaults'); console.log(' validate - Validate configuration'); return; } const subcommand = ctx.args[0]; const configManager = getRuvSwarmConfigManager(logger); try { switch (subcommand) { case 'show': { const config = configManager.getConfig(); console.log( 'šŸ”§ ruv-swarm Configuration:\ ', ); console.log(JSON.stringify(config, null, 2)); break; } case 'set': { if (ctx.args.length < 3) { error('Usage: config set <section>.<key> <value>'); console.log('Example: config set swarm.maxAgents 10'); return; } const path = ctx.args[1]; const value = ctx.args[2]; const [section, key] = path.split('.'); if (!section || !key) { error('Invalid path format. Use: section.key'); return; } // Parse value let parsedValue: any = value; if (value === 'true') parsedValue = true; else if (value === 'false') parsedValue = false; else if (!isNaN(Number(value))) parsedValue = Number(value); const updates = { [section]: { [key]: parsedValue } }; configManager.updateConfig(updates); success(`Configuration updated: ${path} = ${value}`); break; } case 'reset': { configManager.resetConfig(); success('Configuration reset to defaults'); break; } case 'validate': { const validation = configManager.validateConfig(); if (validation.valid) { success('Configuration is valid'); } else { error('Configuration validation failed:'); validation.errors.forEach((err) => console.log(` - ${err}`)); } break; } default: error(`Unknown config subcommand: ${subcommand}`); break; } } catch (err) { error(`Config command failed: ${(err as Error).message}`); } } /** * Handle memory management */ async function handleMemory(ctx: CommandContext) { const detail = (ctx.flags.detail as string) || 'summary'; try { const command = `npx ruv-swarm memory usage --detail ${detail}`; const result = await execAsync(command); if (result.stdout) { try { const memoryData = JSON.parse(result.stdout); if (memoryData.success) { console.log( 'šŸ’¾ Memory Usage:\ ', ); const data = memoryData.data; if (data.total !== undefined) { console.log(` Total Memory: ${formatBytes(data.total)}`); } if (data.used !== undefined) { console.log(` Used Memory: ${formatBytes(data.used)}`); } if (data.available !== undefined) { console.log(` Available: ${formatBytes(data.available)}`); } if (data.swarmUsage !== undefined) { console.log(` Swarm Usage: ${formatBytes(data.swarmUsage)}`); } if (detail === 'detailed' && data.breakdown) { console.log( '\ šŸ“Š Memory Breakdown:', ); console.log(JSON.stringify(data.breakdown, null, 2)); } } else { console.log(result.stdout); } } catch { console.log(result.stdout); } } } catch (err) { error(`Failed to get memory usage: ${(err as Error).message}`); } } /** * Format bytes to human readable string */ function formatBytes(bytes: number): string { const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; if (bytes === 0) return '0 B'; const i = Math.floor(Math.log(bytes) / Math.log(1024)); return Math.round((bytes / Math.pow(1024, i)) * 100) / 100 + ' ' + sizes[i]; } export default { ruvSwarmAction, };