UNPKG

@commit451/salamander

Version:

Never be AFK

79 lines • 3.25 kB
import { execSync } from 'child_process'; import chalk from 'chalk'; import { RunnerType } from '../types/runner.js'; export class CommandExecutor { static async executeCommand(runner, command) { console.log(chalk.blue(`\nšŸ”§ Executing command for runner "${runner.name}"`)); console.log(chalk.gray(`Directory: ${runner.directory}`)); console.log(chalk.gray(`Command: ${command}`)); console.log(chalk.gray(`Type: ${runner.runnerType}\n`)); const startTime = Date.now(); try { const output = this.executeRunnerCommand(runner, command); const executionTime = Date.now() - startTime; console.log(chalk.green('āœ… Command completed successfully')); console.log(chalk.grey(output)); return { output: output || 'Command executed successfully (no output)', success: true, executionTime }; } catch (error) { const executionTime = Date.now() - startTime; console.error(chalk.red('āŒ Error executing command:'), error.message); return { output: `Failed to execute command: ${error.message}`, success: false, executionTime }; } } static executeRunnerCommand(runner, userInput) { const commandLine = this.buildCommandLine(runner, userInput); try { const output = execSync(commandLine, { cwd: runner.directory, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }); return output.trim(); } catch (error) { // Check for common error patterns if (error.message.includes('command not found') || error.message.includes('No such file')) { const toolName = this.getToolName(runner.runnerType); throw new Error(`${toolName} CLI not found. Please ensure ${toolName} is installed and accessible.`); } else { throw new Error(error.stderr?.trim() || error.stdout?.trim() || error.message); } } } static buildCommandLine(runner, userInput) { // Escape quotes in user input to prevent command injection const escapedInput = userInput.replace(/"/g, '\\"'); switch (runner.runnerType) { case RunnerType.CLAUDE: const continuationFlag = runner.lastMessage ? '-c ' : ''; return `claude ${continuationFlag}-p --dangerously-skip-permissions "${escapedInput}"`; case RunnerType.GEMINI: return `gemini -p "${escapedInput}" --yolo`; case RunnerType.CODEX: return `codex exec "${escapedInput}" --full-auto --skip-git-repo-check`; } } static getToolName(runnerType) { switch (runnerType) { case RunnerType.CLAUDE: return 'Claude'; case RunnerType.GEMINI: return 'Gemini'; case RunnerType.CODEX: return 'Codex'; default: return 'Claude'; } } } //# sourceMappingURL=executor.js.map