@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
162 lines • 6.84 kB
TypeScript
import type { Context } from '../../../commands/config.ts';
import { PythonRuntime } from '../base.ts';
import type { OutputFn, Program, RunResult, RuntimeReach } from '../../types.ts';
import { type RuntimeOptions } from '../../config.ts';
import type { SyncVFS } from './fs/types.ts';
import { type PyodideConfig } from './config.ts';
/**
* Rewrite top-level imports of denied packages so Pyodide's
* `loadPackagesFromImports` skips fetching them. The rewritten code is only
* fed to the auto-loader's import scanner — user code still runs unchanged,
* so the actual `import X` will hit any meta_path blocker installed in the
* Python bootstrap.
*
* Recognises:
* - `import X`, `import X.Y`, `import X as alias`
* - `from X import …`, `from X.Y import …`
* The match is line-scoped (`/m`) so multi-import lines like
* `import X, Y` are blanked out as a single statement.
*/
export declare function stripDeniedImports(code: string, denyPackages: ReadonlySet<string>): string;
export declare class PyodideRuntime extends PythonRuntime<undefined> {
private readonly sync?;
private readonly interruptBuffer?;
readonly name = "pyodide";
protected readonly versionSuffix = " (pyodide)";
readonly reach: RuntimeReach;
readonly filesystem: readonly ["read", "write", "list", "stat", "glob"];
private pyodide;
private guest;
private initPromise;
private bootstrapPromise;
private disposeModule;
private queue;
private pending;
private readonly limiter;
private readonly autoLoadFromImports;
private readonly bootstrapCode;
private readonly denyPackages;
private readonly home;
private readonly sysPath;
private readonly packages;
private readonly packageBaseUrl;
private readonly lockFileUrl;
private files;
private readonly journal;
private readonly deferred;
private readonly streams;
private readonly mounted;
private readonly madeDirs;
private readonly mountedFilesystems;
private readonly refused;
private readonly seedMissesReported;
private seedNotices;
private interrupter;
private interrupterTried;
private worker;
private readonly maxMemory;
private readonly syncFailures;
private syncSkipped;
private realmSeal;
constructor(options?: RuntimeOptions<PyodideConfig>, sync?: SyncVFS | undefined, interruptBuffer?: SharedArrayBuffer | undefined);
/**
* Run one program on a fresh interpreter: in the worker for a run with
* files, in process for one without. In the worker the guest reads its
* input as it comes and its writes go to `output` and `errors` as it
* makes them; in process it reads its input whole and its output comes
* back in the result.
*
* @param _engine none; each run builds its own interpreter.
* @param program the source and argv to run.
* @param ctx the run's context.
* @param output receives stdout as the guest writes it.
* @param errors the same for stderr.
*/
interpret(_engine: undefined, program: Program, ctx: Context, output?: OutputFn, errors?: OutputFn): Promise<RunResult>;
private schedule;
private enqueue;
private withPermit;
/**
* The MemoryError for an interpreter whose heap is past `maxMemory`, null
* while it is within it. The heap never shrinks, so its size when a run
* ends is the most the run used, however fast it was. A run in the worker
* is checked there, and on Node the worker is also watched while it runs
* (`watchMemory`).
*/
private passedCap;
/** A run's result, or a MemoryError when the run passed `maxMemory`. */
private capped;
private createRuntime;
private withFreshRuntime;
close(): Promise<void>;
private closeOne;
private closeInterpreter;
private wireInterruptIfNeeded;
private guardRequestedPaths;
private ensureLoaded;
/**
* Seal the Node worker the guest runs in, once the interpreter and any
* trusted init have loaded. Only inside the worker (`sync` set): the main
* thread runs no workspace-backed guest, and a browser worker shares the
* page, whose CSP is its only limit. An `init_module` has host reach by
* design (`'process'`), so its worker is left open; so is a Node too old
* for `module.registerHooks`, documented as trusted-only there.
*
* @param pyodide The loaded interpreter.
*/
private sealRealmIfWorker;
/**
* One request on the worker. A run that passes `maxMemory` takes the
* worker with it (`watchMemory`), so the next run starts a fresh one.
*/
private onWorker;
private ensureWorker;
/**
* Rebuild mount nodes before each run so cached bytes never survive a
* session change. The worker populates nodes on lookup and open, so
* only a worker mounts anything; a bound run with no worker is refused
* before it gets here (`noWorker`). Removed mounts disappear, and nested
* mounts share their parent's Emscripten mountpoint while retaining
* workspace routing boundaries.
*/
private syncMounts;
/**
* Put the configured paths on sys.path, after every mount is in place.
*
* Runs on EVERY syncMounts pass rather than once at load: each pass
* unmounts and remounts the prefixes, and zipimport caches an
* archive's table of contents by path, so a `.whl` served from a
* remounted tree would keep answering from the previous run. Both
* guards inside are idempotent, so repeating is cheap.
*
* Args:
* pyodide: the loaded interpreter.
*/
private seedSysPath;
private guestProcess;
private guestModule;
/**
* The guest's extended-attribute calls (its os.getxattr family, which
* the harness installs over this module), answered by the workspace
* dispatcher and handed back as JSON: `{value}`, or `{code}` naming the
* condition the dispatcher reported. Only the worker can wait on the dispatcher
* from inside a WASM frame, so without one, and for a path no mount
* serves, the answer is ENOTSUP: what a filesystem without extended
* attributes says.
*/
private guestXattr;
private takeSeedNotices;
/**
* Land what the run left open and replay every mutation the shim
* recorded during it, in the order the guest performed them. The guest
* cannot await the bridge from its sync WASM frames without JSPI, so it
* only records; ordering is what makes a create-then-rename or
* mkdir-then-write sequence land the same way it ran. Returns one
* message per failure for the caller's stderr.
*/
private drainMutations;
private loadImports;
private runOne;
private guestCwd;
}
//# sourceMappingURL=runtime.d.ts.map