import { type ChildProcess } from "node:child_process"; import { type ReadStream } from "node:fs"; import type { Dirent, Stats } from "node:fs"; /** * Largest file any tool will pull into memory at once. * * We run ONE shared Node daemon per app process (see CLAUDE.md), so an * unbounded `readFile` is not merely a slow read — it is every open window * dying together when a multi-GB artifact lands in the heap. 20 MiB sits far * above any source file (`read` itself only ever emits 50 KB of text) while * still admitting a large image before the shrink pass. */ export declare const MAX_READ_BYTES: number; /** The file exists but is too large to load; carries the numbers for the message. */ export declare class FileTooLargeError extends Error { readonly filePath: string; readonly size: number; readonly limit: number; constructor(filePath: string, size: number, limit: number); } /** The path resolved to something that is not a regular file (fifo, device, socket). */ export declare class NotRegularFileError extends Error { readonly filePath: string; constructor(filePath: string); } /** A symlink was found where a regular file was required. */ export declare class SymlinkRefusedError extends Error { readonly filePath: string; constructor(filePath: string); } /** * Read a whole file, refusing anything over `limit` bytes. * * Opens ONCE and judges the file from that same handle, so what we checked is * what we read. The alternative — `lstat()` the path, then `readFile()` the * path — inspects one file and reads whatever occupies the name a moment * later, which is exactly how a swapped symlink gets its target read. * * Three flags, three different holes: * - `O_NOFOLLOW` makes the kernel fail with ELOOP if the final component is a * symlink, so the refusal happens atomically at open rather than in a * separate syscall a caller could race. * - `O_NONBLOCK` stops the open itself parking forever on a fifo (a named pipe * called `x.png` would otherwise hang the tool call with no timeout); the * non-regular check then rejects it, and regular files ignore the flag. * - The size check bounds memory before a single byte is read. * * Windows defines neither flag (`?? 0` degrades to a plain read) and offers no * path-reachable fifo here; `resolvePath` plus the sandbox still contain it. */ export declare function readFileBounded(filePath: string, limit?: number): Promise; /** * Abstraction over filesystem and process operations. * Default implementation uses local Node.js APIs. * Replace with SSH/Docker/cloud implementations for remote execution. */ export interface ToolOperations { /** Read a file's contents as UTF-8 string. */ readFile(path: string): Promise; /** Write content to a file. Creates parent directories if needed. */ writeFile(path: string, content: string): Promise; /** Get file/directory stats. */ stat(path: string): Promise; /** Check if a path is a symbolic link. */ lstat(path: string): Promise; /** Read directory contents with file type info. */ readdir(path: string, options: { withFileTypes: true; }): Promise; /** Create a directory (recursive). */ mkdir(path: string): Promise; /** Create a readable stream for a file. */ createReadStream(path: string, encoding: BufferEncoding): ReadStream; /** Spawn a child process. Returns the ChildProcess handle. */ spawn(command: string, args: string[], options: { cwd: string; env?: Record; detached?: boolean; stdio?: Array<"pipe" | "ignore">; }): ChildProcess; } /** * Default local filesystem + process operations. * This is what tools use when running on the local machine. */ export declare const localOperations: ToolOperations; //# sourceMappingURL=operations.d.ts.map