UNPKG

coding-agent

Version:

An AI coding agent using @agenite framework

114 lines (113 loc) 4.58 kB
import { Tool } from '@agenite/tool'; import { spawn } from 'child_process'; export function createCommandRunnerTool() { const commandCache = new Map(); return new Tool({ name: 'command_runner', description: 'Executes shell commands on the system. Use with caution as improper commands can cause unintended behavior.', inputSchema: { type: 'object', properties: { command: { type: 'string', description: 'The command to execute. Ensure it is a valid shell command.', }, cwd: { type: 'string', description: 'Optional working directory for the command.', }, timeout: { type: 'number', description: 'Optional timeout in milliseconds (default: 30,000 ms).', }, }, required: ['command'], }, async execute({ input }) { const startTime = Date.now(); const cacheKey = `${input.command}-${input.cwd || ''}-${input.timeout || 30000}`; // Validate command input if (!input.command || typeof input.command !== 'string') { return { isError: true, data: 'Invalid command input. Must be a non-empty string.', duration: 0, }; } // Check cache for recent execution results const cached = commandCache.get(cacheKey); if (cached && startTime - cached.timestamp < 60000) { return { isError: !cached.success, data: cached.data, duration: 0, }; } return new Promise((resolve) => { let output = ''; let errorOutput = ''; const [cmd, ...args] = input.command.split(' '); if (!cmd) { return resolve({ isError: true, data: 'Invalid command input. Must be a non-empty string.', duration: Date.now() - startTime, }); } const child = spawn(cmd, args, { cwd: process.cwd() + '/' + 'output', shell: true, }); const timeout = input.timeout || 30000; const timer = setTimeout(() => { child.kill('SIGTERM'); resolve({ isError: true, data: 'Command timed out', duration: Date.now() - startTime, }); }, timeout); // Collect stdout child.stdout.on('data', (data) => { output += data.toString(); }); // Collect stderr child.stderr.on('data', (data) => { errorOutput += data.toString(); }); // On command completion child.on('close', (code) => { clearTimeout(timer); const result = { success: code === 0, data: (output || errorOutput || 'No output captured').replace(process.cwd() + '/output', ''), duration: Date.now() - startTime, }; // Cache result commandCache.set(cacheKey, { data: result.data, timestamp: startTime, success: result.success, }); resolve(result); }); // Catch errors with the subprocess child.on('error', (err) => { clearTimeout(timer); resolve({ isError: true, data: `Error executing command: ${err.message}`, duration: Date.now() - startTime, }); }); }).catch((err) => { console.error('Unexpected error:', err); return { isError: true, data: 'Unexpected error while executing the command', duration: Date.now() - startTime, }; }); }, }); }