claude-flow-tbowman01
Version:
Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)
641 lines (554 loc) ⢠19.2 kB
text/typescript
/**
* 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,
};