UNPKG

@vfarcic/dot-ai

Version:

AI-powered development productivity platform that enhances software development workflows through intelligent automation and AI-driven assistance

131 lines (130 loc) 5.29 kB
"use strict"; /** * Shared Command Executor * * Provides common command execution logic for tools (remediate, operate, etc.) * Uses continue-on-error pattern: executes all commands sequentially regardless * of individual failures. * * PRD #343: Commands are executed through the plugin system via shell_exec tool. * The plugin container has RBAC permissions; the MCP server does not. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.executeCommands = executeCommands; const plugin_registry_1 = require("./plugin-registry"); /** * Execute a list of commands sequentially with continue-on-error pattern * * PRD #343: Commands are executed through the plugin's shell_exec tool. * PRD #359: Uses unified plugin registry for tool invocation. * The plugin container has RBAC; commands are executed exactly as provided * (no parsing or transformation). * * @param commands - Array of command strings to execute * @param logger - Logger instance for tracking execution * @param options - Optional execution context and metadata * @returns Array of execution results and overall success status */ async function executeCommands(commands, logger, options = {}) { if (!(0, plugin_registry_1.isPluginInitialized)()) { throw new Error('Plugin system not initialized'); } const results = []; let overallSuccess = true; const { sessionId, context = 'command execution', logMetadata = {} } = options; logger.info(`Starting ${context}`, { ...logMetadata, sessionId, commandCount: commands.length }); // Execute each command sequentially for (let i = 0; i < commands.length; i++) { const command = commands[i]; const commandNum = i + 1; try { logger.debug(`Executing command ${commandNum}/${commands.length}`, { ...logMetadata, sessionId, command }); // Clean up escape sequences that AI models sometimes add const cleanCommand = command.replace(/\\"/g, '"'); // PRD #359: Execute command via unified plugin registry const response = await (0, plugin_registry_1.invokePluginTool)('agentic-tools', 'shell_exec', { command: cleanCommand }); if (response.success) { // Check for nested error - plugin wraps command errors in { success: false, error: "..." } if (typeof response.result === 'object' && response.result !== null) { const result = response.result; if (result.success === false) { throw new Error(result.error || result.message || 'Command execution failed'); } } // Extract only the data field - never pass JSON wrapper let output; if (typeof response.result === 'object' && response.result !== null) { const result = response.result; if (result.data !== undefined) { output = String(result.data); } else if (typeof result === 'string') { output = result; } else { throw new Error('Plugin returned unexpected response format - missing data field'); } } else { output = String(response.result || ''); } results.push({ command, success: true, output: output, timestamp: new Date() }); logger.debug(`Command ${commandNum} succeeded`, { ...logMetadata, sessionId }); } else { const errorMessage = response.error?.message || 'Command execution failed'; overallSuccess = false; results.push({ command, success: false, error: errorMessage, timestamp: new Date() }); logger.error(`Command ${commandNum} failed`, new Error(errorMessage), { ...logMetadata, sessionId, command }); } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; overallSuccess = false; results.push({ command, success: false, error: errorMessage, timestamp: new Date() }); logger.error(`Command ${commandNum} failed`, error, { ...logMetadata, sessionId, command }); // Continue to next command (continue-on-error pattern) } } logger.info(`${context} completed`, { ...logMetadata, sessionId, successCount: results.filter(r => r.success).length, failureCount: results.filter(r => !r.success).length }); return { results, overallSuccess }; }