UNPKG

claude-code-subagents-orchestrator

Version:

Claude Code Sub-agents Orchestrator - A powerful MCP server for orchestrating multiple AI sub-agents for complex task execution in Claude Code

232 lines (202 loc) 6.39 kB
#!/usr/bin/env node /** * Universal Launcher for Claude Code Subagents Orchestrator * * This script handles all installation scenarios: * - Global npm installation * - Local npm installation * - Development environment * - Direct execution * * It automatically detects the correct entry point and execution method. */ import { fileURLToPath } from 'url'; import { dirname, join, resolve } from 'path'; import { spawn } from 'child_process'; import { existsSync, readFileSync } from 'fs'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); /** * Find the project root by looking for package.json */ function findProjectRoot(startPath) { let currentPath = startPath; while (currentPath !== '/') { if (existsSync(join(currentPath, 'package.json'))) { return currentPath; } currentPath = dirname(currentPath); } return null; } /** * Detect if running in development mode */ function isDevMode() { // Check if we're in a development environment const projectRoot = findProjectRoot(__dirname); if (!projectRoot) return false; // Check if src directory exists (development indicator) return existsSync(join(projectRoot, 'src')); } /** * Find the correct entry point based on installation type */ function findEntryPoint() { const projectRoot = findProjectRoot(__dirname); // Possible entry points in order of preference const possiblePaths = [ // MCP server entry point (highest priority for minimal package) join(__dirname, '..', 'server.js'), join(projectRoot || '', 'server.js'), // Production builds join(__dirname, '..', 'dist', 'index.js'), // npm global install join(__dirname, '..', 'dist', 'server.js'), // alternative entry join(projectRoot || '', 'dist', 'index.js'), // local install join(projectRoot || '', 'dist', 'server.js'), // alternative local // Development paths join(__dirname, '..', 'src', 'index.ts'), // development mode join(__dirname, '..', 'src', 'server.ts'), // alternative dev join(projectRoot || '', 'src', 'index.ts'), // local dev join(projectRoot || '', 'src', 'server.ts'), // alternative local dev // Fallback to current directory join(process.cwd(), 'dist', 'index.js'), join(process.cwd(), 'src', 'index.ts'), ].filter(Boolean); // Remove any null paths // Find first existing path for (const path of possiblePaths) { if (existsSync(path)) { return path; } } return null; } /** * Check if tsx is available for TypeScript execution */ function hasTsx() { try { const { execSync } = require('child_process'); execSync('tsx --version', { stdio: 'ignore' }); return true; } catch { return false; } } /** * Main execution */ function main() { console.log('Starting Claude Code Subagents Orchestrator...\n'); const entryPoint = findEntryPoint(); if (!entryPoint) { console.error('ERROR: Could not find claude-orchestrator entry point'); console.error('\nSearched in:'); console.error(' - Global npm installation'); console.error(' - Local npm installation'); console.error(' - Development environment'); console.error(' - Current directory'); console.error('\nPlease ensure the package is properly installed.'); console.error('\nTry running: npm install -g claude-code-subagents-orchestrator'); process.exit(1); } // Determine execution method const isTypeScript = entryPoint.endsWith('.ts'); let executable = 'node'; let args = []; if (isTypeScript) { if (hasTsx()) { executable = 'tsx'; args = [entryPoint]; } else { // Fallback to node with experimental loader args = [ '--loader', 'tsx', '--no-warnings', entryPoint ]; } } else { // For JavaScript files, check if ES modules try { const projectRoot = findProjectRoot(dirname(entryPoint)); if (projectRoot) { const packageJson = JSON.parse(readFileSync(join(projectRoot, 'package.json'), 'utf8')); if (packageJson.type === 'module') { // ES modules need experimental specifier resolution args = [ '--experimental-specifier-resolution=node', '--no-warnings', entryPoint ]; } else { args = [entryPoint]; } } else { args = [entryPoint]; } } catch { args = [entryPoint]; } } // Add user arguments args.push(...process.argv.slice(2)); // Debug output in verbose mode if (process.argv.includes('--debug') || process.argv.includes('-v')) { console.log(`Entry point: ${entryPoint}`); console.log(`Executable: ${executable}`); console.log(`Arguments: ${args.join(' ')}\n`); } // Spawn the process const child = spawn(executable, args, { stdio: 'inherit', env: { ...process.env, CLAUDE_ORCHESTRATOR_LAUNCHER: 'true', CLAUDE_ORCHESTRATOR_ROOT: findProjectRoot(__dirname) || __dirname, }, shell: false }); // Handle child process events child.on('error', (error) => { console.error('\nERROR: Failed to start orchestrator:', error.message); if (error.code === 'ENOENT') { console.error(`\nThe executable '${executable}' was not found.`); if (isTypeScript && !hasTsx()) { console.error('\nFor TypeScript execution, please install tsx:'); console.error(' npm install -g tsx'); } } process.exit(1); }); child.on('exit', (code, signal) => { if (signal) { console.log(`\nOrchestrator terminated by signal: ${signal}`); process.exit(1); } else if (code !== null && code !== 0) { process.exit(code); } else { process.exit(0); } }); // Forward signals to child process ['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach(signal => { process.on(signal, () => { if (!child.killed) { child.kill(signal); } }); }); } // Error handling process.on('uncaughtException', (error) => { console.error('\nFATAL ERROR:', error.message); console.error(error.stack); process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { console.error('\nUnhandled Promise Rejection:', reason); process.exit(1); }); // Run the launcher main();