import type { Context } from '../commands/config.ts';
import type { PathSpec } from '../types.ts';
import { type WorkspaceBinding } from './binding.ts';
import { type RuntimeConfig, type RuntimeOptions } from './config.ts';
import type { ExecutionKind, FilesystemOperation, OutputFn, RunResult, RuntimeReach } from './types.ts';
/**
 * An engine the workspace can route commands or whole lines to.
 *
 * A runtime is to its commands what the regex engine is to grep: the
 * machinery inside a handler, invisible to the dispatcher. Each runtime
 * declares the command names it captures; a command binds to the first
 * runtime in the workspace's ordered list that captures it. Its hooks take
 * what a handler takes, `(engine, paths, texts, ctx)`: the engine (`E`) is
 * built once by `openEngine`; a runtime with none declares
 * `Runtime<undefined>`.
 *
 * The base holds only what every tier shares: the registry name, the
 * captured command names, the coerced config and the engine. What a
 * runtime can DO is declared by its tier and mixins, detected by type and
 * never by probing: LanguageRuntime interprets code in its language
 * (run), LineExecutorMixin takes whole lines (runLine), ProcessExecutorMixin runs
 * an argv (runProcess).
 *
 * Every runtime is constructed the same way (captures, config); each
 * subclass hands the base its class-default captures and its config key
 * list, so a config field the runtime does not have fails loud
 * (config_cls in Python).
 */
export declare abstract class Runtime<E = unknown> {
    abstract readonly name: string;
    readonly captures: readonly string[];
    /**
     * Which entry points this runtime's code has to the outside world (see
     * RuntimeReach): 'workspace' when the workspace dispatch is its only one,
     * as the bridged engines (monty, pyodide, quickjs) and the workspace
     * routing marker declare, 'process' or 'remote' when the code can
     * act around that gate. The default is 'process', the no-promise
     * claim, so a custom runtime must declare a narrower reach
     * explicitly rather than inherit it. Embedders read the aggregate:
     * only a world in which every runtime reaches 'workspace' makes "agent
     * code cannot bypass mount modes and policy" a true statement,
     * which is what the dsh adapter's sandbox claim is built from; one
     * wider runtime voids it.
     */
    readonly reach: RuntimeReach;
    readonly filesystem: readonly FilesystemOperation[];
    /** The runtime's coerced implementation knobs. */
    config: RuntimeConfig;
    protected binding: WorkspaceBinding | null;
    private readonly activity;
    private retired;
    private opening;
    private closing;
    constructor(options?: RuntimeOptions<RuntimeConfig>, defaultCaptures?: readonly string[], configKeys?: readonly string[]);
    /** Whether workspace file mutations already invalidate through dispatch. */
    get fileEffectsDispatched(): boolean;
    /**
     * Land the file writes this runtime still holds for a line. The executor
     * calls it when a line ends, however it ended, so the line's writes are
     * in the workspace by the time it returns. Holds none by default; a
     * sandbox serving the workspace over SFTP lands what its servers hold.
     */
    settle(): Promise<void>;
    /** Attach workspace services; a runtime instance belongs to one workspace. */
    bind(binding: WorkspaceBinding): void;
    /**
     * Run once, as the session the bound workspace captures. The capture
     * supplies the files (`ctx.vfs`, judged as the program's own calls) and
     * the session; the caller's `ctx` the rest.
     *
     * @param paths the path operands (a script).
     * @param texts the text operands (argv; a process's program first).
     * @param ctx the run's context.
     * @param opts `kind`: code in the runtime's language (the default), a
     *   whole line (`sh -c` with `ctx.flags.c`), or a process; `output`:
     *   where the run writes its output as it comes, absent to collect it in
     *   the result; `errors`: the same for its stderr.
     */
    execute(paths: readonly PathSpec[], texts: readonly string[], ctx: Context, opts?: {
        kind?: ExecutionKind;
        output?: OutputFn;
        errors?: OutputFn;
    }): Promise<RunResult>;
    /** Hand the run to the capability its kind asks for. */
    private runAs;
    /**
     * Run code in this runtime's language; only a language runtime has one.
     *
     * @param _engine the install's engine.
     * @param _paths the script operand, if any.
     * @param _texts the program's argv.
     * @param _ctx the run's context.
     * @param _output receives stdout as it comes; undefined returns it in
     *   the result.
     * @param _errors the same for stderr.
     */
    run(_engine: E, _paths: PathSpec[], _texts: string[], _ctx: Context, _output?: OutputFn, _errors?: OutputFn): Promise<RunResult>;
    /** Build the engine every run reuses, once; the default is none. */
    protected openEngine(): Promise<E>;
    /**
     * Release what `openEngine` built.
     *
     * @param _engine the engine.
     */
    protected closeEngine(_engine: E): Promise<void>;
    /** The engine, opened once and shared; a failed open is retried. */
    engine(): Promise<E>;
    /**
     * Whether every restricted mount is served through this caller's gate.
     *
     * @param _restrictedMounts the mounts the session restricts.
     */
    protected servesSession(_restrictedMounts: readonly string[]): boolean;
    /** Count one unit of work, refused once the runtime is retired. */
    admit(): () => void;
    /** Refuse new executions and binds, then wait for running ones. */
    retire(): Promise<void>;
    /**
     * Close the engine, when one was opened. A close that comes while another
     * runs waits for that one rather than finding nothing left to close.
     */
    close(): Promise<void>;
    private dropEngine;
}
/** A workspace runtimes-list entry: an instance or a name shorthand. */
export type RuntimeEntry = Runtime | string;
//# sourceMappingURL=base.d.ts.map