import type { CommandFnResult } from '../../../commands/config.ts';
import { type ByteSource, type CommandOutput } from '../../../io/types.ts';
import type { PathSpec, Producer } from '../../../types.ts';
import { type Files } from '../../files.ts';
/**
 * What a voice says for one failure: the bytes the handler printed before
 * it, the diagnostic line and the exit code.
 */
type Failure = [ByteSource | null, Uint8Array, number];
/**
 * How a caller words a handler that failed, before it answered or while its
 * output streamed. The runner is one for a mount command and a CLI leaf; the
 * wording is the caller's, and stays what each said before the two shared
 * it. Mirrors Python's `HandlerVoice`.
 */
export interface HandlerVoice {
    /** The failure as this caller words it. */
    fail(err: unknown): Failure;
    /**
     * Whether a failure is not the command's to word and reaches the
     * workspace instead (a limit timeout answers 124 there).
     */
    passes(err: unknown): boolean;
    /**
     * Whether output is pulled through `chunks`, which splits even a single
     * blob, so an answer in bytes streams too.
     */
    splits: boolean;
}
export interface RunHandlerOpts {
    /**
     * Drops the caches a write past the dispatcher leaves stale; absent when
     * the handler writes nothing or only through the dispatcher.
     */
    drop?: () => Promise<void>;
    /**
     * What the caller wraps an answer in before it is framed (a mount binds
     * its recorder and activity to the stream).
     */
    scope?: (result: CommandOutput) => CommandOutput;
    /** The caller's abort, which stops waiting for the body. */
    signal?: AbortSignal;
    /**
     * Called once the answer, its rows rendered, has settled, however the
     * caller left: a handler and its renderer may run past an abort, so a
     * caller keeps what they use (a CLI's client) until then.
     */
    settle?: () => void;
    /**
     * The handler's files, whose session's hides filter the rows it hands
     * over; absent filters none.
     */
    vfs?: Files | null;
}
/**
 * What a command given a glob past its mount's `walkLimit` says: exec(2)'s
 * refusal of an argument list too long, which bash reports with exit 126, then
 * the limit's own line. Mirrors Python's `argument_list_too_long`.
 */
export declare function argumentListTooLong(command: string, reason: string): Uint8Array;
/** The voice of a command a mount runs; `paths` are the operands as typed. */
export declare function mountVoice(name: string, paths: readonly PathSpec[]): HandlerVoice;
/** The voice of a CLI leaf, installed or on a mount. */
export declare function cliVoice(prog: string): HandlerVoice;
/**
 * A leaf's answer, an empty one where it returned null. A mount command's
 * null declines, so its mount tries the next handler; a leaf's null is its
 * whole answer, an empty one. Mirrors Python's `answered`.
 */
export declare function answered(body: Promise<CommandFnResult>): Promise<CommandOutput>;
/**
 * Run one handler body: a mount command's, or a CLI leaf's.
 *
 * The body runs until it answers or the caller's signal aborts (the line's
 * deadline among the reasons). Racing a promise does not stop its work, so
 * output the body hands back after its caller left is closed.
 * A usage error is the handler's own words and exit code; any other failure
 * is worded in the caller's voice, so the rest of the line keeps running. A
 * handler that may have written past the dispatcher drops caches afterwards,
 * whether it answered, failed (in its own words too), timed out or was
 * cancelled, again when a body (or the renderer of the rows it handed over)
 * still running past its abort settles, since its write may land then, and
 * again once an answer that streams has ended or
 * been closed, since a stream does its work as it is pulled. An answer
 * carries the producer the output limits resolve from and
 * has its stream framed so a failure while it streams is worded too; a
 * failure the runner framed carries no producer. Null is the handler
 * declining, which a mount's cascade reads as "try the next handler".
 * Rows a handler hands over in place of stdout (`IOResult.rows`) lose those
 * the session cannot see and are rendered here, inside the run, so this
 * is the one place a command's output meets the session's hides.
 * Mirrors Python's `run_handler`.
 */
export declare function runHandler(body: Promise<CommandFnResult>, name: string, producer: Producer, voice: HandlerVoice, opts?: RunHandlerOpts): Promise<CommandFnResult>;
export {};
//# sourceMappingURL=handler.d.ts.map