executor-tool.js•27.7 kB
import { spawn, execSync } from 'child_process';
import { validateWorkingDirectory, createToolResponse, validateRequiredParams as validateRequiredParamsUtil } from '../core/utilities.js';
import { writeFileSync, chmodSync, unlinkSync } from 'fs';
import path from 'path';
import os from 'os';
import { workingDirectoryContext, createToolContext } from '../core/working-directory-context.js';
import { suppressConsoleOutput } from '../core/console-suppression.js';
import { executionState, shouldExecuteAsync, addExecutionStatusToResponse } from '../core/execution-state.js';
import { ToolError, ToolErrorHandler } from '../core/error-handling.js';
import { withConnectionManagement, getGlobalConnectionManager } from '../core/connection-manager.js';
import { withCrossToolAwareness, addToolMetadata } from '../core/cross-tool-context.js';
function getContextSummary(context) {
  if (!context || !context.sessionData) {
    return '';
  }
  const lines = [];
  // Only include practically useful information
  if (context.workingDirectory !== process.cwd()) {
    lines.push(`Working directory: ${context.workingDirectory}`);
  }
  return lines.join('\n') + '\n';
}
function createExecutionErrorResponse(error, startTime, context = {}) {
  return {
    success: false,
    error: error?.message || error || 'Unknown error occurred',
    executionTimeMs: Date.now() - startTime,
    ...context
  };
}
// Enhance execution result with error analysis and actionable suggestions
function enhanceExecutionResult(result, code, runtime, workingDirectory) {
  if (!result || result.success) {
    return result;
  }
  // Perform error analysis for syntax errors
  const errorAnalysis = analyzeExecutionError(result.stderr, result.stdout, runtime, code);
  // Create enhanced error response
  const enhancedResult = {
    ...result,
    _errorAnalysis: errorAnalysis,
    _requiresTroubleshooting: errorAnalysis.isSyntaxError || !result.success,
    _suggestions: errorAnalysis.suggestions || [],
    _confidence: errorAnalysis.confidence
  };
  // If this is a syntax error, provide detailed guidance
  if (errorAnalysis.isSyntaxError) {
    enhancedResult.error = `🐛 SYNTAX ERROR DETECTED: ${errorAnalysis.specificError}`;
    enhancedResult._troubleshootingRequired = true;
    enhancedResult._nextSteps = [
      'Review the code syntax carefully',
      'Fix the identified syntax issues',
      'Test the corrected code again',
      'Use language-specific documentation if needed'
    ];
  }
  return enhancedResult;
}
function generateExecutionInsights(result, query, workingDirectory) {
  const insights = [];
  if (result.success) {
    if (result.filesAccessed && result.filesAccessed.length > 0) {
      insights.push(`Modified ${result.filesAccessed.length} files: ${result.filesAccessed.slice(0, 3).join(', ')}${result.filesAccessed.length > 3 ? '...' : ''}`);
    }
    if (result.executionTimeMs) {
      insights.push(`Execution time: ${result.executionTimeMs}ms`);
    }
    if (result.stdout && result.stdout.length > 0) {
      const lines = result.stdout.split('\n').length;
      insights.push(`Generated ${lines} lines of output`);
    }
  }
  if (workingDirectory !== process.cwd()) {
    insights.push(`Working directory: ${workingDirectory}`);
  }
  return insights;
}
function createSuccessResponse(data, startTime, context = {}) {
  return {
    success: true,
    executionTimeMs: Date.now() - startTime,
    ...data,
    ...context
  };
}
function createTimeoutError(operation, timeoutMs, startTime) {
  return createExecutionErrorResponse(
    `${operation} timed out after ${timeoutMs}ms`,
    startTime,
    { timeout: true, timeoutMs }
  );
}
function handleProcessError(error, command, startTime) {
  let errorMessage = 'Process execution failed';
  let errorContext = { command };
  let suggestions = [];
  if (error.code === 'ENOENT') {
    errorMessage = `Command not found: ${command}`;
    errorContext.missingCommand = true;
    suggestions = [
      `Install ${command} using your package manager`,
      `Check if ${command} is in your PATH`,
      `Verify the command name is correct`
    ];
  } else if (error.code === 'EACCES') {
    errorMessage = `Permission denied executing: ${command}`;
    errorContext.permissionDenied = true;
    suggestions = [
      `Check file permissions for ${command}`,
      `Run with appropriate permissions`,
      `Verify the command is executable`
    ];
  } else if (error.signal) {
    errorMessage = `Process terminated with signal: ${error.signal}`;
    errorContext.signal = error.signal;
    suggestions = [
      `Process was killed by signal ${error.signal}`,
      `Check for resource limits or timeouts`,
      `Verify system resources are available`
    ];
  } else if (error.code) {
    errorMessage = `Process failed with code: ${error.code}`;
    errorContext.exitCode = error.code;
    suggestions = [
      `Check the error output for details`,
      `Verify the command syntax and arguments`,
      `Check if all required dependencies are available`
    ];
  }
  return {
    ...createExecutionErrorResponse(errorMessage, startTime, errorContext),
    suggestions,
    requiresTroubleshooting: true
  };
}
// Enhanced syntax error detection and analysis
function analyzeExecutionError(stderr, stdout, runtime, code) {
  const analysis = {
    isSyntaxError: false,
    errorType: 'unknown',
    specificError: null,
    suggestions: [],
    confidence: 0,
    context: {}
  };
  const errorOutput = (stderr || stdout || '').toLowerCase();
  // JavaScript/TypeScript syntax errors
  if (['nodejs', 'deno'].includes(runtime)) {
    if (errorOutput.includes('syntaxerror')) {
      analysis.isSyntaxError = true;
      analysis.errorType = 'syntax';
      analysis.specificError = extractJavaScriptError(errorOutput);
            analysis.confidence = 0.9;
    }
  }
  // Python syntax errors
  else if (runtime === 'python') {
    if (errorOutput.includes('syntaxerror')) {
      analysis.isSyntaxError = true;
      analysis.errorType = 'syntax';
      analysis.specificError = extractPythonError(errorOutput);
            analysis.confidence = 0.9;
    }
  }
  // Go compilation errors
  else if (runtime === 'go') {
    if (errorOutput.includes('syntax error') || errorOutput.includes('expected')) {
      analysis.isSyntaxError = true;
      analysis.errorType = 'syntax';
      analysis.specificError = extractGoError(errorOutput);
            analysis.confidence = 0.85;
    }
  }
  // Rust compilation errors
  else if (runtime === 'rust') {
    if (errorOutput.includes('error:') && errorOutput.includes('expected')) {
      analysis.isSyntaxError = true;
      analysis.errorType = 'syntax';
      analysis.specificError = extractRustError(errorOutput);
            analysis.confidence = 0.85;
    }
  }
  // C/C++ compilation errors
  else if (['c', 'cpp'].includes(runtime)) {
    if (errorOutput.includes('error:') && errorOutput.includes('expected')) {
      analysis.isSyntaxError = true;
      analysis.errorType = 'syntax';
      analysis.specificError = extractCppError(errorOutput);
            analysis.confidence = 0.85;
    }
  }
  return analysis;
}
function extractJavaScriptError(errorOutput) {
  const match = errorOutput.match(/syntaxerror:\s*(.+?)(?=\n|$)/i);
  return match ? match[1].trim() : 'Unknown JavaScript syntax error';
}
function extractPythonError(errorOutput) {
  const match = errorOutput.match(/syntaxerror:\s*(.+?)(?=\n|$)/i);
  return match ? match[1].trim() : 'Unknown Python syntax error';
}
function extractGoError(errorOutput) {
  const match = errorOutput.match(/syntax error:\s*(.+?)(?=\n|$)/i);
  return match ? match[1].trim() : 'Unknown Go syntax error';
}
function extractRustError(errorOutput) {
  const match = errorOutput.match(/error\[E\d+\]:\s*(.+?)(?=\n|$)/i);
  return match ? match[1].trim() : 'Unknown Rust syntax error';
}
function extractCppError(errorOutput) {
  const match = errorOutput.match(/error:\s*(.+?)(?=\n|$)/i);
  return match ? match[1].trim() : 'Unknown C/C++ syntax error';
}
export async function executeProcess(command, args = [], options = {}) {
  const startTime = Date.now();
  const { timeout = 240000, cwd, input, encoding = 'utf8' } = options;
  return new Promise((resolve) => {
    const child = spawn(command, args, {
      cwd,
      stdio: input ? 'pipe' : ['pipe', 'pipe', 'pipe']
    });
    let stdout = '';
    let stderr = '';
    let isResolved = false;
    const timeoutId = setTimeout(() => {
      if (!isResolved) {
        child.kill('SIGTERM');
        isResolved = true;
        resolve(createTimeoutError(`${command} ${args.join(' ')}`, timeout, startTime));
      }
    }, timeout);
    if (child.stdout) {
      child.stdout.on('data', (data) => {
        if (data && typeof data === 'object' && Buffer.isBuffer(data)) {
          stdout += data.toString(encoding);
        } else if (data && typeof data === 'string') {
          stdout += data;
        }
      });
    }
    if (child.stderr) {
      child.stderr.on('data', (data) => {
        if (data && typeof data === 'object' && Buffer.isBuffer(data)) {
          stderr += data.toString(encoding);
        } else if (data && typeof data === 'string') {
          stderr += data;
        }
      });
    }
    child.on('close', (code, signal) => {
      if (!isResolved) {
        clearTimeout(timeoutId);
        isResolved = true;
        if (code === 0) {
          resolve(createSuccessResponse({ stdout, stderr, code, signal }, startTime));
        } else {
          resolve(createExecutionErrorResponse(
            stderr || `Process exited with code ${code}`,
            startTime,
            { stdout, stderr, code, signal }
          ));
        }
      }
    });
    child.on('error', (error) => {
      if (!isResolved) {
        clearTimeout(timeoutId);
        isResolved = true;
        resolve(handleProcessError(error, `${command} ${args.join(' ')}`, startTime));
      }
    });
    if (input && child.stdin) {
      child.stdin.write(input);
      child.stdin.end();
    }
  });
}
const EXECUTION_CONFIGS = {
  nodejs: { command: 'node', args: ['-e'], description: 'Node.js JavaScript' },
  deno: { command: 'deno', args: ['eval', '--no-check'], description: 'Deno JavaScript/TypeScript' },
  bash: { command: 'bash', args: ['-c'], description: 'Bash shell commands' },
  go: { command: 'go', args: ['run'], description: 'Go programming language', requiresFile: true },
  rust: { command: 'rustc', args: [], description: 'Rust programming language', requiresCompile: true },
  python: { command: 'python3', args: ['-c'], description: 'Python programming language' },
  c: { command: 'gcc', args: [], description: 'C programming language', requiresCompile: true },
  cpp: { command: 'g++', args: [], description: 'C++ programming language', requiresCompile: true }
};
export async function executeWithRuntime(codeOrCommands, runtime, options = {}) {
  const { workingDirectory, timeout = 240000 } = options;
  const config = EXECUTION_CONFIGS[runtime];
  if (!config) {
    throw new Error(`Unsupported runtime: ${runtime}`);
  }
  
  if (runtime === 'bash') {
    
    if (Array.isArray(codeOrCommands)) {
      const script = createBashScript(codeOrCommands);
      const tempScript = path.join(os.tmpdir(), `glootie_bash_${Date.now()}.sh`);
      writeFileSync(tempScript, script);
      chmodSync(tempScript, '755');
      
      return executeProcess(config.command, [tempScript], {
        cwd: workingDirectory,
        timeout,
        encoding: 'utf8'
      }).finally(() => {
        try { unlinkSync(tempScript); } catch (e) {
          
        }
      });
    } else {
      
      return executeProcess(config.command, [...config.args, codeOrCommands], {
        cwd: workingDirectory,
        timeout,
        encoding: 'utf8'
      });
    }
  }
  if (config.requiresFile) {
    
    const tempFile = path.join(os.tmpdir(), `glootie_${runtime}_${Date.now()}.${runtime === 'go' ? 'go' : 'rs'}`);
    try {
      writeFileSync(tempFile, codeOrCommands);
      return executeProcess(config.command, [...config.args, tempFile], {
        cwd: workingDirectory,
        timeout,
        encoding: 'utf8'
      });
    } finally {
      try { unlinkSync(tempFile); } catch (e) {}
    }
  }
  if (config.requiresCompile) {
    
    const extensions = { rust: 'rs', c: 'c', cpp: 'cpp' };
    const compilers = { rust: 'rustc', c: 'gcc', cpp: 'g++' };
    const tempFile = path.join(os.tmpdir(), `glootie_${runtime}_${Date.now()}.${extensions[runtime]}`);
    const tempExec = path.join(os.tmpdir(), `glootie_${runtime}_${Date.now()}`);
    try {
      writeFileSync(tempFile, codeOrCommands);
      
      const compileResult = await executeProcess(compilers[runtime], [tempFile, '-o', tempExec], {
        cwd: workingDirectory,
        timeout: timeout / 2,
        encoding: 'utf8'
      });
      if (!compileResult.success) {
        return compileResult;
      }
      
      return await executeProcess(tempExec, [], {
        cwd: workingDirectory,
        timeout: timeout / 2,
        encoding: 'utf8'
      });
    } finally {
      try { unlinkSync(tempFile); } catch (e) {}
      try { unlinkSync(tempExec); } catch (e) {}
    }
  }
  
  return executeProcess(config.command, [...config.args, codeOrCommands], {
    cwd: workingDirectory,
    timeout,
    encoding: 'utf8'
  });
}
export async function executeBashCommands(commands, options = {}) {
  return executeWithRuntime(commands, 'bash', options);
}
export async function executeNodeCode(code, options = {}) {
  return executeWithRuntime(code, 'nodejs', options);
}
export async function executeDenoCode(code, options = {}) {
  return executeWithRuntime(code, 'deno', options);
}
export async function executeBashCommand(commands, timeout = 240000, workingDirectory, defaultWorkingDir) {
  const startTime = Date.now();
  const paramError = validateRequiredParams({ workingDirectory }, ['workingDirectory'], startTime);
  if (paramError) return paramError;
  const dirValidation = validateWorkingDirectory(workingDirectory);
  if (!dirValidation.isValid) {
    return createExecutionErrorResponse(dirValidation.error, startTime);
  }
  const effectiveWorkingDir = dirValidation.resolvedDir;
  const commandArray = Array.isArray(commands) ? commands : [commands];
  
  const nonEmptyCommands = commandArray.filter(cmd => {
    if (typeof cmd !== 'string') return false;
    const trimmed = cmd.trim();
    
    return trimmed.length > 0 && !trimmed.startsWith('#');
  });
  if (nonEmptyCommands.length === 0) {
    return createExecutionErrorResponse("No valid commands to execute", startTime);
  }
  const validationResult = validateExecutionContent(nonEmptyCommands, 'Commands');
  if (!validationResult.valid) {
    return createExecutionErrorResponse(validationResult.error, startTime);
  }
  
  const securityValidation = validateBashCommands(nonEmptyCommands);
  if (!securityValidation.valid) {
    return createExecutionErrorResponse(securityValidation.error, startTime);
  }
  
  const result = await executeBashCommands(nonEmptyCommands, {
    workingDirectory: dirValidation.effectiveDir,
    timeout
  });
  return result;
}
export function validateBashCommands(commands) {
  if (!Array.isArray(commands) || commands.length === 0) {
    return {
      valid: false,
      error: "Commands must be a non-empty array"
    };
  }
  for (let i = 0; i < commands.length; i++) {
    const command = commands[i];
    if (typeof command !== 'string') {
      return {
        valid: false,
        error: `Command ${i}: Must be a string`
      };
    }
    if (command.trim().length === 0) {
      return {
        valid: false,
        error: `Command ${i}: Cannot be empty or whitespace only`
      };
    }
    const dangerous = ['rm -rf /', 'sudo rm', 'format', 'mkfs', ':(){ :|:& };:', 'dd if=/dev/zero'];
    const lowerCommand = command.toLowerCase();
    for (const pattern of dangerous) {
      if (lowerCommand.includes(pattern)) {
        return {
          valid: false,
          error: `Command ${i}: Contains potentially dangerous pattern '${pattern}'`
        };
      }
    }
  }
  return { valid: true };
}
function createBashScript(commands) {
  const scriptLines = [
    '#!/bin/bash',
    'set -e',
    'set -o pipefail',
    '',
    'echo "=== BASH EXECUTION START ==="',
    `echo "Commands to execute: ${commands.length}"`,
    'echo "Working directory: $(pwd)"',
    'echo "Timestamp: $(date)"',
    'echo ""'
  ];
  commands.forEach((command, index) => {
    scriptLines.push(`echo "--- Command ${index + 1}/${commands.length} ---"`);
    scriptLines.push(`echo "$ ${command}"`);
    scriptLines.push(command);
    scriptLines.push('CMD_EXIT_CODE=$?');
    scriptLines.push('if [ $CMD_EXIT_CODE -ne 0 ]; then');
    scriptLines.push(`  echo "Command ${index + 1} failed with exit code $CMD_EXIT_CODE" >&2`);
    scriptLines.push('  exit $CMD_EXIT_CODE');
    scriptLines.push('fi');
    scriptLines.push('echo ""');
  });
  scriptLines.push('echo "=== BASH EXECUTION COMPLETE ==="');
  scriptLines.push('echo "All commands completed"');
  return scriptLines.join('\n');
}
// validateRequiredParamsUtil is now imported from utilities.js
function validateExecutionContent(content, type) {
  if (!content || (typeof content !== 'string' && !Array.isArray(content))) {
    return { valid: false, error: `${type} must be a non-empty string or array` };
  }
  if (typeof content === 'string' && content.trim().length === 0) {
    return { valid: false, error: `${type} cannot be empty or whitespace only` };
  }
  if (Array.isArray(content) && content.length === 0) {
    return { valid: false, error: `${type} array cannot be empty` };
  }
  if (Array.isArray(content)) {
    for (let i = 0; i < content.length; i++) {
      const item = content[i];
      if (typeof item !== 'string') {
        return { valid: false, error: `${type} array item ${i} must be a string` };
      }
      if (item.trim().length === 0) {
        return { valid: false, error: `${type} array item ${i} cannot be empty` };
      }
    }
  }
  return { valid: true };
}
let runtimeCache = null;
export function detectAvailableRuntimes() {
  if (runtimeCache) return runtimeCache;
  const runtimes = {
    nodejs: { cmd: 'node --version', available: false, version: null },
    deno: { cmd: 'deno --version', available: false, version: null },
    bash: { cmd: 'bash --version', available: false, version: null },
    go: { cmd: 'go version', available: false, version: null },
    rust: { cmd: 'rustc --version', available: false, version: null },
    python: { cmd: 'python3 --version', available: false, version: null },
    c: { cmd: 'gcc --version', available: false, version: null },
    cpp: { cmd: 'g++ --version', available: false, version: null }
  };
  for (const [name, config] of Object.entries(runtimes)) {
    try {
      const result = execSync(config.cmd, {
        encoding: 'utf8',
        stdio: 'pipe'
      });
      config.available = true;
      config.version = result.split('\n')[0].trim();
    } catch (error) {
      config.available = false;
    }
  }
  runtimeCache = runtimes;
  return runtimes;
}
export async function executeWithRuntimeValidation(codeOrCommands, runtime, options = {}) {
  const startTime = Date.now();
  
  const runtimes = detectAvailableRuntimes();
  const runtimeInfo = runtimes[runtime];
  if (!runtimeInfo || !runtimeInfo.available) {
    const config = EXECUTION_CONFIGS[runtime];
    const errorMessage = `${config.description} runtime not available. Install ${config.command} to use this feature.`;
    return createExecutionErrorResponse(errorMessage, startTime);
  }
  return executeWithRuntime(codeOrCommands, runtime, options);
}
export async function executeGoCode(code, options = {}) {
  return executeWithRuntimeValidation(code, 'go', options);
}
export async function executePythonCode(code, options = {}) {
  return executeWithRuntimeValidation(code, 'python', options);
}
export async function executeRustCode(code, options = {}) {
  return executeWithRuntimeValidation(code, 'rust', options);
}
export async function executeCCode(code, options = {}) {
  return executeWithRuntimeValidation(code, 'c', options);
}
export async function executeCppCode(code, options = {}) {
  return executeWithRuntimeValidation(code, 'cpp', options);
}
export { generateExecutionInsights };
export const executionTools = [
  {
    name: "execute",
    description: "Execute code in JS/TS, Go, Rust, Python, C, C++, or bash with auto-runtime detection. Primary tool for testing hypotheses before implementation. Supports both code snippets and shell commands.",
    inputSchema: {
      type: "object",
      properties: {
        workingDirectory: {
          type: "string",
          description: "Path to working directory for execution."
        },
        code: {
          type: "string",
          description: "Code to execute. Include timeouts for network/async operations to prevent hangs."
        },
        commands: {
          type: ["string", "array"],
          description: "Bash commands (single or array for planned batch executions)"
        },
        runtime: {
          type: "string",
          enum: ["nodejs", "deno", "bash", "go", "rust", "python", "c", "cpp", "auto"],
          description: "Execution runtime (default: auto-detect)"
        },
        timeout: {
          type: "number",
          description: "Timeout in milliseconds (default: 240000)"
        }
      },
      required: ["workingDirectory"]
    },
    handler: withCrossToolAwareness(withConnectionManagement(async ({ code, commands, workingDirectory, runtime = "auto", timeout = 240000 }) => {
      const consoleRestore = suppressConsoleOutput();
      const effectiveWorkingDirectory = workingDirectory;
      const query = code || commands || '';
      try {
        // Validate required parameters
        if (!workingDirectory) {
          throw new ToolError(
            'Working directory is required',
            'MISSING_PARAMETER',
            'execute',
            false,
            ['Provide absolute path to working directory', 'Check tool documentation']
          );
        }
        // Start execution tracking for all operations
        const execution = executionState.startExecution({
          type: 'execute',
          code,
          commands,
          runtime,
          workingDirectory: effectiveWorkingDirectory,
          timeout
        });
        let result;
        if (code) {
          let targetRuntime = runtime === "auto" ? "nodejs" : runtime;
          if (runtime === "auto") {
            const shellCommands = ['npm ', 'npx ', 'yarn ', 'pip ', 'python ', 'go ', 'rustc ', 'gcc ', 'g++ ', 'git ', 'mkdir ', 'rm ', 'ls ', 'cd '];
            const isShellCommand = shellCommands.some(cmd => code.trim().startsWith(cmd));
            if (isShellCommand) {
              targetRuntime = 'bash';
            }
          }
          try {
            const executionStart = Date.now();
            result = await executeWithRuntimeValidation(code, targetRuntime, { workingDirectory, timeout });
            const executionDuration = Date.now() - executionStart;
            // Complete execution (duration-based logic for cross-tool sharing)
            executionState.completeExecution(execution.id, result);
          } catch (executionError) {
            if (targetRuntime === 'bash') {
              try {
                result = await executeWithRuntimeValidation(code, 'nodejs', { workingDirectory, timeout });
              } catch (fallbackError) {
                result = {
                  success: false,
                  stdout: '',
                  stderr: `Failed to execute as both bash and nodejs:\nBash error: ${executionError.message}\nNode.js error: ${fallbackError.message}`,
                  executionTimeMs: 0
                };
              }
            } else {
              result = {
                success: false,
                stdout: '',
                stderr: `Execution failed: ${executionError.message}`,
                executionTimeMs: 0
              };
            }
            executionState.failExecution(execution.id, executionError);
          }
          result = enhanceExecutionResult(result, code, targetRuntime, workingDirectory);
        } else if (commands) {
          try {
            const executionStart = Date.now();
            result = await executeWithRuntimeValidation(commands, 'bash', { workingDirectory, timeout });
            const executionDuration = Date.now() - executionStart;
            // Complete execution
            executionState.completeExecution(execution.id, result);
          } catch (executionError) {
            result = {
              success: false,
              stdout: '',
              stderr: `Command execution failed: ${executionError.message}`,
              executionTimeMs: 0
            };
            executionState.failExecution(execution.id, executionError);
          }
          result = enhanceExecutionResult(result, commands, 'bash', workingDirectory);
        } else {
          result = { content: [{ type: "text", text: "No code or commands provided" }] };
        }
        const insights = generateExecutionInsights(result, query, effectiveWorkingDirectory);
        // Format response with enhanced error information
        let responseContent = result;
        if (result._errorAnalysis && result._errorAnalysis.isSyntaxError) {
          // Simple error response
          responseContent = {
            ...result,
            content: [{ type: "text", text: result.error || result.stderr || 'Execution failed' }]
          };
        } else if (!result.success) {
          // Simple error format
          responseContent = {
            ...result,
            content: [{ type: "text", text: result.error || result.stderr || 'Execution failed' }]
          };
        } else if (!result.content) {
          // Format successful execution or basic error
          let outputText = '';
          if (result.success) {
            outputText = result.stdout || 'Execution successful';
          } else {
            outputText = result.error || result.stderr || 'Execution failed';
          }
          responseContent = {
            ...result,
            content: [{ type: "text", text: outputText }]
          };
        }
        const toolContext = createToolContext('execute', effectiveWorkingDirectory, query, {
          ...responseContent,
          duration: responseContent.executionTimeMs || 0,
          filesAccessed: responseContent.filesAccessed || [],
          patterns: responseContent.patterns || [],
          insights: insights
        });
        await workingDirectoryContext.updateContext(effectiveWorkingDirectory, 'execute', toolContext);
        // Clean up old executions
        executionState.cleanup();
        return responseContent;
      } catch (error) {
        const errorContext = createToolContext('execute', effectiveWorkingDirectory, query, {
          error: error.message,
          duration: 0
        });
        await workingDirectoryContext.updateContext(effectiveWorkingDirectory, 'execute', errorContext);
        return {
          content: [{ type: "text", text: `Execution error: ${error.message}` }],
          isError: true
        };
      } finally {
        consoleRestore.restore();
      }
    }, 'execute', {
      maxRetries: 2,
      retryDelay: 1000
    }), 'execute')
  }
];