UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

127 lines • 6.1 kB
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