UNPKG

automagik-genie

Version:

Self-evolving AI agent orchestration framework with Model Context Protocol support

153 lines (152 loc) 4.56 kB
"use strict"; /** * CLI Utility Functions * Helper functions for CLI operations */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.execGenie = execGenie; exports.checkPortConflict = checkPortConflict; exports.formatUptime = formatUptime; exports.isWSL = isWSL; exports.getBrowserOpenCommand = getBrowserOpenCommand; exports.isProcessAlive = isProcessAlive; exports.killProcess = killProcess; const fs_1 = __importDefault(require("fs")); const child_process_1 = require("child_process"); const path_1 = __importDefault(require("path")); /** * Execute the legacy genie CLI */ function execGenie(args) { const genieScript = path_1.default.join(__dirname, '../genie.js'); const child = (0, child_process_1.spawn)('node', [genieScript, ...args], { stdio: 'inherit', env: process.env }); child.on('exit', (code) => { process.exit(code || 0); }); } /** * Check if a port is in use and return process info */ async function checkPortConflict(port) { const { execFile } = require('child_process'); const { promisify } = require('util'); const execFileAsync = promisify(execFile); try { const { stdout } = await execFileAsync('lsof', ['-i', `:${port}`, '-t', '-sTCP:LISTEN']); const pid = stdout.trim().split('\n')[0]; if (pid) { try { const { stdout: psOut } = await execFileAsync('ps', ['-p', pid, '-o', 'command=']); return { pid, command: psOut.trim() }; } catch { return { pid, command: 'unknown' }; } } } catch { // No process on port return null; } return null; } /** * Format uptime in human-readable format */ function formatUptime(ms) { const seconds = Math.floor(ms / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`; if (hours > 0) return `${hours}h ${minutes % 60}m ${seconds % 60}s`; if (minutes > 0) return `${minutes}m ${seconds % 60}s`; return `${seconds}s`; } /** * Detect if running in WSL (Windows Subsystem for Linux) */ function isWSL() { try { // Check environment variables (most reliable) if (process.env.WSL_DISTRO_NAME || process.env.WSLENV) { return true; } // Check /proc/version for "microsoft" or "WSL" if (fs_1.default.existsSync('/proc/version')) { const version = fs_1.default.readFileSync('/proc/version', 'utf8').toLowerCase(); if (version.includes('microsoft') || version.includes('wsl')) { return true; } } } catch { // Ignore errors } return false; } /** * Get the appropriate browser open command for the current OS * Handles WSL by using Windows commands instead of Linux */ function getBrowserOpenCommand() { const platform = process.platform; // WSL: Use Windows command if (platform === 'linux' && isWSL()) { return 'cmd.exe /c start'; } // Regular OS detection if (platform === 'darwin') return 'open'; if (platform === 'win32') return 'start'; return 'xdg-open'; // Linux (non-WSL) } /** * Check if a process is alive by PID */ function isProcessAlive(pid) { try { // Send signal 0 (no-op) to check if process exists process.kill(pid, 0); return true; } catch { return false; } } /** * Kill a process gracefully (SIGTERM first, then SIGKILL if needed) */ async function killProcess(pid, timeout = 5000) { if (!isProcessAlive(pid)) { return true; // Already dead } try { // Try SIGTERM first (graceful) process.kill(pid, 'SIGTERM'); // Wait for process to exit const start = Date.now(); while (isProcessAlive(pid) && Date.now() - start < timeout) { await new Promise(resolve => setTimeout(resolve, 100)); } // If still alive, force kill with SIGKILL if (isProcessAlive(pid)) { process.kill(pid, 'SIGKILL'); await new Promise(resolve => setTimeout(resolve, 500)); } return !isProcessAlive(pid); } catch (error) { return false; } }