UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

162 lines • 6.84 kB
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