import { PythonRuntime } from './base.ts';
import { EVALUATOR, type Evaluator } from '../mixin.ts';
import type { EvalResult, EvalValue, RunArgs, RunResult, RuntimeOptions } from '../types.ts';
import { type MountResolver } from '../resolver.ts';
import type { BridgeDispatchFn } from '../types.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;
/** The pyodide runtime's implementation knobs (its `config` block). */
export interface PyodideConfig {
    autoLoadFromImports?: boolean;
    bootstrapCode?: string;
    denyPackages?: readonly string[];
    /**
     * Virtual paths prepended to sys.path once the mounts are in place, so
     * an agent can `import openpyxl` without writing sys.path.append
     * itself. Entries are MOUNT paths, not host paths: the glob runs
     * inside the interpreter against the mounted tree. A `.whl` may be
     * named directly (zipimport reads a pure-python wheel in place), and a
     * pattern may contain `*`, `?` or `[`.
     *
     * Prepended, not appended: a vendored package of the same name must
     * win over a bundled one, which is also CPython's own PYTHONPATH
     * precedence.
     */
    sysPath?: readonly string[];
    /**
     * Packages loaded once at init from the pyodide distribution, before
     * the first run. Composes with autoLoadFromImports rather than
     * replacing it: the per-run import scan is a no-op for anything
     * already resident.
     */
    packages?: readonly string[];
    /**
     * Where package wheels are fetched from. Distinct from `home`, which
     * only sets indexURL: the npm pyodide package ships the lock file and
     * NO wheels, so a deployment that wants `packages` working offline
     * points this at its own prebuilt distribution. A `://` value makes
     * package loading a network fetch; a local path keeps it on disk.
     */
    packageBaseUrl?: string;
    /** A custom pyodide-lock.json, for a prebuilt distribution. */
    lockFileURL?: string;
    home?: string;
}
export declare class PyodideRuntime extends PythonRuntime implements Evaluator {
    readonly name = "pyodide";
    readonly reach = "vfs";
    readonly [EVALUATOR]: true;
    private pyodide;
    private initPromise;
    private bootstrapPromise;
    private queue;
    private readonly autoLoadFromImports;
    private readonly bootstrapCode;
    private workspaceBridge;
    private readonly denyPackages;
    private resolver;
    private readonly home;
    private readonly sysPath;
    private readonly packages;
    private readonly packageBaseUrl;
    private readonly lockFileURL;
    private vfs;
    private readonly journal;
    private readonly mounted;
    private readonly refused;
    private readonly seedMissesReported;
    private seedNotices;
    private interrupter;
    private interrupterTried;
    constructor(options?: RuntimeOptions<PyodideConfig>);
    attach(dispatch: BridgeDispatchFn, resolver: MountResolver): void;
    run(args: RunArgs): Promise<RunResult>;
    /**
     * Evaluate code; the last expression is the value. One-shot mode
     * runs on the eval wrapper (value crosses the WASM boundary as
     * JSON); a session id routes through the console wrapper (globals
     * persist per id, value is streamed output only). Console failures
     * come back as transcript results; one-shot failures reject with
     * EvalError.
     */
    eval(code: string, opts?: {
        inputs?: Record<string, EvalValue>;
        session?: string;
    }): Promise<EvalResult>;
    private evalOne;
    close(): Promise<void>;
    private wireInterruptIfNeeded;
    private ensureLoaded;
    private wireBridgeIfNeeded;
    /**
     * Rebuild the guest's mount table from the workspace's, before every
     * run.
     *
     * Every prefix is re-seeded, not just a newly added one, because the
     * filesystem's callbacks are synchronous and so this is the only place
     * that can await the bridge at all. A stale snapshot is not merely a
     * missed read: a file the snapshot lacks looks like a new file, so
     * `open(path, 'a')` would start from an empty buffer and the flush
     * would replace content the guest never saw. Re-seeding is what keeps
     * that impossible without JSPI, which no shipping Node has and Safari
     * does not implement.
     *
     * The cost is one readdir plus one read per file per run. Narrowing that
     * to what actually changed needs a per-entry change stamp the bridge
     * does not carry yet; until it does, correctness is the side to err on.
     *
     * A prefix the workspace has dropped is unmounted, so a removed mount
     * stops being visible instead of lingering for the interpreter's life.
     */
    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;
    /**
     * Queue a notice for each glob that expanded to nothing this pass.
     *
     * The seed cannot report these itself: it runs inside syncMounts,
     * before the run's stdout/stderr are captured, so anything it wrote
     * to sys.stderr reached nobody. Queuing here and draining onto the
     * run's stderr puts the warning in front of the same agent whose
     * import is about to fail.
     *
     * Args:
     *   pyodide: the loaded interpreter, holding the seed's `_seed_misses`.
     */
    private recordSeedMisses;
    private takeSeedNotices;
    /**
     * Replay every mutation the shim recorded during the run, 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 runOneRepl;
}
//# sourceMappingURL=pyodide.d.ts.map