@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
96 lines • 4.62 kB
TypeScript
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