/**
 * Coarse I/O backends a tool may reach for.
 *
 * Tools never touch `node:fs` or `node:child_process` directly. Instead they
 * receive an {@link Fs} and a {@link Shell} through their {@link ToolContext},
 * and every real-world side effect flows through one of those two seams. Keeping
 * the surface intentionally small means a host can swap in a sandboxed, remote,
 * or in-memory implementation without any tool being aware of it.
 *
 * Only the interfaces live here. The concrete Node-backed implementations are
 * assembled in a later phase under `backends/`.
 */
/** Metadata about a single filesystem entry, as returned by {@link Fs.stat}. */
export interface FsEntryInfo {
    /** True when the entry is a regular file. */
    readonly isFile: boolean;
    /** True when the entry is a directory. */
    readonly isDirectory: boolean;
    /** True when the entry is a symbolic link. */
    readonly isSymlink: boolean;
    /** Size of the entry in bytes. */
    readonly size: number;
    /** Last-modified time, in epoch milliseconds. */
    readonly modifiedMs: number;
}
/** One child of a directory, as yielded by {@link Fs.readdir}. */
export interface DirChild {
    /** The bare entry name (no leading path). */
    readonly name: string;
    /** True when this child is itself a directory. */
    readonly isDirectory: boolean;
}
/** Options accepted by {@link Fs.rm}. */
export interface RemoveOptions {
    /** Remove directory trees, not just single files. Defaults to false. */
    readonly recursive?: boolean;
    /** Stay silent when the target is already absent. Defaults to false. */
    readonly ignoreMissing?: boolean;
}
/**
 * The filesystem capability handed to file-oriented tools.
 *
 * Paths are plain strings the caller has already resolved against the working
 * directory; the backend does no path interpretation of its own. Text reads and
 * writes go through {@link readFile} / {@link writeFile} with an explicit
 * encoding, while raw bytes are exchanged as a `Uint8Array` when encoding is
 * omitted.
 */
export interface Fs {
    /** Load a file's contents. With an encoding, returns text; without, raw bytes. */
    readFile(path: string, encoding: BufferEncoding): Promise<string>;
    readFile(path: string): Promise<Uint8Array>;
    /** Persist data to a file, creating it if absent and truncating if present. */
    writeFile(path: string, data: string | Uint8Array, encoding?: BufferEncoding): Promise<void>;
    /** Describe a single entry, following symlinks. Rejects when the path is absent. */
    stat(path: string): Promise<FsEntryInfo>;
    /** Enumerate the immediate children of a directory. */
    readdir(path: string): Promise<DirChild[]>;
    /** Create a directory, optionally building any missing parents. */
    mkdir(path: string, options?: {
        recursive?: boolean;
    }): Promise<void>;
    /** Delete a file or directory subtree per {@link RemoveOptions}. */
    rm(path: string, options?: RemoveOptions): Promise<void>;
    /** Report whether anything exists at the given path. */
    exists(path: string): Promise<boolean>;
}
/** Settings shared by both one-shot and long-lived shell launches. */
export interface ShellLaunchOptions {
    /** Working directory for the launched command. Defaults to the context cwd. */
    readonly cwd?: string;
    /** Environment overlay merged onto the inherited process environment. */
    readonly env?: Record<string, string>;
    /** Abort hook; firing it terminates the command. */
    readonly signal?: AbortSignal;
}
/** Extra knobs for a blocking {@link Shell.exec}. */
export interface ShellExecOptions extends ShellLaunchOptions {
    /** Hard deadline in milliseconds after which the command is killed. */
    readonly timeoutMs?: number;
    /** Bytes piped to the command's standard input before it runs. */
    readonly input?: string;
}
/** The settled result of a one-shot {@link Shell.exec}. */
export interface ShellExecResult {
    /** Everything the command emitted on standard output. */
    readonly stdout: string;
    /** Everything the command emitted on standard error. */
    readonly stderr: string;
    /** The process exit status; null when the command was signalled instead. */
    readonly code: number | null;
}
/** A live handle to a process started via {@link Shell.spawn}. */
export interface ShellHandle {
    /** The operating-system process id, once assigned. */
    readonly pid: number | undefined;
    /** Request termination of the process (and, where supported, its group). */
    kill(signal?: NodeJS.Signals): void;
    /**
     * Subscribe to the process finishing. The listener fires once with the exit
     * code (or null on signal) and the signal name if one ended it. Returns an
     * unsubscribe function.
     */
    onExit(listener: (code: number | null, signal: NodeJS.Signals | null) => void): () => void;
}
/**
 * The shell capability handed to command-running tools.
 *
 * {@link exec} is the blocking path used by the bulk of tools: it runs a command
 * to completion and resolves with its captured streams and status. {@link spawn}
 * is the background path used by the daemon/process tool: it hands back a live
 * {@link ShellHandle} the caller manages over time.
 */
export interface Shell {
    /** Run a command to completion, capturing its output. */
    exec(command: string, options?: ShellExecOptions): Promise<ShellExecResult>;
    /** Start a long-lived command and return a handle to manage it. */
    spawn(command: string, options?: ShellLaunchOptions): ShellHandle;
}
