import type { JsonValue } from '../types.ts';
import type { ProcessInfo, ProcessRunner } from './types.ts';
/**
 * Runs a runner as part of its execution, so what it records names it and
 * the runner it is. The workspace hands over the caller's binder: the
 * process layer sits below the session the caller carries, so it cannot
 * import it.
 */
export type ExecutionBind = <T>(executionId: string, run: () => Promise<T>, process: ProcessHandle) => Promise<T>;
/** Host-side runner lifecycle; cancellation and actual completion are separate.
 * A cancellation stands for a signal: a native program the runner started
 * receives it, and a cancelled runner's status is 128 plus it, as a shell
 * reports a child the signal ended. Joining covers the runner's finally
 * blocks, not untracked native descendants.
 * The runner starts once `start` is called, so whoever tracks the handle
 * registers it before even a synchronous prelude of the runner runs.
 */
export declare class ProcessHandle {
    private readonly run;
    private readonly cancel;
    private readonly finished;
    private readonly cancelChildren;
    private readonly bind;
    task: Promise<number>;
    /** Whether the runner has started running. */
    begun: boolean;
    private current;
    private stopSignal;
    private exitedCode;
    private readonly nativeRuns;
    private completion;
    constructor(info: ProcessInfo, run: ProcessRunner, cancel: (signal: number) => void, finished: (pid: number) => void, cancelChildren?: (signal: number) => void, bind?: ExecutionBind);
    /**
     * Start the runner.
     *
     * @param eager run it at once, up to its first wait, for a caller with
     *   nothing left to set up; otherwise it starts on the next microtask.
     *   Either way a runner that throws before it returns its promise fails
     *   as one whose promise rejects.
     */
    start(eager?: boolean): void;
    get info(): ProcessInfo;
    /** The signal the runner was stopped with, null while it runs. */
    get signal(): number | null;
    /** The status a program the runner started exited with on its own after the stop signal, null unless one did. */
    get programCode(): number | null;
    /**
     * The native runs this runner has going, each under a key of its own: a
     * host program it started, a sandbox's run.
     */
    get runs(): Record<string, Record<string, JsonValue>>;
    /**
     * Record a native run this runner started, which the process plane
     * publishes and a workspace that outlives this one stops.
     *
     * @param key the run's key, unique among the runner's.
     * @param run how another workspace reaches it.
     */
    addRun(key: string, run: Record<string, JsonValue>): void;
    /** Forget a native run once it ended, by the key it was recorded under. */
    dropRun(key: string): void;
    /**
     * Record that a program the runner started handled the stop signal and
     * exited: a job that is that one program reports its status, as bash
     * reports a child that handled the signal.
     *
     * @param code the program's exit status.
     */
    programExited(code: number): void;
    /**
     * Request cancellation without waiting for the runner to exit. A runner
     * that already exited has nothing to cancel, but what it started may
     * still run (`sh -c 'sleep 100 &'`), so its children are stopped all the
     * same. A KILL while the runner still stops under another signal cuts the
     * grace that signal gave its program short, as a second `kill -KILL` does.
     *
     * @param signal what the stop stands for, KILL (9) unless a `kill` named another.
     */
    terminate(signal?: number): boolean;
    private settle;
    join(): Promise<ProcessInfo>;
}
//# sourceMappingURL=handle.d.ts.map