claude-flow-multilang
Version:
Revolutionary multilingual AI orchestration framework with cultural awareness and DDD architecture
275 lines (231 loc) • 7.55 kB
JavaScript
// process-ui.js - Simple process management UI in pure JavaScript
import { printSuccess, printError, printWarning, printInfo } from '../utils.js';
import { cwd, exit, existsSync } from '../node-compat.js';
import process from 'process';
// Simple color utilities
const colors = {
cyan: (text) => `\x1b[36m${text}\x1b[0m`,
gray: (text) => `\x1b[90m${text}\x1b[0m`,
white: (text) => `\x1b[37m${text}\x1b[0m`,
yellow: (text) => `\x1b[33m${text}\x1b[0m`,
green: (text) => `\x1b[32m${text}\x1b[0m`,
red: (text) => `\x1b[31m${text}\x1b[0m`,
};
const PROCESSES = [
{ id: 'event-bus', name: 'Event Bus', description: 'Central event distribution system' },
{ id: 'orchestrator', name: 'Orchestrator', description: 'Main coordination engine' },
{ id: 'memory-manager', name: 'Memory Manager', description: 'Persistent memory system' },
{ id: 'terminal-pool', name: 'Terminal Pool', description: 'Terminal session management' },
{ id: 'mcp-server', name: 'MCP Server', description: 'Model Context Protocol server' },
{ id: 'coordinator', name: 'Coordinator', description: 'Task coordination service' },
];
export class ProcessUI {
constructor() {
this.processes = new Map();
this.running = true;
this.selectedIndex = 0;
// Initialize process states
PROCESSES.forEach((p) => {
this.processes.set(p.id, {
...p,
status: 'stopped',
pid: null,
uptime: 0,
cpu: 0,
memory: 0,
});
});
}
async start() {
// Clear screen
console.clear();
// Show welcome
printSuccess('🧠 Claude-Flow Process Management UI v1.0.43');
console.log('─'.repeat(60));
console.log();
// Initial render
this.render();
// Main UI loop
while (this.running) {
await this.handleInput();
if (this.running) {
// Only re-render if still running
this.render();
}
}
}
render() {
// Clear screen and move cursor to top
console.log('\x1b[2J\x1b[H');
// Header
console.log(colors.cyan('🧠 Claude-Flow Process Manager'));
console.log(colors.gray('─'.repeat(60)));
console.log();
// Process list
console.log(colors.white('Processes:'));
console.log();
let index = 0;
for (const [id, process] of this.processes) {
const selected = index === this.selectedIndex;
const prefix = selected ? colors.yellow('▶ ') : ' ';
const status = this.getStatusIcon(process.status);
const name = selected ? colors.yellow(process.name) : colors.white(process.name);
console.log(`${prefix}[${index + 1}] ${status} ${name}`);
console.log(` ${colors.gray(process.description)}`);
if (process.status === 'running') {
console.log(
` ${colors.gray(`PID: ${process.pid} | Uptime: ${this.formatUptime(process.uptime)}`)}`,
);
}
console.log();
index++;
}
// Controls
console.log(colors.gray('─'.repeat(60)));
console.log(colors.white('Controls:'));
console.log(
` ${colors.yellow('1-6')} Select process ${colors.yellow('Space/Enter')} Toggle selected`,
);
console.log(` ${colors.yellow('A')} Start all ${colors.yellow('Z')} Stop all`);
console.log(` ${colors.yellow('R')} Restart all ${colors.yellow('Q')} Quit`);
console.log();
console.log(colors.gray('─'.repeat(60)));
}
getStatusIcon(status) {
switch (status) {
case 'running':
return colors.green('●');
case 'stopped':
return colors.gray('○');
case 'error':
return colors.red('✗');
case 'starting':
return colors.yellow('◐');
default:
return colors.gray('?');
}
}
formatUptime(seconds) {
if (seconds < 60) return `${seconds}s`;
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
return `${Math.floor(seconds / 3600)}h`;
}
async handleInput() {
// Simple input reading
const decoder = new TextDecoder();
const encoder = new TextEncoder();
await Deno.stdout.write(encoder.encode('\nCommand: '));
const buf = new Uint8Array(1024);
const n = await Deno.stdin.read(buf);
if (n === null) return;
const rawInput = decoder.decode(buf.subarray(0, n)).trim();
// Take only the first line if multiple lines were read
const input = rawInput.split('\n')[0].toLowerCase();
// Handle commands
switch (input) {
case 'q':
case 'quit':
this.running = false;
console.clear();
printSuccess('Goodbye!');
process.exit(0); // Exit immediately
break;
case 'a':
await this.startAll();
break;
case 'z':
await this.stopAll();
break;
case 'r':
await this.restartAll();
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
const index = parseInt(input) - 1;
if (index >= 0 && index < PROCESSES.length) {
this.selectedIndex = index;
await this.toggleSelected();
}
break;
case ' ':
case 'enter':
case '':
await this.toggleSelected();
break;
default:
if (input) {
console.log(colors.yellow(`Unknown command: ${input}`));
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
}
async toggleSelected() {
const process = Array.from(this.processes.values())[this.selectedIndex];
if (process.status === 'stopped') {
await this.startProcess(process.id);
} else {
await this.stopProcess(process.id);
}
}
async startProcess(id) {
const process = this.processes.get(id);
if (!process) return;
console.log(colors.yellow(`Starting ${process.name}...`));
process.status = 'starting';
// Simulate startup
await new Promise((resolve) => setTimeout(resolve, 500));
process.status = 'running';
process.pid = Math.floor(Math.random() * 10000) + 1000;
process.uptime = 0;
console.log(colors.green(`✓ ${process.name} started`));
// Start uptime counter
const interval = setInterval(() => {
if (process.status === 'running') {
process.uptime++;
} else {
clearInterval(interval);
}
}, 1000);
}
async stopProcess(id) {
const process = this.processes.get(id);
if (!process) return;
console.log(colors.yellow(`Stopping ${process.name}...`));
process.status = 'stopped';
process.pid = null;
process.uptime = 0;
await new Promise((resolve) => setTimeout(resolve, 300));
console.log(colors.green(`✓ ${process.name} stopped`));
}
async startAll() {
console.log(colors.yellow('Starting all processes...'));
for (const [id, process] of this.processes) {
if (process.status === 'stopped') {
await this.startProcess(id);
}
}
console.log(colors.green('✓ All processes started'));
}
async stopAll() {
console.log(colors.yellow('Stopping all processes...'));
for (const [id, process] of this.processes) {
if (process.status === 'running') {
await this.stopProcess(id);
}
}
console.log(colors.green('✓ All processes stopped'));
}
async restartAll() {
await this.stopAll();
await new Promise((resolve) => setTimeout(resolve, 500));
await this.startAll();
}
}
export async function launchProcessUI() {
const ui = new ProcessUI();
await ui.start();
}