@@ -21,6 +21,23 @@ import { getTextOutput, invalidArgText, str } from "./render-utils.ts";
|
||||
import { wrapToolDefinition } from "./tool-definition-wrapper.ts";
|
||||
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult } from "./truncate.ts";
|
||||
|
||||
const MAX_TIMEOUT_MS = 2_147_483_647;
|
||||
const MAX_TIMEOUT_SECONDS = MAX_TIMEOUT_MS / 1000;
|
||||
|
||||
function resolveTimeoutMs(timeout: number | undefined): number | undefined {
|
||||
if (timeout === undefined) return undefined;
|
||||
if (!Number.isFinite(timeout)) {
|
||||
throw new Error("Invalid timeout: must be a finite number of seconds");
|
||||
}
|
||||
if (timeout <= 0) return undefined;
|
||||
|
||||
const timeoutMs = timeout * 1000;
|
||||
if (timeoutMs > MAX_TIMEOUT_MS) {
|
||||
throw new Error(`Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`);
|
||||
}
|
||||
return timeoutMs;
|
||||
}
|
||||
|
||||
const bashSchema = Type.Object({
|
||||
command: Type.String({ description: "Bash command to execute" }),
|
||||
timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (optional, no default timeout)" })),
|
||||
@@ -66,15 +83,16 @@ export interface BashOperations {
|
||||
export function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {
|
||||
return {
|
||||
exec: async (command, cwd, { onData, signal, timeout, env }) => {
|
||||
const timeoutMs = resolveTimeoutMs(timeout);
|
||||
if (signal?.aborted) {
|
||||
throw new Error("aborted");
|
||||
}
|
||||
const shellConfig = getShellConfig(options?.shellPath);
|
||||
try {
|
||||
await fsAccess(cwd, constants.F_OK);
|
||||
} catch {
|
||||
throw new Error(`Working directory does not exist: ${cwd}\nCannot execute bash commands.`);
|
||||
}
|
||||
if (signal?.aborted) {
|
||||
throw new Error("aborted");
|
||||
}
|
||||
|
||||
const commandFromStdin = shellConfig.commandTransport === "stdin";
|
||||
const child = spawn(shellConfig.shell, commandFromStdin ? shellConfig.args : [...shellConfig.args, command], {
|
||||
@@ -97,11 +115,11 @@ export function createLocalBashOperations(options?: { shellPath?: string }): Bas
|
||||
|
||||
try {
|
||||
// Set timeout if provided.
|
||||
if (timeout !== undefined && timeout > 0) {
|
||||
if (timeoutMs !== undefined) {
|
||||
timeoutHandle = setTimeout(() => {
|
||||
timedOut = true;
|
||||
if (child.pid) killProcessTree(child.pid);
|
||||
}, timeout * 1000);
|
||||
}, timeoutMs);
|
||||
}
|
||||
// Stream stdout and stderr.
|
||||
child.stdout?.on("data", onData);
|
||||
|
||||
Reference in New Issue
Block a user