UNPKG

@agentics.org/sparc2

Version:

SPARC 2.0 - Autonomous Vector Coding Agent + MCP. SPARC 2.0, vectorized AI code analysis, is an intelligent coding agent framework built to automate and streamline software development. It combines secure execution environments, and version control into a

401 lines (344 loc) 12.5 kB
#!/usr/bin/env node /** * SPARC2 CLI Wrapper Script * * This script provides a more robust way to run the SPARC2 CLI, * with better error handling and diagnostics. */ import { spawn, execSync } from 'child_process'; import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; // Get the directory of this script const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // ANSI color codes for terminal output const colors = { red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m', reset: '\x1b[0m' }; /** * Check if Deno is installed * @returns {boolean} True if Deno is installed, false otherwise */ function isDenoInstalled() { try { execSync('deno --version', { stdio: 'ignore' }); return true; } catch (error) { return false; } } /** * Print Deno installation instructions */ function printDenoInstallInstructions() { console.log(`${colors.red}Error: Deno is required but not installed.${colors.reset}`); console.log(`${colors.yellow}Please install Deno using one of the following methods:${colors.reset}`); console.log(`\n${colors.blue}Linux/macOS:${colors.reset}`); console.log(` curl -fsSL https://deno.land/install.sh | sh`); console.log(`\n${colors.blue}Windows (PowerShell):${colors.reset}`); console.log(` irm https://deno.land/install.ps1 | iex`); // Check if the install script exists const installScriptPath = path.join(__dirname, 'install-deno.sh'); if (fs.existsSync(installScriptPath)) { console.log(`\n${colors.green}Or run the included installation script:${colors.reset}`); console.log(` ${installScriptPath}`); } console.log(`\n${colors.yellow}For more information, visit: https://deno.land/#installation${colors.reset}`); console.log(`\n${colors.cyan}After installing Deno, you may need to restart your terminal or add Deno to your PATH.${colors.reset}`); } /** * Check if we're running from a global installation (node_modules) * @returns {boolean} True if running from node_modules, false otherwise */ function isRunningFromNodeModules() { // More robust check for node_modules return __dirname.includes('node_modules') || __dirname.includes('/usr/local/') || __dirname.includes('/usr/lib/') || __dirname.includes('/usr/share/'); } /** * Find the CLI TypeScript source file * @returns {string|null} Path to the CLI TypeScript file if found, null otherwise */ function findCliSourceFile() { // Possible locations for the CLI TypeScript source file const possiblePaths = [ // Local source directory path.join(__dirname, 'src', 'cli', 'cli.ts'), // Current directory path.join(process.cwd(), 'src', 'cli', 'cli.ts') ]; for (const p of possiblePaths) { if (fs.existsSync(p)) { return p; } } return null; } /** * Find the CLI script (JS) * @returns {string|null} Path to the CLI script if found, null otherwise */ function findCliScript() { // Possible locations for the CLI script const possiblePaths = [ // Local build directory path.join(__dirname, 'build', 'cli', 'cli.js'), // Global installation path.join(__dirname, 'build', 'cli', 'cli.js') ]; for (const p of possiblePaths) { if (fs.existsSync(p)) { return p; } } return null; } /** * Run the CLI using Deno directly with the TypeScript source */ function runCliWithDeno() { const cliSourcePath = findCliSourceFile(); if (!cliSourcePath) { console.log(`${colors.yellow}No TypeScript source found, trying JavaScript...${colors.reset}`); runCliFallback(); return; } console.log(`${colors.green}Found CLI TypeScript source at: ${cliSourcePath}${colors.reset}`); // Run the CLI using Deno const denoArgs = [ 'run', '--allow-read', '--allow-write', '--allow-env', '--allow-net', '--allow-run', cliSourcePath, ...process.argv.slice(2) ]; console.log(`${colors.blue}Running: deno ${denoArgs.join(' ')}${colors.reset}`); // Spawn the Deno process const denoProcess = spawn('deno', denoArgs, { stdio: 'inherit', env: process.env }); // Handle process exit denoProcess.on('exit', (code) => { if (code !== 0) { console.log(`${colors.red}CLI exited with code ${code}${colors.reset}`); process.exit(code); } }); // Forward signals to the child process ['SIGINT', 'SIGTERM'].forEach(signal => { process.on(signal, () => { denoProcess.kill(signal); }); }); } /** * Fallback to running the CLI using Node.js */ function runCliFallback() { const cliPath = findCliScript(); if (!cliPath) { console.log(`${colors.red}Error: Could not find any SPARC2 CLI script.${colors.reset}`); console.log(`${colors.yellow}This could be due to an incomplete installation or build.${colors.reset}`); console.log(`${colors.yellow}Try running 'npm run build' in the SPARC2 directory.${colors.reset}`); process.exit(1); } console.log(`${colors.green}Found CLI at: ${cliPath}${colors.reset}`); // Run the CLI using Node const nodeArgs = [cliPath, ...process.argv.slice(2)]; console.log(`${colors.blue}Running: node ${nodeArgs.join(' ')}${colors.reset}`); // Spawn the Node process const nodeProcess = spawn('node', nodeArgs, { stdio: 'inherit', env: process.env }); // Handle process exit nodeProcess.on('exit', (code) => { if (code !== 0) { console.log(`${colors.red}CLI exited with code ${code}${colors.reset}`); process.exit(code); } }); // Forward signals to the child process ['SIGINT', 'SIGTERM'].forEach(signal => { process.on(signal, () => { nodeProcess.kill(signal); }); }); } /** * Run a simplified version of the CLI directly */ function runSimplifiedCli() { console.log("OpenAI client initialized"); const args = process.argv.slice(2); // Handle help and version flags if (args.includes('--help') || args.includes('-h') || args.length === 0) { printHelp(); return; } if (args.includes('--version') || args.includes('-v')) { printVersion(); return; } // Handle supported commands with wrappers if (['mcp', 'analyze', 'modify'].includes(args[0])) { const wrapperName = `sparc2-${args[0]}-wrapper.js`; const wrapperPath = path.join(__dirname, wrapperName); if (fs.existsSync(wrapperPath)) { console.log(`${colors.green}Found ${args[0]} wrapper at: ${wrapperPath}${colors.reset}`); console.log(`${colors.blue}Running ${args[0]} command...${colors.reset}`); // Spawn the process const childProcess = spawn('node', [wrapperPath, ...args.slice(1)], { stdio: 'inherit', env: process.env }); // Handle process exit childProcess.on('exit', (code) => { if (code !== 0) { console.log(`${colors.red}Command exited with code ${code}${colors.reset}`); process.exit(code); } }); // Forward signals to the child process ['SIGINT', 'SIGTERM'].forEach(signal => { process.on(signal, () => { childProcess.kill(signal); }); }); return; } } // For all other commands, print a message explaining the situation console.log(`${colors.yellow}This is a simplified version of the SPARC2 CLI.${colors.reset}`); console.log(`${colors.yellow}For full functionality, please run SPARC2 from a local installation.${colors.reset}`); console.log(`${colors.yellow}You can clone the repository and run it locally:${colors.reset}`); console.log(`${colors.blue}git clone https://github.com/agentics-org/sparc2.git${colors.reset}`); console.log(`${colors.blue}cd sparc2${colors.reset}`); console.log(`${colors.blue}npm install${colors.reset}`); console.log(`${colors.blue}npm run build${colors.reset}`); console.log(`${colors.blue}./sparc2 ${args.join(' ')}${colors.reset}`); // Print help as a fallback console.log(""); printHelp(); } /** * Print the CLI help message */ function printHelp() { console.log("SPARC 2.0 CLI v2.0.24"); console.log(""); console.log("Usage: sparc2 <command> [options]"); console.log(""); console.log("Commands:"); console.log(" analyze Analyze code files for issues and improvements"); console.log(" modify Apply suggested modifications to code files"); console.log(" execute Execute code in a sandbox"); console.log(" search Search for similar code changes"); console.log(" checkpoint Create a git checkpoint"); console.log(" rollback Rollback to a previous checkpoint"); console.log(" config Manage configuration"); console.log(" api Start a Model Context Protocol (MCP) HTTP API server"); console.log(" mcp Start a Model Context Protocol (MCP) server using stdio transport"); console.log(""); console.log("Options:"); console.log(" --help, -h Show help"); console.log(" --version, -v Show version"); console.log(""); console.log("For command-specific help, run: sparc2 <command> --help"); } /** * Print the CLI version */ function printVersion() { console.log("SPARC 2.0 CLI v2.0.24"); } /** * Display diagnostic information */ function showDiagnostics() { console.log(`${colors.magenta}=== SPARC2 CLI Diagnostics ===${colors.reset}`); // Check Node.js version try { const nodeVersion = execSync('node --version').toString().trim(); console.log(`${colors.green}Node.js version: ${nodeVersion}${colors.reset}`); } catch (error) { console.log(`${colors.red}Failed to get Node.js version: ${error.message}${colors.reset}`); } // Check Deno version try { const denoVersion = execSync('deno --version').toString().trim().split('\n')[0]; console.log(`${colors.green}Deno version: ${denoVersion}${colors.reset}`); } catch (error) { console.log(`${colors.red}Deno is not installed or not in PATH${colors.reset}`); } // Check npm version try { const npmVersion = execSync('npm --version').toString().trim(); console.log(`${colors.green}npm version: ${npmVersion}${colors.reset}`); } catch (error) { console.log(`${colors.red}Failed to get npm version: ${error.message}${colors.reset}`); } // Check SPARC2 package version try { const packageJsonPath = path.join(__dirname, 'package.json'); if (fs.existsSync(packageJsonPath)) { const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); console.log(`${colors.green}SPARC2 package version: ${packageJson.version}${colors.reset}`); } else { console.log(`${colors.yellow}Could not find package.json${colors.reset}`); } } catch (error) { console.log(`${colors.red}Failed to read package.json: ${error.message}${colors.reset}`); } // Check if running from node_modules const isGlobal = isRunningFromNodeModules(); console.log(`${colors.green}Running from node_modules: ${isGlobal}${colors.reset}`); // Check for CLI TypeScript source const cliSourcePath = findCliSourceFile(); if (cliSourcePath) { console.log(`${colors.green}Found CLI TypeScript source at: ${cliSourcePath}${colors.reset}`); } else { console.log(`${colors.yellow}Could not find CLI TypeScript source${colors.reset}`); } // Check for CLI script const cliPath = findCliScript(); if (cliPath) { console.log(`${colors.green}Found CLI script at: ${cliPath}${colors.reset}`); } else { console.log(`${colors.red}Could not find CLI script${colors.reset}`); } // Check current directory console.log(`${colors.green}Current directory: ${process.cwd()}${colors.reset}`); console.log(`${colors.green}Script directory: ${__dirname}${colors.reset}`); console.log(`${colors.magenta}=== End of Diagnostics ===${colors.reset}`); } // Main execution if (process.argv.includes('--diagnostics')) { showDiagnostics(); process.exit(0); } if (!isDenoInstalled()) { printDenoInstallInstructions(); process.exit(1); } // If running from node_modules, use the simplified CLI if (isRunningFromNodeModules()) { console.log(`${colors.yellow}Running from global installation, using simplified CLI${colors.reset}`); runSimplifiedCli(); } else { // Otherwise, try to run with Deno first (directly from TypeScript) runCliWithDeno(); }