claude-flow 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +612 -0
- package/bin/claude-flow +0 -0
- package/bin/claude-flow-simple +0 -0
- package/bin/claude-flow-typecheck +0 -0
- package/deno.json +84 -0
- package/package.json +45 -0
- package/scripts/check-links.ts +274 -0
- package/scripts/check-performance-regression.ts +168 -0
- package/scripts/claude-sparc.sh +562 -0
- package/scripts/coverage-report.ts +692 -0
- package/scripts/demo-task-system.ts +224 -0
- package/scripts/install.js +72 -0
- package/scripts/test-batch-tasks.ts +29 -0
- package/scripts/test-coordination-features.ts +238 -0
- package/scripts/test-mcp.ts +251 -0
- package/scripts/test-runner.ts +571 -0
- package/scripts/validate-examples.ts +288 -0
- package/src/cli/cli-core.ts +273 -0
- package/src/cli/commands/agent.ts +83 -0
- package/src/cli/commands/config.ts +442 -0
- package/src/cli/commands/help.ts +765 -0
- package/src/cli/commands/index.ts +963 -0
- package/src/cli/commands/mcp.ts +191 -0
- package/src/cli/commands/memory.ts +74 -0
- package/src/cli/commands/monitor.ts +403 -0
- package/src/cli/commands/session.ts +595 -0
- package/src/cli/commands/start.ts +156 -0
- package/src/cli/commands/status.ts +345 -0
- package/src/cli/commands/task.ts +79 -0
- package/src/cli/commands/workflow.ts +763 -0
- package/src/cli/completion.ts +553 -0
- package/src/cli/formatter.ts +310 -0
- package/src/cli/index.ts +211 -0
- package/src/cli/main.ts +23 -0
- package/src/cli/repl.ts +1050 -0
- package/src/cli/simple-cli.js +211 -0
- package/src/cli/simple-cli.ts +211 -0
- package/src/coordination/README.md +400 -0
- package/src/coordination/advanced-scheduler.ts +487 -0
- package/src/coordination/circuit-breaker.ts +366 -0
- package/src/coordination/conflict-resolution.ts +490 -0
- package/src/coordination/dependency-graph.ts +475 -0
- package/src/coordination/index.ts +63 -0
- package/src/coordination/manager.ts +460 -0
- package/src/coordination/messaging.ts +290 -0
- package/src/coordination/metrics.ts +585 -0
- package/src/coordination/resources.ts +322 -0
- package/src/coordination/scheduler.ts +390 -0
- package/src/coordination/work-stealing.ts +224 -0
- package/src/core/config.ts +627 -0
- package/src/core/event-bus.ts +186 -0
- package/src/core/json-persistence.ts +183 -0
- package/src/core/logger.ts +262 -0
- package/src/core/orchestrator-fixed.ts +312 -0
- package/src/core/orchestrator.ts +1234 -0
- package/src/core/persistence.ts +276 -0
- package/src/mcp/auth.ts +438 -0
- package/src/mcp/claude-flow-tools.ts +1280 -0
- package/src/mcp/load-balancer.ts +510 -0
- package/src/mcp/router.ts +240 -0
- package/src/mcp/server.ts +548 -0
- package/src/mcp/session-manager.ts +418 -0
- package/src/mcp/tools.ts +180 -0
- package/src/mcp/transports/base.ts +21 -0
- package/src/mcp/transports/http.ts +457 -0
- package/src/mcp/transports/stdio.ts +254 -0
- package/src/memory/backends/base.ts +22 -0
- package/src/memory/backends/markdown.ts +283 -0
- package/src/memory/backends/sqlite.ts +329 -0
- package/src/memory/cache.ts +238 -0
- package/src/memory/indexer.ts +238 -0
- package/src/memory/manager.ts +572 -0
- package/src/terminal/adapters/base.ts +29 -0
- package/src/terminal/adapters/native.ts +504 -0
- package/src/terminal/adapters/vscode.ts +340 -0
- package/src/terminal/manager.ts +308 -0
- package/src/terminal/pool.ts +271 -0
- package/src/terminal/session.ts +250 -0
- package/src/terminal/vscode-bridge.ts +242 -0
- package/src/utils/errors.ts +231 -0
- package/src/utils/helpers.ts +476 -0
- package/src/utils/types.ts +493 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP command for Claude-Flow
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from '@cliffy/command';
|
|
6
|
+
import { colors } from '@cliffy/ansi/colors';
|
|
7
|
+
import { logger } from '../../core/logger.ts';
|
|
8
|
+
import { configManager } from '../../core/config.ts';
|
|
9
|
+
import { MCPServer } from '../../mcp/server.ts';
|
|
10
|
+
import { eventBus } from '../../core/event-bus.ts';
|
|
11
|
+
|
|
12
|
+
let mcpServer: MCPServer | null = null;
|
|
13
|
+
|
|
14
|
+
export const mcpCommand = new Command()
|
|
15
|
+
.description('Manage MCP server and tools')
|
|
16
|
+
.action(() => {
|
|
17
|
+
console.log(colors.yellow('Please specify a subcommand:'));
|
|
18
|
+
console.log(' start - Start the MCP server');
|
|
19
|
+
console.log(' stop - Stop the MCP server');
|
|
20
|
+
console.log(' status - Show MCP server status');
|
|
21
|
+
console.log(' tools - List available MCP tools');
|
|
22
|
+
console.log(' config - Show MCP configuration');
|
|
23
|
+
console.log(' restart - Restart the MCP server');
|
|
24
|
+
console.log(' logs - Show MCP server logs');
|
|
25
|
+
})
|
|
26
|
+
.command('start', new Command()
|
|
27
|
+
.description('Start the MCP server')
|
|
28
|
+
.option('-p, --port <port:number>', 'Port for MCP server', { default: 3000 })
|
|
29
|
+
.option('-h, --host <host:string>', 'Host for MCP server', { default: 'localhost' })
|
|
30
|
+
.option('--transport <transport:string>', 'Transport type (stdio, http)', { default: 'stdio' })
|
|
31
|
+
.action(async (options: any) => {
|
|
32
|
+
try {
|
|
33
|
+
const config = await configManager.load();
|
|
34
|
+
|
|
35
|
+
// Override with CLI options
|
|
36
|
+
const mcpConfig = {
|
|
37
|
+
...config.mcp,
|
|
38
|
+
port: options.port,
|
|
39
|
+
host: options.host,
|
|
40
|
+
transport: options.transport,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
mcpServer = new MCPServer(mcpConfig, eventBus, logger);
|
|
44
|
+
await mcpServer.start();
|
|
45
|
+
|
|
46
|
+
console.log(colors.green(`✅ MCP server started on ${options.host}:${options.port}`));
|
|
47
|
+
console.log(colors.cyan(`📡 Server URL: http://${options.host}:${options.port}`));
|
|
48
|
+
console.log(colors.cyan(`🔧 Available tools: Research, Code, Terminal, Memory`));
|
|
49
|
+
console.log(colors.cyan(`📚 API documentation: http://${options.host}:${options.port}/docs`));
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error(colors.red(`❌ Failed to start MCP server: ${(error as Error).message}`));
|
|
52
|
+
Deno.exit(1);
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
)
|
|
56
|
+
.command('stop', new Command()
|
|
57
|
+
.description('Stop the MCP server')
|
|
58
|
+
.action(async () => {
|
|
59
|
+
try {
|
|
60
|
+
if (mcpServer) {
|
|
61
|
+
await mcpServer.stop();
|
|
62
|
+
mcpServer = null;
|
|
63
|
+
console.log(colors.green('✅ MCP server stopped'));
|
|
64
|
+
} else {
|
|
65
|
+
console.log(colors.yellow('⚠️ MCP server is not running'));
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(colors.red(`❌ Failed to stop MCP server: ${(error as Error).message}`));
|
|
69
|
+
Deno.exit(1);
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
)
|
|
73
|
+
.command('status', new Command()
|
|
74
|
+
.description('Show MCP server status')
|
|
75
|
+
.action(async () => {
|
|
76
|
+
try {
|
|
77
|
+
const config = await configManager.load();
|
|
78
|
+
const isRunning = mcpServer !== null;
|
|
79
|
+
|
|
80
|
+
console.log(colors.cyan('MCP Server Status:'));
|
|
81
|
+
console.log(`🌐 Status: ${isRunning ? colors.green('Running') : colors.red('Stopped')}`);
|
|
82
|
+
|
|
83
|
+
if (isRunning) {
|
|
84
|
+
console.log(`📍 Address: ${config.mcp.host}:${config.mcp.port}`);
|
|
85
|
+
console.log(`🔐 Authentication: ${config.mcp.auth ? colors.green('Enabled') : colors.yellow('Disabled')}`);
|
|
86
|
+
console.log(`🔧 Tools: ${colors.green('Available')}`);
|
|
87
|
+
console.log(`📊 Metrics: ${colors.green('Collecting')}`);
|
|
88
|
+
} else {
|
|
89
|
+
console.log(colors.gray('Use "claude-flow mcp start" to start the server'));
|
|
90
|
+
}
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error(colors.red(`❌ Failed to get MCP status: ${(error as Error).message}`));
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
)
|
|
96
|
+
.command('tools', new Command()
|
|
97
|
+
.description('List available MCP tools')
|
|
98
|
+
.action(() => {
|
|
99
|
+
console.log(colors.cyan('Available MCP Tools:'));
|
|
100
|
+
|
|
101
|
+
console.log('\n📊 Research Tools:');
|
|
102
|
+
console.log(' • web_search - Search the web for information');
|
|
103
|
+
console.log(' • web_fetch - Fetch content from URLs');
|
|
104
|
+
console.log(' • knowledge_query - Query knowledge base');
|
|
105
|
+
|
|
106
|
+
console.log('\n💻 Code Tools:');
|
|
107
|
+
console.log(' • code_edit - Edit code files');
|
|
108
|
+
console.log(' • code_search - Search through codebase');
|
|
109
|
+
console.log(' • code_analyze - Analyze code quality');
|
|
110
|
+
|
|
111
|
+
console.log('\n🖥️ Terminal Tools:');
|
|
112
|
+
console.log(' • terminal_execute - Execute shell commands');
|
|
113
|
+
console.log(' • terminal_session - Manage terminal sessions');
|
|
114
|
+
console.log(' • file_operations - File system operations');
|
|
115
|
+
|
|
116
|
+
console.log('\n💾 Memory Tools:');
|
|
117
|
+
console.log(' • memory_store - Store information');
|
|
118
|
+
console.log(' • memory_query - Query stored information');
|
|
119
|
+
console.log(' • memory_index - Index and search content');
|
|
120
|
+
})
|
|
121
|
+
)
|
|
122
|
+
.command('config', new Command()
|
|
123
|
+
.description('Show MCP configuration')
|
|
124
|
+
.action(async () => {
|
|
125
|
+
try {
|
|
126
|
+
const config = await configManager.load();
|
|
127
|
+
|
|
128
|
+
console.log(colors.cyan('MCP Configuration:'));
|
|
129
|
+
console.log(JSON.stringify(config.mcp, null, 2));
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error(colors.red(`❌ Failed to show MCP config: ${(error as Error).message}`));
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
)
|
|
135
|
+
.command('restart', new Command()
|
|
136
|
+
.description('Restart the MCP server')
|
|
137
|
+
.action(async () => {
|
|
138
|
+
try {
|
|
139
|
+
console.log(colors.yellow('🔄 Stopping MCP server...'));
|
|
140
|
+
if (mcpServer) {
|
|
141
|
+
await mcpServer.stop();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.log(colors.yellow('🔄 Starting MCP server...'));
|
|
145
|
+
const config = await configManager.load();
|
|
146
|
+
mcpServer = new MCPServer(config.mcp, eventBus, logger);
|
|
147
|
+
await mcpServer.start();
|
|
148
|
+
|
|
149
|
+
console.log(colors.green(`✅ MCP server restarted on ${config.mcp.host}:${config.mcp.port}`));
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error(colors.red(`❌ Failed to restart MCP server: ${(error as Error).message}`));
|
|
152
|
+
Deno.exit(1);
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
)
|
|
156
|
+
.command('logs', new Command()
|
|
157
|
+
.description('Show MCP server logs')
|
|
158
|
+
.option('-n, --lines <lines:number>', 'Number of log lines to show', { default: 50 })
|
|
159
|
+
.action((options: any) => {
|
|
160
|
+
console.log(colors.cyan(`MCP Server Logs (last ${options.lines} lines):`));
|
|
161
|
+
|
|
162
|
+
// Mock logs since logging system might not be fully implemented
|
|
163
|
+
const logEntries = [
|
|
164
|
+
'2024-01-10 10:00:00 [INFO] MCP server started on localhost:3000',
|
|
165
|
+
'2024-01-10 10:00:01 [INFO] Tools registered: 12',
|
|
166
|
+
'2024-01-10 10:00:02 [INFO] Authentication disabled',
|
|
167
|
+
'2024-01-10 10:01:00 [INFO] Client connected: claude-desktop',
|
|
168
|
+
'2024-01-10 10:01:05 [INFO] Tool called: web_search',
|
|
169
|
+
'2024-01-10 10:01:10 [INFO] Tool response sent successfully',
|
|
170
|
+
'2024-01-10 10:02:00 [INFO] Tool called: terminal_execute',
|
|
171
|
+
'2024-01-10 10:02:05 [INFO] Command executed successfully',
|
|
172
|
+
'2024-01-10 10:03:00 [INFO] Memory operation: store',
|
|
173
|
+
'2024-01-10 10:03:01 [INFO] Data stored in namespace: default',
|
|
174
|
+
];
|
|
175
|
+
|
|
176
|
+
const startIndex = Math.max(0, logEntries.length - options.lines);
|
|
177
|
+
const displayLogs = logEntries.slice(startIndex);
|
|
178
|
+
|
|
179
|
+
for (const entry of displayLogs) {
|
|
180
|
+
if (entry.includes('[ERROR]')) {
|
|
181
|
+
console.log(colors.red(entry));
|
|
182
|
+
} else if (entry.includes('[WARN]')) {
|
|
183
|
+
console.log(colors.yellow(entry));
|
|
184
|
+
} else if (entry.includes('[INFO]')) {
|
|
185
|
+
console.log(colors.green(entry));
|
|
186
|
+
} else {
|
|
187
|
+
console.log(colors.gray(entry));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory management commands
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from '@cliffy/command';
|
|
6
|
+
import { colors } from '@cliffy/ansi/colors';
|
|
7
|
+
import { Table } from '@cliffy/table';
|
|
8
|
+
|
|
9
|
+
export const memoryCommand = new Command()
|
|
10
|
+
.description('Manage agent memory')
|
|
11
|
+
.action(() => {
|
|
12
|
+
memoryCommand.showHelp();
|
|
13
|
+
})
|
|
14
|
+
.command('query', new Command()
|
|
15
|
+
.description('Query memory entries')
|
|
16
|
+
.option('-a, --agent <agent:string>', 'Filter by agent ID')
|
|
17
|
+
.option('-s, --session <session:string>', 'Filter by session ID')
|
|
18
|
+
.option('-t, --type <type:string>', 'Filter by entry type')
|
|
19
|
+
.option('--tags <tags:string>', 'Filter by tags (comma-separated)')
|
|
20
|
+
.option('--search <search:string>', 'Search in content')
|
|
21
|
+
.option('--limit <limit:number>', 'Limit results', { default: 10 })
|
|
22
|
+
.action(async (options: any) => {
|
|
23
|
+
console.log(colors.yellow('Memory query requires a running Claude-Flow instance'));
|
|
24
|
+
console.log(colors.gray('Query parameters:'));
|
|
25
|
+
console.log(JSON.stringify(options, null, 2));
|
|
26
|
+
}),
|
|
27
|
+
)
|
|
28
|
+
.command('export', new Command()
|
|
29
|
+
.description('Export memory to file')
|
|
30
|
+
.arguments('<output-file:string>')
|
|
31
|
+
.option('-a, --agent <agent:string>', 'Export specific agent memory')
|
|
32
|
+
.option('-f, --format <format:string>', 'Export format (json, markdown)', {
|
|
33
|
+
default: 'json',
|
|
34
|
+
})
|
|
35
|
+
.action(async (options: any, outputFile: string) => {
|
|
36
|
+
console.log(colors.yellow('Memory export requires a running Claude-Flow instance'));
|
|
37
|
+
}),
|
|
38
|
+
)
|
|
39
|
+
.command('import', new Command()
|
|
40
|
+
.description('Import memory from file')
|
|
41
|
+
.arguments('<input-file:string>')
|
|
42
|
+
.option('-a, --agent <agent:string>', 'Import to specific agent')
|
|
43
|
+
.action(async (options: any, inputFile: string) => {
|
|
44
|
+
try {
|
|
45
|
+
const content = await Deno.readTextFile(inputFile);
|
|
46
|
+
const data = JSON.parse(content);
|
|
47
|
+
|
|
48
|
+
console.log(colors.green('Memory data loaded:'));
|
|
49
|
+
console.log(`- Entries: ${Array.isArray(data) ? data.length : 1}`);
|
|
50
|
+
console.log(colors.yellow('\nTo import this data, ensure Claude-Flow is running'));
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error(colors.red('Failed to load memory file:'), (error as Error).message);
|
|
53
|
+
}
|
|
54
|
+
}),
|
|
55
|
+
)
|
|
56
|
+
.command('stats', new Command()
|
|
57
|
+
.description('Show memory statistics')
|
|
58
|
+
.action(async () => {
|
|
59
|
+
console.log(colors.yellow('Memory statistics require a running Claude-Flow instance'));
|
|
60
|
+
}),
|
|
61
|
+
)
|
|
62
|
+
.command('cleanup', new Command()
|
|
63
|
+
.description('Clean up old memory entries')
|
|
64
|
+
.option('--older-than <days:number>', 'Delete entries older than N days', {
|
|
65
|
+
default: 30,
|
|
66
|
+
})
|
|
67
|
+
.option('--dry-run', 'Show what would be deleted without deleting')
|
|
68
|
+
.action(async (options: any) => {
|
|
69
|
+
console.log(colors.yellow('Memory cleanup requires a running Claude-Flow instance'));
|
|
70
|
+
if (options.dryRun) {
|
|
71
|
+
console.log(colors.gray('(Dry run mode - no changes would be made)'));
|
|
72
|
+
}
|
|
73
|
+
}),
|
|
74
|
+
);
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monitor command for Claude-Flow - Live dashboard mode
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from '@cliffy/command';
|
|
6
|
+
import { colors } from '@cliffy/ansi/colors';
|
|
7
|
+
import { Table } from '@cliffy/table';
|
|
8
|
+
import { formatProgressBar, formatDuration, formatStatusIndicator } from '../formatter.ts';
|
|
9
|
+
|
|
10
|
+
export const monitorCommand = new Command()
|
|
11
|
+
.description('Start live monitoring dashboard')
|
|
12
|
+
.option('-i, --interval <seconds:number>', 'Update interval in seconds', { default: 2 })
|
|
13
|
+
.option('-c, --compact', 'Compact view mode')
|
|
14
|
+
.option('--no-graphs', 'Disable ASCII graphs')
|
|
15
|
+
.option('--focus <component:string>', 'Focus on specific component')
|
|
16
|
+
.action(async (options: any) => {
|
|
17
|
+
await startMonitorDashboard(options);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
interface MonitorData {
|
|
21
|
+
timestamp: Date;
|
|
22
|
+
system: {
|
|
23
|
+
cpu: number;
|
|
24
|
+
memory: number;
|
|
25
|
+
agents: number;
|
|
26
|
+
tasks: number;
|
|
27
|
+
};
|
|
28
|
+
components: Record<string, any>;
|
|
29
|
+
agents: any[];
|
|
30
|
+
tasks: any[];
|
|
31
|
+
events: any[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
class Dashboard {
|
|
35
|
+
private data: MonitorData[] = [];
|
|
36
|
+
private maxDataPoints = 60; // 2 minutes at 2-second intervals
|
|
37
|
+
private running = true;
|
|
38
|
+
|
|
39
|
+
constructor(private options: any) {}
|
|
40
|
+
|
|
41
|
+
async start(): Promise<void> {
|
|
42
|
+
// Hide cursor and clear screen
|
|
43
|
+
Deno.stdout.writeSync(new TextEncoder().encode('\x1b[?25l'));
|
|
44
|
+
console.clear();
|
|
45
|
+
|
|
46
|
+
// Setup signal handlers
|
|
47
|
+
const cleanup = () => {
|
|
48
|
+
this.running = false;
|
|
49
|
+
Deno.stdout.writeSync(new TextEncoder().encode('\x1b[?25h')); // Show cursor
|
|
50
|
+
console.log('\n' + colors.gray('Monitor stopped'));
|
|
51
|
+
Deno.exit(0);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
Deno.addSignalListener('SIGINT', cleanup);
|
|
55
|
+
Deno.addSignalListener('SIGTERM', cleanup);
|
|
56
|
+
|
|
57
|
+
// Start monitoring loop
|
|
58
|
+
await this.monitoringLoop();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private async monitoringLoop(): Promise<void> {
|
|
62
|
+
while (this.running) {
|
|
63
|
+
try {
|
|
64
|
+
const data = await this.collectData();
|
|
65
|
+
this.data.push(data);
|
|
66
|
+
|
|
67
|
+
// Keep only recent data points
|
|
68
|
+
if (this.data.length > this.maxDataPoints) {
|
|
69
|
+
this.data = this.data.slice(-this.maxDataPoints);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
this.render();
|
|
73
|
+
await new Promise(resolve => setTimeout(resolve, this.options.interval * 1000));
|
|
74
|
+
} catch (error) {
|
|
75
|
+
this.renderError(error);
|
|
76
|
+
await new Promise(resolve => setTimeout(resolve, this.options.interval * 1000));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private async collectData(): Promise<MonitorData> {
|
|
82
|
+
// Mock data collection - in production, this would connect to the orchestrator
|
|
83
|
+
const timestamp = new Date();
|
|
84
|
+
const cpuUsage = 10 + Math.random() * 20; // 10-30%
|
|
85
|
+
const memoryUsage = 200 + Math.random() * 100; // 200-300MB
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
timestamp,
|
|
89
|
+
system: {
|
|
90
|
+
cpu: cpuUsage,
|
|
91
|
+
memory: memoryUsage,
|
|
92
|
+
agents: 3 + Math.floor(Math.random() * 3),
|
|
93
|
+
tasks: 5 + Math.floor(Math.random() * 10)
|
|
94
|
+
},
|
|
95
|
+
components: {
|
|
96
|
+
orchestrator: { status: 'healthy', load: Math.random() * 100 },
|
|
97
|
+
terminal: { status: 'healthy', load: Math.random() * 100 },
|
|
98
|
+
memory: { status: 'healthy', load: Math.random() * 100 },
|
|
99
|
+
coordination: { status: 'healthy', load: Math.random() * 100 },
|
|
100
|
+
mcp: { status: 'healthy', load: Math.random() * 100 }
|
|
101
|
+
},
|
|
102
|
+
agents: this.generateMockAgents(),
|
|
103
|
+
tasks: this.generateMockTasks(),
|
|
104
|
+
events: this.generateMockEvents()
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private render(): void {
|
|
109
|
+
console.clear();
|
|
110
|
+
|
|
111
|
+
const latest = this.data[this.data.length - 1];
|
|
112
|
+
if (!latest) return;
|
|
113
|
+
|
|
114
|
+
// Header
|
|
115
|
+
this.renderHeader(latest);
|
|
116
|
+
|
|
117
|
+
if (this.options.focus) {
|
|
118
|
+
this.renderFocusedComponent(latest, this.options.focus);
|
|
119
|
+
} else {
|
|
120
|
+
// System overview
|
|
121
|
+
this.renderSystemOverview(latest);
|
|
122
|
+
|
|
123
|
+
// Components status
|
|
124
|
+
this.renderComponentsStatus(latest);
|
|
125
|
+
|
|
126
|
+
if (!this.options.compact) {
|
|
127
|
+
// Agents and tasks
|
|
128
|
+
this.renderAgentsAndTasks(latest);
|
|
129
|
+
|
|
130
|
+
// Recent events
|
|
131
|
+
this.renderRecentEvents(latest);
|
|
132
|
+
|
|
133
|
+
// Performance graphs
|
|
134
|
+
if (!this.options.noGraphs) {
|
|
135
|
+
this.renderPerformanceGraphs();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Footer
|
|
141
|
+
this.renderFooter();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private renderHeader(data: MonitorData): void {
|
|
145
|
+
const time = data.timestamp.toLocaleTimeString();
|
|
146
|
+
console.log(colors.cyan.bold('Claude-Flow Live Monitor') + colors.gray(` - ${time}`));
|
|
147
|
+
console.log('═'.repeat(80));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private renderSystemOverview(data: MonitorData): void {
|
|
151
|
+
console.log(colors.white.bold('System Overview'));
|
|
152
|
+
console.log('─'.repeat(40));
|
|
153
|
+
|
|
154
|
+
const cpuBar = formatProgressBar(data.system.cpu, 100, 20, 'CPU');
|
|
155
|
+
const memoryBar = formatProgressBar(data.system.memory, 1024, 20, 'Memory');
|
|
156
|
+
|
|
157
|
+
console.log(`${cpuBar} ${data.system.cpu.toFixed(1)}%`);
|
|
158
|
+
console.log(`${memoryBar} ${data.system.memory.toFixed(0)}MB`);
|
|
159
|
+
console.log(`${colors.white('Agents:')} ${data.system.agents} active`);
|
|
160
|
+
console.log(`${colors.white('Tasks:')} ${data.system.tasks} in queue`);
|
|
161
|
+
console.log();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private renderComponentsStatus(data: MonitorData): void {
|
|
165
|
+
console.log(colors.white.bold('Components'));
|
|
166
|
+
console.log('─'.repeat(40));
|
|
167
|
+
|
|
168
|
+
const table = new Table()
|
|
169
|
+
.header(['Component', 'Status', 'Load'])
|
|
170
|
+
.border(false);
|
|
171
|
+
|
|
172
|
+
for (const [name, component] of Object.entries(data.components)) {
|
|
173
|
+
const statusIcon = formatStatusIndicator(component.status);
|
|
174
|
+
const loadBar = this.createMiniProgressBar(component.load, 100, 10);
|
|
175
|
+
|
|
176
|
+
table.push([
|
|
177
|
+
colors.cyan(name),
|
|
178
|
+
`${statusIcon} ${component.status}`,
|
|
179
|
+
`${loadBar} ${component.load.toFixed(0)}%`
|
|
180
|
+
]);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
table.render();
|
|
184
|
+
console.log();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private renderAgentsAndTasks(data: MonitorData): void {
|
|
188
|
+
// Agents table
|
|
189
|
+
console.log(colors.white.bold('Active Agents'));
|
|
190
|
+
console.log('─'.repeat(40));
|
|
191
|
+
|
|
192
|
+
if (data.agents.length > 0) {
|
|
193
|
+
const agentTable = new Table()
|
|
194
|
+
.header(['ID', 'Type', 'Status', 'Tasks'])
|
|
195
|
+
.border(false);
|
|
196
|
+
|
|
197
|
+
for (const agent of data.agents.slice(0, 5)) {
|
|
198
|
+
const statusIcon = formatStatusIndicator(agent.status);
|
|
199
|
+
|
|
200
|
+
agentTable.push([
|
|
201
|
+
colors.gray(agent.id.substring(0, 8) + '...'),
|
|
202
|
+
colors.cyan(agent.type),
|
|
203
|
+
`${statusIcon} ${agent.status}`,
|
|
204
|
+
agent.activeTasks.toString()
|
|
205
|
+
]);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
agentTable.render();
|
|
209
|
+
} else {
|
|
210
|
+
console.log(colors.gray('No active agents'));
|
|
211
|
+
}
|
|
212
|
+
console.log();
|
|
213
|
+
|
|
214
|
+
// Recent tasks
|
|
215
|
+
console.log(colors.white.bold('Recent Tasks'));
|
|
216
|
+
console.log('─'.repeat(40));
|
|
217
|
+
|
|
218
|
+
if (data.tasks.length > 0) {
|
|
219
|
+
const taskTable = new Table()
|
|
220
|
+
.header(['ID', 'Type', 'Status', 'Duration'])
|
|
221
|
+
.border(false);
|
|
222
|
+
|
|
223
|
+
for (const task of data.tasks.slice(0, 5)) {
|
|
224
|
+
const statusIcon = formatStatusIndicator(task.status);
|
|
225
|
+
|
|
226
|
+
taskTable.push([
|
|
227
|
+
colors.gray(task.id.substring(0, 8) + '...'),
|
|
228
|
+
colors.white(task.type),
|
|
229
|
+
`${statusIcon} ${task.status}`,
|
|
230
|
+
task.duration ? formatDuration(task.duration) : '-'
|
|
231
|
+
]);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
taskTable.render();
|
|
235
|
+
} else {
|
|
236
|
+
console.log(colors.gray('No recent tasks'));
|
|
237
|
+
}
|
|
238
|
+
console.log();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
private renderRecentEvents(data: MonitorData): void {
|
|
242
|
+
console.log(colors.white.bold('Recent Events'));
|
|
243
|
+
console.log('─'.repeat(40));
|
|
244
|
+
|
|
245
|
+
if (data.events.length > 0) {
|
|
246
|
+
for (const event of data.events.slice(0, 3)) {
|
|
247
|
+
const time = new Date(event.timestamp).toLocaleTimeString();
|
|
248
|
+
const icon = this.getEventIcon(event.type);
|
|
249
|
+
console.log(`${colors.gray(time)} ${icon} ${event.message}`);
|
|
250
|
+
}
|
|
251
|
+
} else {
|
|
252
|
+
console.log(colors.gray('No recent events'));
|
|
253
|
+
}
|
|
254
|
+
console.log();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private renderPerformanceGraphs(): void {
|
|
258
|
+
console.log(colors.white.bold('Performance (Last 60s)'));
|
|
259
|
+
console.log('─'.repeat(40));
|
|
260
|
+
|
|
261
|
+
if (this.data.length >= 2) {
|
|
262
|
+
// CPU graph
|
|
263
|
+
console.log(colors.cyan('CPU Usage:'));
|
|
264
|
+
console.log(this.createSparkline(this.data.map(d => d.system.cpu), 30));
|
|
265
|
+
|
|
266
|
+
// Memory graph
|
|
267
|
+
console.log(colors.cyan('Memory Usage:'));
|
|
268
|
+
console.log(this.createSparkline(this.data.map(d => d.system.memory), 30));
|
|
269
|
+
} else {
|
|
270
|
+
console.log(colors.gray('Collecting data...'));
|
|
271
|
+
}
|
|
272
|
+
console.log();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
private renderFocusedComponent(data: MonitorData, componentName: string): void {
|
|
276
|
+
const component = data.components[componentName];
|
|
277
|
+
if (!component) {
|
|
278
|
+
console.log(colors.red(`Component '${componentName}' not found`));
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
console.log(colors.white.bold(`${componentName} Details`));
|
|
283
|
+
console.log('─'.repeat(40));
|
|
284
|
+
|
|
285
|
+
const statusIcon = formatStatusIndicator(component.status);
|
|
286
|
+
console.log(`${statusIcon} Status: ${component.status}`);
|
|
287
|
+
console.log(`Load: ${formatProgressBar(component.load, 100, 30)} ${component.load.toFixed(1)}%`);
|
|
288
|
+
|
|
289
|
+
// Add component-specific metrics here
|
|
290
|
+
console.log();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private renderFooter(): void {
|
|
294
|
+
console.log('─'.repeat(80));
|
|
295
|
+
console.log(colors.gray('Press Ctrl+C to exit • Update interval: ') +
|
|
296
|
+
colors.yellow(`${this.options.interval}s`));
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private renderError(error: any): void {
|
|
300
|
+
console.clear();
|
|
301
|
+
console.log(colors.red.bold('Monitor Error'));
|
|
302
|
+
console.log('─'.repeat(40));
|
|
303
|
+
|
|
304
|
+
if ((error as Error).message.includes('ECONNREFUSED')) {
|
|
305
|
+
console.log(colors.red('✗ Cannot connect to Claude-Flow'));
|
|
306
|
+
console.log(colors.gray('Make sure Claude-Flow is running with: claude-flow start'));
|
|
307
|
+
} else {
|
|
308
|
+
console.log(colors.red('Error:'), (error as Error).message);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
console.log('\n' + colors.gray('Retrying in ') + colors.yellow(`${this.options.interval}s...`));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private createMiniProgressBar(current: number, max: number, width: number): string {
|
|
315
|
+
const filled = Math.floor((current / max) * width);
|
|
316
|
+
const empty = width - filled;
|
|
317
|
+
return colors.green('█'.repeat(filled)) + colors.gray('░'.repeat(empty));
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private createSparkline(data: number[], width: number): string {
|
|
321
|
+
if (data.length < 2) return colors.gray('▁'.repeat(width));
|
|
322
|
+
|
|
323
|
+
const max = Math.max(...data);
|
|
324
|
+
const min = Math.min(...data);
|
|
325
|
+
const range = max - min || 1;
|
|
326
|
+
|
|
327
|
+
const chars = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];
|
|
328
|
+
const recent = data.slice(-width);
|
|
329
|
+
|
|
330
|
+
return recent.map(value => {
|
|
331
|
+
const normalized = (value - min) / range;
|
|
332
|
+
const charIndex = Math.floor(normalized * (chars.length - 1));
|
|
333
|
+
return colors.cyan(chars[charIndex]);
|
|
334
|
+
}).join('');
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
private getEventIcon(type: string): string {
|
|
338
|
+
const icons = {
|
|
339
|
+
agent_spawned: colors.green('↗'),
|
|
340
|
+
agent_terminated: colors.red('↙'),
|
|
341
|
+
task_completed: colors.green('✓'),
|
|
342
|
+
task_failed: colors.red('✗'),
|
|
343
|
+
task_assigned: colors.blue('→'),
|
|
344
|
+
system_warning: colors.yellow('⚠'),
|
|
345
|
+
system_error: colors.red('✗'),
|
|
346
|
+
};
|
|
347
|
+
return icons[type as keyof typeof icons] || colors.blue('•');
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
private generateMockAgents(): any[] {
|
|
351
|
+
return [
|
|
352
|
+
{
|
|
353
|
+
id: 'agent-001',
|
|
354
|
+
type: 'coordinator',
|
|
355
|
+
status: 'active',
|
|
356
|
+
activeTasks: Math.floor(Math.random() * 5) + 1
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
id: 'agent-002',
|
|
360
|
+
type: 'researcher',
|
|
361
|
+
status: 'active',
|
|
362
|
+
activeTasks: Math.floor(Math.random() * 8) + 1
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
id: 'agent-003',
|
|
366
|
+
type: 'implementer',
|
|
367
|
+
status: Math.random() > 0.7 ? 'idle' : 'active',
|
|
368
|
+
activeTasks: Math.floor(Math.random() * 3)
|
|
369
|
+
}
|
|
370
|
+
];
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
private generateMockTasks(): any[] {
|
|
374
|
+
const types = ['research', 'implementation', 'analysis', 'coordination'];
|
|
375
|
+
const statuses = ['running', 'pending', 'completed', 'failed'];
|
|
376
|
+
|
|
377
|
+
return Array.from({ length: 8 }, (_, i) => ({
|
|
378
|
+
id: `task-${String(i + 1).padStart(3, '0')}`,
|
|
379
|
+
type: types[Math.floor(Math.random() * types.length)],
|
|
380
|
+
status: statuses[Math.floor(Math.random() * statuses.length)],
|
|
381
|
+
duration: Math.random() > 0.5 ? Math.floor(Math.random() * 120000) : null
|
|
382
|
+
}));
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
private generateMockEvents(): any[] {
|
|
386
|
+
const events = [
|
|
387
|
+
{ type: 'task_completed', message: 'Research task completed successfully' },
|
|
388
|
+
{ type: 'agent_spawned', message: 'New implementer agent spawned' },
|
|
389
|
+
{ type: 'task_assigned', message: 'Task assigned to coordinator agent' },
|
|
390
|
+
{ type: 'system_warning', message: 'High memory usage detected' }
|
|
391
|
+
];
|
|
392
|
+
|
|
393
|
+
return events.map((event, i) => ({
|
|
394
|
+
...event,
|
|
395
|
+
timestamp: Date.now() - (i * 30000) // 30 seconds apart
|
|
396
|
+
}));
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
async function startMonitorDashboard(options: any): Promise<void> {
|
|
401
|
+
const dashboard = new Dashboard(options);
|
|
402
|
+
await dashboard.start();
|
|
403
|
+
}
|