import type { ToolResult } from "../types.js"; export interface ShellExecArgs { command: string; cwd?: string | undefined; timeoutMs?: number | undefined; signal?: AbortSignal | undefined; onOutput?: ((chunk: string, stream: "stdout" | "stderr") => void) | undefined; /** Max bytes of output to retain in memory for the model (head+tail). */ maxModelBytes?: number | undefined; /** Max bytes streamed to the artifact file before the child is terminated. */ maxCaptureBytes?: number | undefined; /** Behavior when maxCaptureBytes is exceeded. Defaults to "terminate". */ onLimit?: "terminate" | "continue" | undefined; /** Where to save the raw artifact. When undefined, the active session temp dir (or ~/.clai/outputs) is used. */ artifactPath?: string | undefined; /** When true, do not allocate an artifact file (used by tests / dry runs). */ noArtifact?: boolean | undefined; /** * Force the child to inherit the parent's stdin so interactive * password prompts (sudo, ssh, gpg, doas) can read from the controlling * TTY. Defaults to `auto`: enabled for commands {@link looksInteractiveStdin} * detects when stdin is a TTY; disabled otherwise. Set explicitly to * `true` to force-inherit, `false` to keep stdin closed. */ interactiveStdin?: boolean | "auto" | undefined; } export interface SpawnArgvArgs { command: string; argv: string[]; cwd?: string | undefined; timeoutMs?: number | undefined; signal?: AbortSignal | undefined; onOutput?: ((chunk: string, stream: "stdout" | "stderr") => void) | undefined; maxModelBytes?: number | undefined; maxCaptureBytes?: number | undefined; onLimit?: "terminate" | "continue" | undefined; artifactPath?: string | undefined; noArtifact?: boolean | undefined; /** Sensitive stdin payload written directly to the child and never logged. */ stdinText?: string | undefined; /** See {@link ShellExecArgs.interactiveStdin}. */ interactiveStdin?: boolean | "auto" | undefined; } /** Prefer the platform default shell, but tolerate minimal sandboxes that omit it. */ export declare function resolveShell(): string | undefined; /** Disable/enable TTY stdin inheritance for password prompts. */ export declare function setAllowInteractiveStdinInherit(allow: boolean): void; export declare function getAllowInteractiveStdinInherit(): boolean; export type InteractiveStdinKind = "elevate" | "tty"; export declare function interactiveStdinKind(command: string): InteractiveStdinKind | undefined; export declare function looksInteractiveStdin(command: string): boolean; /** * Streaming UTF-8 decoder with byte accounting and a binary sniff. * * `chunk.toString()` per chunk splits multi-byte characters at buffer * boundaries (mojibake in nmap banners, i18n build logs, unicode filenames), * and `text.length` counts UTF-16 code units, so every byte cap was wrong for * non-ASCII output. Binary output is detected once and reported so the model * gets a marker instead of lossy text. * Exported only for tests. */ export declare class OutputDecoder { private readonly decoder; private sniffed; private nonPrintable; private binaryDetected; decode(chunk: Buffer): { text: string; bytes: number; }; end(): string; get isBinary(): boolean; private sniff; } /** A small ring buffer of recent output lines used as the "tail" summary. * Exported only for tests. */ export declare class RingBuffer { private readonly capacity; private chunks; private bytes; constructor(capacity: number); push(text: string): void; toString(): string; size(): number; } /** * Run a foreground shell command. A launch-level ENOENT can be transient on * macOS even when /bin/sh and cwd both exist. Because the child never started, * one runtime-owned retry is safe and avoids teaching the model to mutate the * command repeatedly. Command failures after a successful spawn are never * retried here. */ export declare function shellExec(args: ShellExecArgs): Promise; /** * Run a child process with `shell: false`, passing argv directly. Use this * for any tool that builds command lines from model-provided strings (eg * `net.scan`, `pentest.recon`, `pkg.install`). Sharing argv with the OS * shell would let a malicious target turn into "; rm -rf /" — `shell: false` * + argv prevents that even if the model is adversarial. * * The capture pipeline (head + ring-tail + artifact + cap-and-kill + stats) * is identical to shellExec. */ export declare function spawnArgv(args: SpawnArgvArgs): Promise;