claude-flow
Version:
Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration
927 lines • 36.7 kB
JavaScript
/**
* V3 CLI Agent Command
* Agent management commands for spawning, listing, and controlling agents
*/
import { output } from '../output.js';
import { select, confirm, input } from '../prompt.js';
import { callMCPTool, MCPClientError } from '../mcp-client.js';
import { wasmSubcommands } from './agent-wasm.js';
import * as fs from 'fs';
import * as path from 'path';
/**
* Update swarm-activity.json metrics after agent count changes.
* The statusline reads this file to display the swarm agent count.
*/
function updateSwarmActivityMetrics(agentCountDelta) {
try {
const metricsDir = path.join(process.cwd(), '.claude-flow', 'metrics');
const activityPath = path.join(metricsDir, 'swarm-activity.json');
let data = {
timestamp: new Date().toISOString(),
swarm: { active: false, agent_count: 0, coordination_active: false },
};
if (fs.existsSync(activityPath)) {
data = JSON.parse(fs.readFileSync(activityPath, 'utf-8'));
}
else {
fs.mkdirSync(metricsDir, { recursive: true });
}
const swarm = data.swarm ?? {};
const currentCount = Math.max(0, swarm.agent_count || 0);
const newCount = Math.max(0, currentCount + agentCountDelta);
swarm.agent_count = newCount;
swarm.active = newCount > 0;
swarm.coordination_active = newCount > 0;
data.swarm = swarm;
data.timestamp = new Date().toISOString();
fs.writeFileSync(activityPath, JSON.stringify(data, null, 2));
}
catch {
// Non-critical — don't fail the command if metrics update fails
}
}
// Available agent types with descriptions
const AGENT_TYPES = [
{ value: 'coder', label: 'Coder', hint: 'Code development with neural patterns' },
{ value: 'researcher', label: 'Researcher', hint: 'Research with web access and data analysis' },
{ value: 'tester', label: 'Tester', hint: 'Comprehensive testing with automation' },
{ value: 'reviewer', label: 'Reviewer', hint: 'Code review with security and quality checks' },
{ value: 'architect', label: 'Architect', hint: 'System design with enterprise patterns' },
{ value: 'coordinator', label: 'Coordinator', hint: 'Multi-agent orchestration and workflow' },
{ value: 'analyst', label: 'Analyst', hint: 'Performance analysis and optimization' },
{ value: 'optimizer', label: 'Optimizer', hint: 'Performance optimization and bottleneck analysis' },
{ value: 'security-architect', label: 'Security Architect', hint: 'Security architecture and threat modeling' },
{ value: 'security-auditor', label: 'Security Auditor', hint: 'CVE remediation and security testing' },
{ value: 'memory-specialist', label: 'Memory Specialist', hint: 'AgentDB unification (150x-12,500x faster)' },
{ value: 'swarm-specialist', label: 'Swarm Specialist', hint: 'Unified coordination engine' },
{ value: 'performance-engineer', label: 'Performance Engineer', hint: '2.49x-7.47x optimization targets' },
{ value: 'core-architect', label: 'Core Architect', hint: 'Domain-driven design restructure' },
{ value: 'test-architect', label: 'Test Architect', hint: 'TDD London School methodology' }
];
// Agent spawn subcommand
const spawnCommand = {
name: 'spawn',
description: 'Spawn a new agent',
options: [
{
name: 'type',
short: 't',
description: 'Agent type to spawn',
type: 'string',
choices: AGENT_TYPES.map(a => a.value)
},
{
name: 'name',
short: 'n',
description: 'Agent name/identifier',
type: 'string'
},
{
name: 'provider',
short: 'p',
description: 'Provider to use (anthropic, openrouter, ollama)',
type: 'string',
default: 'anthropic'
},
{
name: 'model',
short: 'm',
description: 'Model to use',
type: 'string'
},
{
name: 'task',
description: 'Initial task for the agent',
type: 'string'
},
{
name: 'timeout',
description: 'Agent timeout in seconds',
type: 'number',
default: 300
},
{
name: 'auto-tools',
description: 'Enable automatic tool usage',
type: 'boolean',
default: true
}
],
examples: [
{ command: 'claude-flow agent spawn --type coder --name bot-1', description: 'Spawn a coder agent' },
{ command: 'claude-flow agent spawn -t researcher --task "Research React 19"', description: 'Spawn researcher with task' }
],
action: async (ctx) => {
let agentType = ctx.flags.type;
let agentName = ctx.flags.name;
// Interactive mode if type not specified
if (!agentType && ctx.interactive) {
agentType = await select({
message: 'Select agent type:',
options: AGENT_TYPES
});
}
if (!agentType) {
output.printError('Agent type is required. Use --type or -t flag.');
return { success: false, exitCode: 1 };
}
// Generate name if not provided
if (!agentName) {
agentName = `${agentType}-${Date.now().toString(36)}`;
}
output.printInfo(`Spawning ${agentType} agent: ${output.highlight(agentName)}`);
try {
// Call MCP tool to spawn agent
const result = await callMCPTool('agent_spawn', {
agentType,
id: agentName,
config: {
provider: ctx.flags.provider || 'anthropic',
model: ctx.flags.model,
task: ctx.flags.task,
timeout: ctx.flags.timeout,
autoTools: ctx.flags.autoTools,
},
priority: 'normal',
metadata: {
name: agentName,
capabilities: getAgentCapabilities(agentType),
},
});
output.writeln();
output.printTable({
columns: [
{ key: 'property', header: 'Property', width: 15 },
{ key: 'value', header: 'Value', width: 40 }
],
data: [
{ property: 'ID', value: result.agentId },
{ property: 'Type', value: result.agentType },
{ property: 'Name', value: agentName },
{ property: 'Status', value: result.status },
{ property: 'Created', value: result.createdAt },
{ property: 'Capabilities', value: getAgentCapabilities(agentType).join(', ') }
]
});
output.writeln();
output.printSuccess(`Agent ${agentName} spawned successfully`);
// Update swarm-activity.json so statusline reflects the new agent count
updateSwarmActivityMetrics(1);
if (ctx.flags.format === 'json') {
output.printJson(result);
}
return { success: true, data: result };
}
catch (error) {
if (error instanceof MCPClientError) {
output.printError(`Failed to spawn agent: ${error.message}`);
}
else {
output.printError(`Unexpected error: ${String(error)}`);
}
return { success: false, exitCode: 1 };
}
}
};
// Agent list subcommand
const listCommand = {
name: 'list',
aliases: ['ls'],
description: 'List all active agents',
options: [
{
name: 'all',
short: 'a',
description: 'Include inactive agents',
type: 'boolean',
default: false
},
{
name: 'type',
short: 't',
description: 'Filter by agent type',
type: 'string'
},
{
name: 'status',
short: 's',
description: 'Filter by status',
type: 'string'
}
],
action: async (ctx) => {
try {
// Call MCP tool to list agents
const result = await callMCPTool('agent_list', {
status: ctx.flags.all ? 'all' : ctx.flags.status || undefined,
agentType: ctx.flags.type || undefined,
limit: 100,
});
if (ctx.flags.format === 'json') {
output.printJson(result);
return { success: true, data: result };
}
output.writeln();
output.writeln(output.bold('Active Agents'));
output.writeln();
if (result.agents.length === 0) {
output.printInfo('No agents found matching criteria');
return { success: true, data: result };
}
// Format for display
const displayAgents = result.agents.map(agent => ({
id: agent.id,
type: agent.agentType,
status: agent.status,
created: new Date(agent.createdAt).toLocaleTimeString(),
lastActivity: agent.lastActivityAt
? new Date(agent.lastActivityAt).toLocaleTimeString()
: 'N/A',
}));
output.printTable({
columns: [
{ key: 'id', header: 'ID', width: 20 },
{ key: 'type', header: 'Type', width: 15 },
{ key: 'status', header: 'Status', width: 12, format: formatStatus },
{ key: 'created', header: 'Created', width: 12 },
{ key: 'lastActivity', header: 'Last Activity', width: 12 }
],
data: displayAgents
});
output.writeln();
output.printInfo(`Total: ${result.total} agents`);
return { success: true, data: result };
}
catch (error) {
if (error instanceof MCPClientError) {
output.printError(`Failed to list agents: ${error.message}`);
}
else {
output.printError(`Unexpected error: ${String(error)}`);
}
return { success: false, exitCode: 1 };
}
}
};
// Agent status subcommand
const statusCommand = {
name: 'status',
description: 'Show detailed status of an agent',
options: [
{
name: 'id',
description: 'Agent ID',
type: 'string'
}
],
action: async (ctx) => {
let agentId = ctx.args[0] || ctx.flags.id;
if (!agentId && ctx.interactive) {
agentId = await input({
message: 'Enter agent ID:',
validate: (v) => v.length > 0 || 'Agent ID is required'
});
}
if (!agentId) {
output.printError('Agent ID is required');
return { success: false, exitCode: 1 };
}
try {
// Call MCP tool to get agent status
const status = await callMCPTool('agent_status', {
agentId,
includeMetrics: true,
includeHistory: false,
});
if (ctx.flags.format === 'json') {
output.printJson(status);
return { success: true, data: status };
}
output.writeln();
output.printBox([
`Type: ${status.agentType}`,
`Status: ${formatStatus(status.status)}`,
`Created: ${new Date(status.createdAt).toLocaleString()}`,
`Last Activity: ${status.lastActivityAt ? new Date(status.lastActivityAt).toLocaleString() : 'N/A'}`
].join('\n'), `Agent: ${status.id}`);
if (status.metrics) {
output.writeln();
output.writeln(output.bold('Metrics'));
const avgExecTime = status.metrics.averageExecutionTime ?? 0;
const uptime = status.metrics.uptime ?? 0;
output.printTable({
columns: [
{ key: 'metric', header: 'Metric', width: 25 },
{ key: 'value', header: 'Value', width: 15, align: 'right' }
],
data: [
{ metric: 'Tasks Completed', value: status.metrics.tasksCompleted ?? 0 },
{ metric: 'Tasks In Progress', value: status.metrics.tasksInProgress ?? 0 },
{ metric: 'Tasks Failed', value: status.metrics.tasksFailed ?? 0 },
{ metric: 'Avg Execution Time', value: `${avgExecTime.toFixed(2)}ms` },
{ metric: 'Uptime', value: `${(uptime / 1000 / 60).toFixed(1)}m` }
]
});
}
return { success: true, data: status };
}
catch (error) {
if (error instanceof MCPClientError) {
output.printError(`Failed to get agent status: ${error.message}`);
}
else {
output.printError(`Unexpected error: ${String(error)}`);
}
return { success: false, exitCode: 1 };
}
}
};
// Agent stop subcommand
const stopCommand = {
name: 'stop',
aliases: ['kill'],
description: 'Stop a running agent',
options: [
{
name: 'force',
short: 'f',
description: 'Force stop without graceful shutdown',
type: 'boolean',
default: false
},
{
name: 'timeout',
description: 'Graceful shutdown timeout in seconds',
type: 'number',
default: 30
}
],
action: async (ctx) => {
const agentId = ctx.args[0];
if (!agentId) {
output.printError('Agent ID is required');
return { success: false, exitCode: 1 };
}
const force = ctx.flags.force;
if (!force && ctx.interactive) {
const confirmed = await confirm({
message: `Are you sure you want to stop agent ${agentId}?`,
default: false
});
if (!confirmed) {
output.printInfo('Operation cancelled');
return { success: true };
}
}
output.printInfo(`Stopping agent ${agentId}...`);
try {
// Call MCP tool to terminate agent
const result = await callMCPTool('agent_terminate', {
agentId,
graceful: !force,
reason: 'Stopped by user via CLI',
});
if (!force) {
output.writeln(output.dim(' Completing current task...'));
output.writeln(output.dim(' Saving state...'));
output.writeln(output.dim(' Releasing resources...'));
}
output.printSuccess(`Agent ${agentId} stopped successfully`);
// Update swarm-activity.json so statusline reflects the reduced agent count
updateSwarmActivityMetrics(-1);
if (ctx.flags.format === 'json') {
output.printJson(result);
}
return { success: true, data: result };
}
catch (error) {
if (error instanceof MCPClientError) {
output.printError(`Failed to stop agent: ${error.message}`);
}
else {
output.printError(`Unexpected error: ${String(error)}`);
}
return { success: false, exitCode: 1 };
}
}
};
// Agent metrics subcommand
const metricsCommand = {
name: 'metrics',
description: 'Show agent performance metrics',
options: [
{
name: 'period',
short: 'p',
description: 'Time period (1h, 24h, 7d, 30d)',
type: 'string',
default: '24h'
}
],
action: async (ctx) => {
const agentId = ctx.args[0];
const period = ctx.flags.period;
// Collect real metrics from .swarm/ state
const { existsSync, readFileSync, readdirSync, statSync } = await import('fs');
const { join } = await import('path');
let totalAgents = 0;
let activeAgents = 0;
let tasksCompleted = 0;
const typeCounts = {};
// Read swarm agent state
const swarmDir = join(process.cwd(), '.swarm');
const agentsDir = join(swarmDir, 'agents');
if (existsSync(agentsDir)) {
try {
const files = readdirSync(agentsDir).filter(f => f.endsWith('.json'));
for (const file of files) {
try {
const data = JSON.parse(readFileSync(join(agentsDir, file), 'utf-8'));
totalAgents++;
const agType = data.type || 'unknown';
if (!typeCounts[agType])
typeCounts[agType] = { count: 0, tasks: 0, success: 0 };
typeCounts[agType].count++;
if (data.status === 'active' || data.status === 'running')
activeAgents++;
if (data.tasksCompleted) {
typeCounts[agType].tasks += data.tasksCompleted;
tasksCompleted += data.tasksCompleted;
}
if (data.successCount)
typeCounts[agType].success += data.successCount;
}
catch { /* skip malformed */ }
}
}
catch { /* no agents dir */ }
}
// Read swarm activity for additional state
const activityFile = join(swarmDir, 'swarm-activity.json');
if (existsSync(activityFile)) {
try {
const activity = JSON.parse(readFileSync(activityFile, 'utf-8'));
if (activity.totalAgents && totalAgents === 0)
totalAgents = activity.totalAgents;
if (activity.activeAgents && activeAgents === 0)
activeAgents = activity.activeAgents;
}
catch { /* ignore */ }
}
// Read memory.db stats
let vectorCount = 0;
const dbPath = join(swarmDir, 'memory.db');
if (existsSync(dbPath)) {
try {
const dbSize = statSync(dbPath).size;
vectorCount = Math.floor(dbSize / 2048);
}
catch { /* ignore */ }
}
const byType = Object.entries(typeCounts).map(([type, data]) => ({
type,
count: data.count,
tasks: data.tasks,
successRate: data.tasks > 0 ? `${Math.round((data.success / data.tasks) * 100)}%` : 'N/A'
}));
const avgSuccessRate = tasksCompleted > 0
? `${Math.round(Object.values(typeCounts).reduce((a, d) => a + d.success, 0) / tasksCompleted * 100)}%`
: 'N/A';
const metrics = {
period,
summary: {
totalAgents,
activeAgents,
tasksCompleted,
avgSuccessRate,
vectorCount,
note: totalAgents === 0 ? 'No agents spawned yet. Use: agent spawn -t coder' : undefined
},
byType,
performance: {
memoryVectors: `${vectorCount} vectors`,
searchBackend: vectorCount > 0 ? 'HNSW-indexed' : 'none'
}
};
if (ctx.flags.format === 'json') {
output.printJson(metrics);
return { success: true, data: metrics };
}
output.writeln();
output.writeln(output.bold(`Agent Metrics (${period})`));
output.writeln();
output.printTable({
columns: [
{ key: 'metric', header: 'Metric', width: 20 },
{ key: 'value', header: 'Value', width: 15, align: 'right' }
],
data: [
{ metric: 'Total Agents', value: metrics.summary.totalAgents },
{ metric: 'Active Agents', value: metrics.summary.activeAgents },
{ metric: 'Tasks Completed', value: metrics.summary.tasksCompleted },
{ metric: 'Success Rate', value: metrics.summary.avgSuccessRate },
{ metric: 'Memory Vectors', value: metrics.summary.vectorCount }
]
});
output.writeln();
output.writeln(output.bold('By Agent Type'));
output.printTable({
columns: [
{ key: 'type', header: 'Type', width: 12 },
{ key: 'count', header: 'Count', width: 8, align: 'right' },
{ key: 'tasks', header: 'Tasks', width: 8, align: 'right' },
{ key: 'successRate', header: 'Success', width: 10, align: 'right' }
],
data: metrics.byType
});
if (metrics.summary.note) {
output.writeln();
output.writeln(output.dim(metrics.summary.note));
}
output.writeln();
output.writeln(output.bold('Memory'));
output.printList([
`Vectors: ${output.success(metrics.performance.memoryVectors)}`,
`Backend: ${output.success(metrics.performance.searchBackend)}`
]);
return { success: true, data: metrics };
}
};
// Agent pool subcommand
const poolCommand = {
name: 'pool',
description: 'Manage agent pool for scaling',
options: [
{
name: 'size',
short: 's',
description: 'Pool size',
type: 'number'
},
{
name: 'min',
description: 'Minimum pool size',
type: 'number',
default: 1
},
{
name: 'max',
description: 'Maximum pool size',
type: 'number',
default: 10
},
{
name: 'auto-scale',
short: 'a',
description: 'Enable auto-scaling',
type: 'boolean',
default: true
}
],
examples: [
{ command: 'claude-flow agent pool --size 5', description: 'Set pool size' },
{ command: 'claude-flow agent pool --min 2 --max 15', description: 'Configure auto-scaling' }
],
action: async (ctx) => {
try {
const result = await callMCPTool('agent_pool', {
size: ctx.flags.size,
min: ctx.flags.min,
max: ctx.flags.max,
autoScale: ctx.flags.autoScale ?? true,
});
if (ctx.flags.format === 'json') {
output.printJson(result);
return { success: true, data: result };
}
output.writeln();
const utilization = result.utilization ?? 0;
output.printBox([
`Pool ID: ${result.poolId ?? 'default'}`,
`Current Size: ${result.currentSize ?? 0}`,
`Min/Max: ${result.minSize ?? 0}/${result.maxSize ?? 100}`,
`Auto-Scale: ${result.autoScale ? 'Yes' : 'No'}`,
`Utilization: ${(utilization * 100).toFixed(1)}%`
].join('\n'), 'Agent Pool');
const agents = result.agents ?? [];
if (agents.length > 0) {
output.writeln();
output.writeln(output.bold('Pool Agents'));
output.printTable({
columns: [
{ key: 'id', header: 'ID', width: 20 },
{ key: 'type', header: 'Type', width: 15 },
{ key: 'status', header: 'Status', width: 12, format: formatStatus }
],
data: agents
});
}
return { success: true, data: result };
}
catch (error) {
if (error instanceof MCPClientError) {
output.printError(`Pool error: ${error.message}`);
}
else {
output.printError(`Unexpected error: ${String(error)}`);
}
return { success: false, exitCode: 1 };
}
}
};
// Agent health subcommand
const healthCommand = {
name: 'health',
description: 'Show agent health and metrics',
options: [
{
name: 'id',
short: 'i',
description: 'Agent ID (all if not specified)',
type: 'string'
},
{
name: 'detailed',
short: 'd',
description: 'Show detailed health metrics',
type: 'boolean',
default: false
},
{
name: 'watch',
short: 'w',
description: 'Watch mode (refresh every 5s)',
type: 'boolean',
default: false
}
],
examples: [
{ command: 'claude-flow agent health', description: 'Show all agents health' },
{ command: 'claude-flow agent health -i agent-001 -d', description: 'Detailed health for specific agent' }
],
action: async (ctx) => {
const agentId = ctx.args[0] || ctx.flags.id;
const detailed = ctx.flags.detailed;
try {
const result = await callMCPTool('agent_health', {
agentId,
detailed,
});
if (ctx.flags.format === 'json') {
output.printJson(result);
return { success: true, data: result };
}
output.writeln();
output.writeln(output.bold('Agent Health'));
output.writeln();
// Overall summary with null checks
const overall = result.overall ?? { healthy: 0, degraded: 0, unhealthy: 0, avgCpu: 0, avgMemory: 0 };
const avgCpu = overall.avgCpu ?? 0;
const avgMemory = overall.avgMemory ?? 0;
output.printBox([
`Healthy: ${output.success(String(overall.healthy ?? 0))}`,
`Degraded: ${output.warning(String(overall.degraded ?? 0))}`,
`Unhealthy: ${output.error(String(overall.unhealthy ?? 0))}`,
`Avg CPU: ${avgCpu.toFixed(1)}%`,
`Avg Memory: ${(avgMemory * 100).toFixed(1)}%`
].join(' | '), 'Overall Status');
const healthAgents = result.agents ?? [];
output.writeln();
output.printTable({
columns: [
{ key: 'id', header: 'Agent ID', width: 18 },
{ key: 'type', header: 'Type', width: 12 },
{ key: 'health', header: 'Health', width: 10, format: formatHealthStatus },
{ key: 'cpu', header: 'CPU %', width: 8, align: 'right', format: (v) => `${Number(v ?? 0).toFixed(1)}%` },
{ key: 'memory', header: 'Memory', width: 10, align: 'right', format: (v) => {
const mem = v;
if (!mem)
return '0%';
return `${(mem.used / mem.limit * 100).toFixed(0)}%`;
} },
{ key: 'tasks', header: 'Tasks', width: 12, align: 'right', format: (v) => {
const t = v;
if (!t)
return '0/0';
return `${t.active ?? 0}/${t.completed ?? 0}`;
} }
],
data: healthAgents
});
if (detailed && healthAgents.length > 0) {
output.writeln();
output.writeln(output.bold('Detailed Metrics'));
for (const agent of healthAgents) {
output.writeln();
output.writeln(output.highlight(agent.id));
const uptime = agent.uptime ?? 0;
const latency = agent.latency ?? { avg: 0, p99: 0 };
const tasks = agent.tasks ?? { completed: 0, failed: 0, queued: 0 };
const errors = agent.errors ?? { count: 0 };
output.printList([
`Uptime: ${(uptime / 1000 / 60).toFixed(1)} min`,
`Latency: avg ${(latency.avg ?? 0).toFixed(1)}ms, p99 ${(latency.p99 ?? 0).toFixed(1)}ms`,
`Tasks: ${tasks.completed ?? 0} completed, ${tasks.failed ?? 0} failed, ${tasks.queued ?? 0} queued`,
`Errors: ${errors.count ?? 0}${errors.lastError ? ` (${errors.lastError})` : ''}`
]);
}
}
return { success: true, data: result };
}
catch (error) {
if (error instanceof MCPClientError) {
output.printError(`Health check error: ${error.message}`);
}
else {
output.printError(`Unexpected error: ${String(error)}`);
}
return { success: false, exitCode: 1 };
}
}
};
// Agent logs subcommand
const logsCommand = {
name: 'logs',
description: 'Show agent activity logs',
options: [
{
name: 'id',
short: 'i',
description: 'Agent ID',
type: 'string'
},
{
name: 'tail',
short: 'n',
description: 'Number of recent entries',
type: 'number',
default: 50
},
{
name: 'level',
short: 'l',
description: 'Minimum log level',
type: 'string',
choices: ['debug', 'info', 'warn', 'error'],
default: 'info'
},
{
name: 'follow',
short: 'f',
description: 'Follow log output',
type: 'boolean',
default: false
},
{
name: 'since',
description: 'Show logs since (e.g., "1h", "30m")',
type: 'string'
}
],
examples: [
{ command: 'claude-flow agent logs -i agent-001', description: 'Show agent logs' },
{ command: 'claude-flow agent logs -i agent-001 -f', description: 'Follow agent logs' },
{ command: 'claude-flow agent logs -l error --since 1h', description: 'Show errors from last hour' }
],
action: async (ctx) => {
const agentId = ctx.args[0] || ctx.flags.id;
const tail = ctx.flags.tail;
const level = ctx.flags.level;
if (!agentId) {
output.printError('Agent ID is required. Use --id or -i');
return { success: false, exitCode: 1 };
}
try {
const result = await callMCPTool('agent_logs', {
agentId,
tail,
level,
since: ctx.flags.since,
});
if (ctx.flags.format === 'json') {
output.printJson(result);
return { success: true, data: result };
}
output.writeln();
output.writeln(output.bold(`Logs for ${agentId}`));
output.writeln(output.dim(`Showing ${result.entries.length} of ${result.total} entries`));
output.writeln();
for (const entry of result.entries) {
const time = new Date(entry.timestamp).toLocaleTimeString();
const levelStr = formatLogLevel(entry.level);
output.writeln(`${output.dim(time)} ${levelStr} ${entry.message}`);
if (entry.context && Object.keys(entry.context).length > 0) {
output.writeln(output.dim(` ${JSON.stringify(entry.context)}`));
}
}
return { success: true, data: result };
}
catch (error) {
if (error instanceof MCPClientError) {
output.printError(`Logs error: ${error.message}`);
}
else {
output.printError(`Unexpected error: ${String(error)}`);
}
return { success: false, exitCode: 1 };
}
}
};
function formatHealthStatus(health) {
const h = String(health);
switch (h) {
case 'healthy':
return output.success(h);
case 'degraded':
return output.warning(h);
case 'unhealthy':
return output.error(h);
default:
return h;
}
}
function formatLogLevel(level) {
switch (level) {
case 'debug':
return output.dim('[DEBUG]');
case 'info':
return '[INFO] ';
case 'warn':
return output.warning('[WARN] ');
case 'error':
return output.error('[ERROR]');
default:
return `[${level.toUpperCase()}]`;
}
}
// Main agent command
export const agentCommand = {
name: 'agent',
description: 'Agent management commands',
subcommands: [spawnCommand, listCommand, statusCommand, stopCommand, metricsCommand, poolCommand, healthCommand, logsCommand, ...wasmSubcommands],
options: [],
examples: [
{ command: 'claude-flow agent spawn -t coder', description: 'Spawn a coder agent' },
{ command: 'claude-flow agent list', description: 'List all agents' },
{ command: 'claude-flow agent status agent-001', description: 'Show agent status' }
],
action: async (ctx) => {
// Show help if no subcommand
output.writeln();
output.writeln(output.bold('Agent Management Commands'));
output.writeln();
output.writeln('Usage: claude-flow agent <subcommand> [options]');
output.writeln();
output.writeln('Subcommands:');
output.printList([
`${output.highlight('spawn')} - Spawn a new agent`,
`${output.highlight('list')} - List all active agents`,
`${output.highlight('status')} - Show detailed agent status`,
`${output.highlight('stop')} - Stop a running agent`,
`${output.highlight('metrics')} - Show agent metrics`,
`${output.highlight('pool')} - Manage agent pool`,
`${output.highlight('health')} - Show agent health`,
`${output.highlight('logs')} - Show agent logs`,
`${output.highlight('wasm-status')} - Check WASM runtime availability`,
`${output.highlight('wasm-create')} - Create a WASM-sandboxed agent`,
`${output.highlight('wasm-prompt')} - Send a prompt to a WASM agent`,
`${output.highlight('wasm-gallery')} - List WASM agent gallery templates`,
]);
output.writeln();
output.writeln('Run "claude-flow agent <subcommand> --help" for subcommand help');
return { success: true };
}
};
// Helper functions
function getAgentCapabilities(type) {
const capabilities = {
coder: ['code-generation', 'refactoring', 'debugging', 'testing'],
researcher: ['web-search', 'data-analysis', 'summarization', 'citation'],
tester: ['unit-testing', 'integration-testing', 'coverage-analysis', 'automation'],
reviewer: ['code-review', 'security-audit', 'quality-check', 'documentation'],
architect: ['system-design', 'pattern-analysis', 'scalability', 'documentation'],
coordinator: ['task-orchestration', 'agent-management', 'workflow-control'],
'security-architect': ['threat-modeling', 'security-patterns', 'compliance', 'audit'],
'memory-specialist': ['vector-search', 'agentdb', 'caching', 'optimization'],
'performance-engineer': ['benchmarking', 'profiling', 'optimization', 'monitoring']
};
return capabilities[type] || ['general'];
}
function formatStatus(status) {
const statusStr = String(status);
switch (statusStr) {
case 'active':
return output.success(statusStr);
case 'idle':
return output.warning(statusStr);
case 'inactive':
case 'stopped':
return output.dim(statusStr);
case 'error':
return output.error(statusStr);
default:
return statusStr;
}
}
export default agentCommand;
//# sourceMappingURL=agent.js.map