UNPKG

@agentforce/adk

Version:

AgentForce Agent Development Kit - A powerful framework for building AI agents and servers

145 lines (131 loc) 4.84 kB
import { exec } from "child_process"; import { promisify } from "util"; const execAsync = promisify(exec); /** * Configuration options for command execution * @interface ExecOptions * @property {string} [cwd] - Working directory for command execution * @property {number} [timeout] - Timeout in milliseconds * @property {Record<string, string>} [env] - Environment variables * @property {string | boolean} [shell] - Shell to use for execution * @property {BufferEncoding} [encoding] - Text encoding for output * @property {number} [maxBuffer] - Maximum buffer size for output */ export interface ExecOptions { cwd?: string; timeout?: number; env?: Record<string, string>; shell?: string | boolean; encoding?: BufferEncoding; maxBuffer?: number; } /** * Result of command execution * @interface ExecResult * @property {boolean} success - Whether command executed successfully * @property {string} stdout - Standard output from command * @property {string} stderr - Standard error from command * @property {number | null} exitCode - Exit code of the command * @property {string} command - The executed command * @property {string} [error] - Error message if execution failed */ export interface ExecResult { success: boolean; stdout: string; stderr: string; exitCode: number | null; command: string; error?: string; } /** * Execute a shell command asynchronously * @param command The command to execute * @param options Execution options * @returns Promise with execution result */ export async function executeCommand(command: string, options: ExecOptions = {}): Promise<ExecResult> { const { cwd = process.cwd(), timeout = 30000, // 30 seconds default timeout env = process.env, encoding = "utf8", maxBuffer = 1024 * 1024 * 10, // 10MB default buffer } = options; try { const { stdout, stderr } = await execAsync(command, { cwd, timeout, env: { ...env }, encoding, maxBuffer, }); return { success: true, stdout: stdout.toString().trim(), stderr: stderr.toString().trim(), exitCode: 0, command, }; } catch (error: any) { return { success: false, stdout: error.stdout ? error.stdout.toString().trim() : "", stderr: error.stderr ? error.stderr.toString().trim() : "", exitCode: error.code || -1, command, error: error.message || "Unknown error occurred", }; } } /** * Check if a command/program is available in the system PATH * @param command The command to check * @returns Promise<boolean> indicating if command is available */ export async function isCommandAvailable(command: string): Promise<boolean> { const checkCommand = process.platform === "win32" ? `where ${command}` : `which ${command}`; const result = await executeCommand(checkCommand, { timeout: 5000 }); return result.success && result.stdout.length > 0; } /** * Execute GitHub CLI command with proper error handling * @param ghArgs Array of arguments for gh command * @param options Execution options * @returns Promise with execution result */ export async function executeGitHubCLI(ghArgs: string[], options: ExecOptions = {}): Promise<ExecResult> { // Check if gh is available const isGhAvailable = await isCommandAvailable("gh"); if (!isGhAvailable) { return { success: false, stdout: "", stderr: "", exitCode: -1, command: `gh ${ghArgs.join(" ")}`, error: "GitHub CLI (gh) is not installed or not available in PATH", }; } // Build the gh command const command = `gh ${ghArgs.join(" ")}`; // Execute with enhanced timeout for GitHub API calls const enhancedOptions: ExecOptions = { timeout: 60000, // 60 seconds for GitHub API calls ...options, }; const result = await executeCommand(command, enhancedOptions); // Enhanced error handling for GitHub CLI specific errors if (!result.success) { // Check for common gh authentication errors if (result.stderr.includes("authentication") || result.stderr.includes("login")) { result.error = "GitHub CLI authentication required. Run 'gh auth login' to authenticate."; } else if (result.stderr.includes("rate limit")) { result.error = "GitHub API rate limit exceeded. Please try again later."; } else if (result.stderr.includes("not found")) { result.error = "Repository or resource not found. Check permissions and repository name."; } } return result; }