import { V as Vfs, C as Cred, f as RuntimePod, O as OutboundPolicy, D as DirEntry, p as Stats } from './contracts-BHo4LdY2.js'; /** * Byte streams for stdin/stdout/stderr, pipelines and redirections. * * Everything here is promise-based rather than Node-stream based: commands are * plain async functions, a pipeline is just a chain of `Pipe` objects, and a * closed reader turns further writes into `EPIPE` the way a real pipe does. */ interface OutputStream { write(data: Uint8Array | string): void; end(): void; /** True once the far end went away — producers should stop. */ readonly closed: boolean; isTTY: boolean; /** Terminal width, when this is a TTY. */ columns?: number; rows?: number; } interface InputStream { /** Resolves to null at EOF. `size` is a maximum, not a guarantee. */ read(size?: number): Promise; readAll(): Promise; /** One line without its terminator; null at EOF. */ readLine(): Promise; /** Bytes already buffered, for non-blocking peeks. */ readonly available: number; close(): void; isTTY: boolean; /** * True when the far end is a live caller who may never signal EOF — a * terminal, or the `stdin` pipe of `Container.spawn`. Programs that would * otherwise slurp stdin before starting must not block on these. */ readonly interactive?: boolean; } interface Stdio { stdin: InputStream; stdout: OutputStream; stderr: OutputStream; } /** An in-memory pipe: writable on one end, readable on the other. */ declare class Pipe implements InputStream, OutputStream { private chunks; private buffered; private writerClosed; private readerClosed; private wakers; isTTY: boolean; /** Set on pipes owned by an outside caller, who may never call `end()`. */ interactive: boolean; /** * Set while the running program has put the terminal in raw mode. * * A program in raw mode draws its own input — a prompt library redraws the * whole line on every keystroke — so the terminal must stop echoing, or * every character appears twice. */ private raw; /** * Translate carriage returns on the way in, the way `ICRNL` does. * * A terminal sends CR when Enter is pressed — xterm and every browser * terminal emulator do — while everything that reads a line looks for LF. * A real tty reconciles the two in its line discipline, which is on by * default; without it `read name` waits forever on input the user already * typed, and the only visible symptom is a hang. * * Deliberately opt-in rather than implied by `isTTY`, because stdout is a * tty too and a bare CR there is how every progress bar and menu redraw * returns to the start of the line. Translating those would corrupt exactly * the output this runtime exists to render faithfully. */ icrnl: boolean; onRawMode?: (enabled: boolean) => void; get rawMode(): boolean; set rawMode(enabled: boolean); columns: number | undefined; rows: number | undefined; get closed(): boolean; get ended(): boolean; get available(): number; write(data: Uint8Array | string): void; end(): void; close(): void; private wake; private waitForData; read(size?: number): Promise; readAll(): Promise; private lineRemainder; readLine(): Promise; /** Seed the pipe with content then close it — handy for here-docs. */ static from(data: Uint8Array | string): Pipe; static empty(): Pipe; } /** Discards everything; `/dev/null` as an output stream. */ declare class NullOutput implements OutputStream { readonly closed = false; isTTY: boolean; write(): void; end(): void; } /** Always at EOF; `/dev/null` as an input stream. */ declare class NullInput implements InputStream { readonly available = 0; isTTY: boolean; read(): Promise; readAll(): Promise; readLine(): Promise; close(): void; } /** Collects everything written, for `exec()` and command substitution. */ declare class BufferSink implements OutputStream { private readonly onWrite?; private chunks; private total; private _closed; isTTY: boolean; columns: number | undefined; rows: number | undefined; constructor(onWrite?: ((chunk: Uint8Array) => void) | undefined); get closed(): boolean; write(data: Uint8Array | string): void; end(): void; bytes(): Uint8Array; text(): string; get length(): number; reset(): void; } /** Forwards each write to a callback — used to stream into a terminal. */ declare class CallbackSink implements OutputStream { private readonly sink; private _closed; isTTY: boolean; columns: number | undefined; rows: number | undefined; constructor(sink: (text: string) => void, opts?: { isTTY?: boolean; columns?: number; rows?: number; }); get closed(): boolean; write(data: Uint8Array | string): void; end(): void; } /** Fan-out, for `tee` and for `2>&1`-style duplication. */ declare class TeeOutput implements OutputStream { private readonly targets; constructor(targets: OutputStream[]); get closed(): boolean; isTTY: boolean; write(data: Uint8Array | string): void; end(): void; } /** * Writes into a VFS file. Buffers in memory and flushes on every write so a * long-running redirect (`cmd > log &`) is observable while it runs. */ declare class FileOutput implements OutputStream { private readonly vfs; private readonly path; private readonly opts; private _closed; isTTY: boolean; constructor(vfs: Vfs, path: string, opts?: { append?: boolean; cred?: Cred; mode?: number; }); get closed(): boolean; write(data: Uint8Array | string): void; end(): void; } /** Reads a VFS file as an input stream, for `cmd < file`. */ declare class FileInput implements InputStream { private pipe; isTTY: boolean; constructor(vfs: Vfs, path: string, cred?: Cred); get available(): number; read(size?: number): Promise; readAll(): Promise; readLine(): Promise; close(): void; } /** Convenience factory for a fully buffered stdio triple. */ declare function captureStdio(stdin?: Uint8Array | string): { stdio: Stdio; out: BufferSink; err: BufferSink; }; /** * The process table. * * Processes here are cooperative JavaScript tasks, not OS processes, but they * carry the state Linux tooling expects to see: pid/ppid/pgid/sid, a state * letter, credentials, a cwd, an environment, and an exit status that encodes * the killing signal. `ps`, `kill`, `jobs` and `/proc` all read from here. */ type ProcessState = "R" | "S" | "D" | "T" | "Z" | "X"; type Env = Record; interface ProcessOptions { argv: string[]; cwd: string; env: Env; cred: Cred; ppid?: number; pgid?: number; sid?: number; stdio?: Partial; /** Descriptors above 2, readable and writable from this process's side. */ fds?: Record; tty?: string | null; /** Marks the process as a shell builtin frame rather than a real command. */ kind?: ProcessKind; } type ProcessKind = "init" | "shell" | "builtin" | "command" | "node" | "python" | "script"; declare class Process { readonly pid: number; ppid: number; pgid: number; sid: number; argv: string[]; cwd: string; env: Env; cred: Cred; kind: ProcessKind; tty: string | null; state: ProcessState; exitCode: number | null; /** Signal that terminated the process, if any. */ termSignal: string | null; readonly startTime: number; cpuMs: number; stdin: InputStream; stdout: OutputStream; stderr: OutputStream; /** Descriptors above 2 the parent handed over, such as Chromium's fds 3 and 4. */ readonly fds: Map; readonly children: Set; private readonly aborter; private readonly exitWaiters; private readonly signalHandlers; constructor(opts: ProcessOptions); /** Basename of argv[0], the `comm` field in `ps`. */ get comm(): string; get cmdline(): string; get running(): boolean; get signal(): AbortSignal; /** Seconds since the process started, for `ps etime`. */ get elapsedMs(): number; setStdio(stdio: Partial): void; onSignal(sig: string, handler: "default" | "ignore" | ((sig: string) => void)): void; /** * Deliver a signal. Returns true when the process handled or died from it. * Catchable signals run the installed handler; uncatchable ones always kill. */ deliver(sigSpec: string | number): boolean; exit(code: number): void; /** Remove from the table entirely — the parent has reaped us. */ reap(): void; wait(): Promise; } interface ProcessFilter { pid?: number; pgid?: number; uid?: number; comm?: string; includeDead?: boolean; } declare class ProcessTable { private readonly map; create(opts: ProcessOptions): Process; get(pid: number): Process | undefined; has(pid: number): boolean; remove(pid: number): void; list(filter?: ProcessFilter): Process[]; get size(): number; /** Send a signal to a pid, a process group (negative pid), or everything (-1). */ signal(target: number, sig: string | number): number; /** Drop finished processes so the table does not grow without bound. */ gc(keepMs?: number): void; clear(): void; } /** Reset the pid counter — used by tests and by `Container.reset()`. */ declare function resetPidCounter(start?: number): void; /** * The user and group database, backed by real `/etc/passwd`, `/etc/group` and * `/etc/shadow` files so `cat /etc/passwd` and `id` agree with each other and * `useradd` is just a file edit. */ interface PasswdEntry { name: string; passwd: string; uid: number; gid: number; gecos: string; home: string; shell: string; } interface GroupEntry { name: string; passwd: string; gid: number; members: string[]; } declare class UserDatabase { private readonly vfs; constructor(vfs: Vfs); private readLines; users(): PasswdEntry[]; groups(): GroupEntry[]; userByName(name: string): PasswdEntry | undefined; userByUid(uid: number): PasswdEntry | undefined; groupByName(name: string): GroupEntry | undefined; groupByGid(gid: number): GroupEntry | undefined; /** Accepts a name or a numeric id, the way `chown` arguments do. */ resolveUid(spec: string): number | undefined; resolveGid(spec: string): number | undefined; nameForUid(uid: number): string; nameForGid(gid: number): string; /** Every group id a user belongs to, primary first. */ groupsFor(name: string): number[]; credFor(nameOrUid: string | number, umask?: number): Cred; nextFreeUid(min?: number, max?: number): number; nextFreeGid(min?: number, max?: number): number; addUser(entry: PasswdEntry, opts?: { createHome?: boolean; password?: string; }): void; addGroup(entry: GroupEntry): void; removeUser(name: string): boolean; removeGroup(name: string): boolean; /** Add `user` to the supplementary members of `group`. */ addUserToGroup(user: string, group: string): boolean; } /** * The contract every in-container program implements. * * A "binary" is an async function over an `ExecContext`, returning an exit * code. The shell, the coreutils and the language runtimes all speak this one * interface, which is what lets `node`, `python3` and `grep` sit side by side * in `$PATH` and be pipelined together. */ interface ExecContext { /** argv[0] is the command name as invoked. */ readonly argv: string[]; readonly stdin: InputStream; readonly stdout: OutputStream; readonly stderr: OutputStream; readonly env: Env; readonly cwd: string; readonly vfs: Vfs; readonly kernel: Kernel; readonly proc: Process; readonly cred: Cred; readonly signal: AbortSignal; /** Command name, for error prefixes. */ readonly name: string; /** argv without argv[0]. */ readonly args: string[]; /** Resolve a possibly relative path against the process cwd. */ path(p: string): string; /** Write to stdout verbatim. */ write(text: string | Uint8Array): void; /** Write a line to stdout. */ line(text?: string): void; /** Write `name: message` to stderr, followed by a newline. */ warn(message: string): void; /** Report an error and produce an exit code in one expression. */ fail(message: string, code?: number): number; /** Turn a caught filesystem error into the message coreutils would print. */ reportError(e: unknown, subject?: string): number; /** Change the calling process's directory (used by `cd`, `chroot`). */ chdir(dir: string): void; } interface Command { readonly name: string; /** One-line summary shown by `help` and `whatis`. */ readonly summary?: string; /** Usage string shown on `--help` and on a `UsageError`. */ readonly usage?: string; /** Longer text shown by `man`. */ readonly manual?: string; /** Aliases registered into the same PATH entry, e.g. `egrep` → `grep`. */ readonly aliases?: string[]; /** Where the binary claims to live, for `which` and `type`. */ readonly path?: string; run(ctx: ExecContext): Promise | number; } declare function defineCommand(cmd: Command): Command; declare class CommandRegistry { private readonly commands; register(cmd: Command): void; registerAll(cmds: Command[]): void; get(name: string): Command | undefined; has(name: string): boolean; names(): string[]; all(): Command[]; /** Default install location, used when populating `/bin` and `/usr/bin`. */ binPath(name: string): string; } interface ContextInit { argv: string[]; proc: Process; kernel: Kernel; stdin?: InputStream; stdout?: OutputStream; stderr?: OutputStream; env?: Env; cwd?: string; cred?: Cred; } declare function createContext(init: ContextInit): ExecContext; /** * The container's network stack. * * There is no real socket layer: HTTP servers started inside the container are * registered with the RuntimePod's request proxy, and this module is the routing and * name-resolution layer on top — interfaces for `ip`/`ifconfig`, a hosts file * resolver, a listening-port table for `ss`/`netstat`, and an outbound policy * that decides whether `curl https://example.com` is allowed to touch the real * network. */ interface NetInterface { name: string; mac: string; ipv4: string; netmask: string; broadcast?: string; ipv6?: string; mtu: number; up: boolean; loopback: boolean; rxBytes: number; txBytes: number; rxPackets: number; txPackets: number; } interface ListeningPort { port: number; proto: "tcp" | "udp"; address: string; pid: number; program: string; since: number; } interface NetworkOptions { /** * Allow outbound requests to the real internet. When false (the default), * `curl`/`wget`/`fetch` only reach servers running inside the container. */ allowOutbound?: boolean; /** Host allowlist applied when `allowOutbound` is on. `null` means any host. */ allowedHosts?: string[] | null; /** * A URL that performs this container's outbound requests on its behalf. * * In a browser the container's only way out is the page's `fetch`, and a * page may read a response only from a host that sends CORS headers back. * Most APIs do not — an `Authorization` header alone forces a preflight that * plenty of them answer with 405 — so a container that works under Node * fails in a browser at the first real API call, for a reason that belongs * to the page rather than to anything in here. * * A proxy is the way out of that: a server on an origin the page is allowed * to read, which makes the request where CORS does not apply and hands the * whole response back. `sandboxedjs-egress` is one; any endpoint speaking * the same small JSON protocol will do. * * Loopback requests never reach it — those are the container's own servers — * and the outbound policy is applied before a request is handed over, so a * proxy widens what a page can reach, not what the container may. */ proxy?: string; /** Address handed to eth0. */ ipv4?: string; gateway?: string; } declare class NetworkStack { private readonly pod; private readonly vfs; private readonly ifaces; private readonly listeners; readonly options: Required> & NetworkOptions; constructor(pod: RuntimePod, vfs: Vfs, options?: NetworkOptions); interfaces(): NetInterface[]; interface(name: string): NetInterface | undefined; setInterfaceUp(name: string, up: boolean): boolean; get gateway(): string; /** Resolve through `/etc/hosts`; returns null when the name is not local. */ resolve(host: string): string | null; isLocal(host: string): boolean; registerListener(port: number, info: Omit): void; unregisterListener(port: number): void; listening(): ListeningPort[]; /** Ports the pod's proxy has registered for this instance. */ private knownPodPorts; /** True when something inside the container answers on `port`. */ isPortOpen(port: number, timeoutMs?: number): Promise; /** Wait for an in-container server to start answering on `port`. */ waitForPort(port: number, opts?: { timeoutMs?: number; intervalMs?: number; }): Promise; /** The policy every way out of the container applies, not only the shell's. */ get policy(): OutboundPolicy; outboundAllowed(url: string): boolean; /** The endpoint outbound requests are handed to, when the host named one. */ get proxy(): string | null; procNetDev(): string; procNetRoute(): string; countTx(bytes: number, iface?: string): void; countRx(bytes: number, iface?: string): void; } type ExecutionTier = "compatibility" | "translation" | "emulation"; interface BinaryInfo { format: "elf"; bits: 32 | 64; machine: number; architecture: string; littleEndian: boolean; } interface BinaryRequest { path: string; bytes: Uint8Array; sha256: string; info: BinaryInfo; } interface PreparedBinary { /** Once execution begins, failure never retries another backend: effects may exist. */ run(ctx: ExecContext): Promise | number; } type Preparation = { supported: true; program: PreparedBinary; } | { supported: false; reason: string; }; interface BinaryBackend { id: string; tier: ExecutionTier; /** Host-supplied trusted code. Preparation must not execute the guest or mutate its files. */ prepare(request: BinaryRequest, signal: AbortSignal): Promise | Preparation; } interface ExecutionDecision { path: string; backend: string; tier: ExecutionTier; supported: boolean; reason?: string; } declare function binaryDigest(bytes: Uint8Array): string; declare function isElfBinary(bytes: Uint8Array): boolean; declare function inspectElf(bytes: Uint8Array): BinaryInfo; /** Per-container backend registry. No vendor packages or network services are built in. */ declare class BinaryExecutionRegistry { private readonly onDecision?; private backends; constructor(onDecision?: ((decision: ExecutionDecision) => void) | undefined); register(backend: BinaryBackend): () => void; clear(): void; list(): { id: string; tier: ExecutionTier; }[]; run(ctx: ExecContext, path: string): Promise; } interface WasmCommandArtifact { name: string; bytes: Uint8Array; /** Exact SHA-256 hex digest from the package's trusted manifest. */ sha256: string; } /** Install a host-loaded pack of WASI commands. Nothing is fetched implicitly. */ declare function installWasmCommands(kernel: Kernel, artifacts: WasmCommandArtifact[]): void; /** Match exact Linux artifacts to their independently built, ABI-compatible WASI ports. */ declare function createWasmCompatibilityBackend(id: string, entries: { elfSha256: string; wasm: WasmCommandArtifact; }[]): BinaryBackend; interface WasmTranslator { /** Versioned compiler identity: change when flags, compiler or syscall ABI changes. */ id: string; supports(info: BinaryInfo): boolean; /** Supply a real compiler here. Null means unsupported, not a guest runtime failure. */ translate(request: BinaryRequest, signal: AbortSignal): Promise; } /** Bounded, content-addressed cache around a host-provided ELF → WASI translator. */ declare function createTranslationBackend(translator: WasmTranslator, maxCacheBytes?: number): BinaryBackend; /** * The kernel: the object that owns the filesystem, the process table, the user * database and the executable namespace, and knows how to turn an `argv` into * a running process. * * Executables in `$PATH` are real files. Built-in programs are installed as * tiny stub files whose shebang points at the in-kernel implementation, so * `ls -l /usr/bin/grep`, `which grep` and `file /usr/bin/grep` all behave, and * a user-written script in `/usr/local/bin` is dispatched by exactly the same * lookup path. */ interface KernelOptions { pod: RuntimePod; hostname?: string; /** Login user for interactive sessions. Defaults to `root`. */ user?: string; env?: Env; /** Total "RAM" reported by `free`, `/proc/meminfo` and `top`. */ memoryBytes?: number; /** Simulated CPU count for `nproc` and `/proc/cpuinfo`. */ cpus?: number; now?: () => number; } interface RunOptions { cwd?: string; env?: Env; cred?: Cred; stdin?: InputStream | string | Uint8Array; stdout?: OutputStream; stderr?: OutputStream; ppid?: number; pgid?: number; kind?: ProcessKind; tty?: string | null; /** Wall-clock budget; the process is sent SIGKILL when it expires. */ timeoutMs?: number; /** * Descriptors above 2, keyed by number. Each is readable and writable from * the child's side, the way an inherited socketpair end is. */ fds?: Record; } interface RunResult { exitCode: number; stdout: string; stderr: string; pid: number; signal: string | null; timedOut: boolean; } type ExecutableKind = "builtin" | "script" | "native" | "unknown"; interface ResolvedExecutable { kind: ExecutableKind; /** Absolute path of the file that was found. */ path: string; /** Present when `kind === "builtin"`. */ command?: Command; /** Interpreter argv from a `#!` line, when `kind === "script"`. */ interpreter?: string[]; } interface MountEntry { device: string; mountpoint: string; fstype: string; options: string; totalBytes: number; } declare class Kernel { readonly vfs: Vfs; readonly procs: ProcessTable; readonly commands: CommandRegistry; readonly binaries: BinaryExecutionRegistry; readonly users: UserDatabase; readonly pod: RuntimePod; readonly bootTime: number; readonly memoryBytes: number; readonly cpus: number; readonly now: () => number; /** Populated by the network module once it is attached. */ net: NetworkStack; /** init — pid 1, the ancestor of everything. */ readonly init: Process; private readonly builtinByPath; private readonly mounts; private disposed; private _current; /** * The process whose builtin is currently on the stack. `/proc/self` resolves * through this. It is set around each dispatch, so a command that reads * `/proc/self/...` synchronously always sees itself. */ get currentProcess(): Process | null; constructor(opts: KernelOptions); get hostname(): string; set hostname(value: string); get uptimeMs(): number; addMount(entry: MountEntry): void; removeMount(mountpoint: string): boolean; mountTable(): MountEntry[]; /** * Install a command as a real file in `$PATH`. The file holds a shebang that * points at the in-kernel dispatcher, which is what `resolve` looks for. */ installCommand(cmd: Command, dir?: string): void; installCommands(cmds: Command[], dir?: string): void; /** Directories from `$PATH`, with a sane fallback. */ pathDirs(env: Env): string[]; /** * Find `name` the way `execvp` does. Returns null when nothing matches. */ resolveExecutable(name: string, cwd: string, env: Env, cred?: Cred): ResolvedExecutable | null; /** `which`-style lookup that only reports the path. */ which(name: string, cwd: string, env: Env, cred?: Cred): string | null; /** Every executable name reachable through `$PATH`, for tab completion. */ executableNames(env: Env, cred?: Cred): string[]; private toInputStream; /** * Create a process for `argv` and start it. Returns the process immediately; * `proc.wait()` resolves with the exit code. */ spawn(argv: string[], opts?: RunOptions): Process; /** Run to completion and collect stdout/stderr. */ run(argv: string[], opts?: RunOptions): Promise; /** * Resolve `proc.argv` and execute it in-process. Interpreted scripts are * dispatched by re-entering with the interpreter's argv, up to a small depth * so a self-referential shebang cannot loop forever. */ private dispatch; /** Convenience for internal callers that just want the text output. */ capture(argv: string[], opts?: RunOptions): Promise; dispose(): void; get isDisposed(): boolean; assertActive(): void; } /** Shell syntax tree. Words stay raw; `expand.ts` interprets them. */ type RedirectOp = ">" | ">>" | "<" | "<>" | ">|" | ">&" | "<&" | "&>" | "&>>" | "<<" | "<<<"; interface Redirect { op: RedirectOp; /** Source fd, e.g. `2` in `2>file`. Defaults per operator. */ fd?: number; /** Target word (a filename, an fd number, or here-doc/string content). */ target: string; /** Populated for `<<`. */ heredoc?: { body: string; expand: boolean; }; } interface Assignment { name: string; /** Raw value word; undefined for `name=` with nothing after it. */ value: string; /** `name+=value`. */ append: boolean; /** `name=(a b c)` array literal. */ arrayWords?: string[]; } type Node = ListNode | PipelineNode | SimpleCommandNode | SubshellNode | GroupNode | IfNode | ForNode | ForArithNode | WhileNode | CaseNode | FunctionNode | ArithCommandNode | CondNode; type ListOperator = ";" | "&" | "&&" | "||"; interface ListItem { node: Node; /** Operator that *follows* this item. */ op: ListOperator; } interface ListNode { type: "list"; items: ListItem[]; } interface PipelineNode { type: "pipeline"; commands: Node[]; /** `! cmd` inverts the exit status. */ negated: boolean; /** `cmd |& next` pipes stderr too. */ stderrToo: boolean[]; /** `time cmd` */ timed?: boolean; } interface SimpleCommandNode { type: "command"; assignments: Assignment[]; words: string[]; redirects: Redirect[]; } interface SubshellNode { type: "subshell"; body: Node; redirects: Redirect[]; } interface GroupNode { type: "group"; body: Node; redirects: Redirect[]; } interface IfClause { condition: Node; body: Node; } interface IfNode { type: "if"; clauses: IfClause[]; elseBody?: Node; redirects: Redirect[]; } interface ForNode { type: "for"; name: string; /** Absent means `for x; do` which iterates `"$@"`. */ words?: string[]; body: Node; redirects: Redirect[]; /** `select` shares the same shape. */ select?: boolean; } interface ForArithNode { type: "for-arith"; init: string; condition: string; step: string; body: Node; redirects: Redirect[]; } interface WhileNode { type: "while"; condition: Node; body: Node; until: boolean; redirects: Redirect[]; } interface CaseItem { patterns: string[]; body: Node | null; /** `;;` stops, `;&` falls through, `;;&` retests. */ terminator: ";;" | ";&" | ";;&"; } interface CaseNode { type: "case"; word: string; items: CaseItem[]; redirects: Redirect[]; } interface FunctionNode { type: "function"; name: string; body: Node; redirects: Redirect[]; } interface ArithCommandNode { type: "arith"; expression: string; redirects: Redirect[]; } /** `[[ ... ]]` — parsed as a small expression tree of its own. */ type CondExpr = { type: "unary"; op: string; operand: string; } | { type: "binary"; op: string; left: string; right: string; } | { type: "not"; operand: CondExpr; } | { type: "and"; left: CondExpr; right: CondExpr; } | { type: "or"; left: CondExpr; right: CondExpr; } | { type: "word"; value: string; }; interface CondNode { type: "cond"; expression: CondExpr; redirects: Redirect[]; } /** * Shell variable table: scalars, indexed arrays, export/readonly attributes, * and the function-local scoping that `local` introduces. */ interface VarAttributes { exported?: boolean; readonly?: boolean; integer?: boolean; /** `declare -l` / `-u` case folding. */ lower?: boolean; upper?: boolean; } interface VarEntry extends VarAttributes { value: string; array?: string[]; assoc?: Map; } declare class Variables { /** Innermost scope last; index 0 is the global scope. */ private readonly scopes; constructor(initial?: Record); pushScope(): void; popScope(): void; get depth(): number; private find; has(name: string): boolean; get(name: string): string | undefined; entry(name: string): VarEntry | undefined; getArray(name: string): string[] | undefined; isArray(name: string): boolean; set(name: string, value: string, attrs?: VarAttributes): void; /** Declare in the innermost scope, shadowing outer definitions (`local`). */ setLocal(name: string, value: string, attrs?: VarAttributes): void; setArray(name: string, values: string[], attrs?: VarAttributes): void; setIndex(name: string, index: number, value: string): void; append(name: string, value: string): void; unset(name: string): boolean; export(name: string, exported?: boolean): void; markReadonly(name: string): void; names(): string[]; /** The environment handed to a child process. */ environment(): Record; /** Every variable with its attributes, for `declare -p` / `set`. */ all(): Array<{ name: string; entry: VarEntry; }>; } /** * Word expansion, in the order POSIX specifies: * * brace → tilde → parameter/command/arithmetic → field splitting → * pathname → quote removal * * The tricky part is that only text produced by *unquoted* expansions may be * field-split, and only unquoted text may be globbed. Each fragment therefore * carries `split` and `glob` flags through the pipeline, and quote removal is * the last thing that happens. */ interface ExpandContext { vars: Variables; /** `$1`, `$2`, … */ positional: string[]; /** `$0` */ scriptName: string; /** `$?` */ lastStatus: number; /** `$$` */ shellPid: number; /** `$!` */ lastBackgroundPid: number; /** `$-` */ optionFlags: string; cwd: string; vfs: Vfs; cred: Cred; /** Home directory lookup for `~user`. */ homeFor(user: string): string | undefined; /** Runs a command substitution and returns its stdout. */ runSubstitution(command: string): Promise; /** Materialises `<(cmd)` / `>(cmd)` as a path. Optional. */ processSubstitution?(command: string, direction: "in" | "out"): Promise; /** `set -u` */ nounset?: boolean; /** `set -f` */ noglob?: boolean; /** Extended globbing (`shopt -s extglob`). */ extglob?: boolean; /** Include dotfiles in globs (`shopt -s dotglob`). */ dotglob?: boolean; /** Leave an unmatched glob as-is (bash default) or drop it (`nullglob`). */ nullglob?: boolean; /** Error out on an unmatched glob (`failglob`). */ failglob?: boolean; } /** Full expansion of a list of words, as used for command arguments. */ declare function expandWords(words: string[], ctx: ExpandContext): Promise; /** Expand one word into zero or more fields. */ declare function expandWord(word: string, ctx: ExpandContext): Promise; /** `a{b,c}d` → `abd acd`; `{1..5}` and `{a..e}` sequences too. */ declare function braceExpand(word: string): string[]; declare function shellQuote(value: string): string; /** * The shell interpreter. * * Walks the syntax tree, applies redirections, wires pipelines together, and * dispatches each simple command to a function, a builtin, or the kernel's * executable lookup — in that order, which is the order bash uses. */ interface ShellIO { stdin: InputStream; stdout: OutputStream; stderr: OutputStream; } interface ShellOptions { /** `set -e` */ errexit: boolean; /** `set -u` */ nounset: boolean; /** `set -x` */ xtrace: boolean; /** `set -v` */ verbose: boolean; /** `set -f` */ noglob: boolean; /** `set -o pipefail` */ pipefail: boolean; /** `set -n` */ noexec: boolean; /** `set -m` */ monitor: boolean; /** `set -C` */ noclobber: boolean; /** `set -a` */ allexport: boolean; /** Interactive shells print prompts and keep history. */ interactive: boolean; /** Login shells source `/etc/profile`. */ login: boolean; } interface Job { id: number; pgid: number; command: string; state: "running" | "done" | "stopped"; exitCode: number | null; promise: Promise; pids: number[]; } declare class ShellExit { readonly code: number; constructor(code: number); } interface ShellInit { kernel: Kernel; proc: Process; cwd?: string; env?: Record; cred?: Cred; options?: Partial; positional?: string[]; scriptName?: string; } declare class Shell { readonly kernel: Kernel; readonly proc: Process; readonly vars: Variables; readonly functions: Map; readonly aliases: Map; readonly traps: Map; readonly dirStack: string[]; readonly jobs: Job[]; readonly history: string[]; options: ShellOptions; shopts: Set; positional: string[]; scriptName: string; lastStatus: number; lastBackgroundPid: number; cwd: string; cred: Cred; /** Pipeline exit statuses, exposed as `PIPESTATUS`. */ pipeStatus: number[]; private nextJobId; private functionDepth; private tempFileCounter; private exiting; constructor(init: ShellInit); /** Parse and run a script fragment. Returns the last exit status. */ execute(source: string, io: ShellIO): Promise; /** Signal the current terminal pipeline without terminating the interactive shell. */ interruptForeground(signal: string, stdin: InputStream): void; get isExiting(): boolean; /** True when `source` is not yet a complete command (for REPL continuation). */ static isIncomplete(source: string): boolean; expandContext(): ExpandContext; optionFlagString(): string; /** Run `command` in a subshell and return its stdout. */ captureSubshell(command: string): Promise; /** `<(cmd)` — run the command now and hand back a path holding its output. */ private makeProcessSubstitution; /** * A copy that shares nothing mutable with this shell. * * Subshells and pipeline stages run as part of this shell's process. A * background job passes a process of its own, the way fork(2) gives one. */ fork(proc?: Process): Shell; private currentIO; run(node: Node, io: ShellIO): Promise; private runList; /** Skip past short-circuited members of an `&&`/`||` chain. */ private skipChain; private runPipeline; /** * Every stage of a pipeline runs in its own subshell in bash. Sharing the * variable table would let `echo x | read v` leak `v` into the parent. */ private forkForPipeline; private reportTime; private startBackgroundJob; private runSubshell; private runGroup; private runIf; /** Conditions are exempt from `set -e`. */ private runCondition; private runFor; private runSelect; private runForArith; private runWhile; private runCase; private runFunctionDefinition; private runArithCommand; private runCond; private evalCond; private runSimpleCommand; private reportCommandError; /** One level of alias substitution on the command word. */ private substituteAlias; private invoke; private callFunction; private runExternal; /** `VAR=x cmd` — set for the duration, then restore. */ private applyTemporaryAssignments; applyAssignment(assignment: SimpleCommandNode["assignments"][number], exported: boolean): Promise; applyRedirects(redirects: Redirect[], io: ShellIO): Promise<{ io: ShellIO; cleanup: () => void; }>; private openInput; private openOutput; private expandHeredoc; setTrap(signal: string, action: string): void; runTrap(signal: string, io: ShellIO): Promise; changeDirectory(target: string): void; throwBreak(levels: number): never; throwContinue(levels: number): never; throwReturn(code: number): never; throwExit(code: number): never; addJob(job: Job): void; reapJobs(): Job[]; } /** * What a Python runtime release says about itself. * * A manifest is how a host selects an interpreter build without guessing from * a URL. It names the exact artifact, the ABI it was compiled against, and the * capabilities it actually has — so a program that needs threads or native * extensions can be told "not in this profile" instead of failing somewhere * deep inside an import. * * The ABI identity is the part that must never be inferred. A build compiled * against `sbx_host_v1` cannot be loaded by a kernel that speaks a different * version, and finding that out at the first syscall rather than at load time * turns a clear error into a corrupted run. */ declare const MANIFEST_FORMAT = "sandboxedjs-python-runtime"; declare const MANIFEST_SCHEMA_VERSION = 1; /** Build profiles, as defined in docs/python/architecture.md. */ type PythonProfile = "core" | "threaded-fixed" | "dynamic"; interface PythonCapabilities { /** Real Python threads. `core` builds have none, and must say so. */ threads: boolean; /** * How native extensions may arrive: * `none` — no extension modules beyond the built-ins; * `fixed` — curated extensions linked into the image; * `dynamic` — side modules loaded at import time. */ nativeExtensions: "none" | "fixed" | "dynamic"; /** `none`, `http` (kernel-controlled fetch), or `sockets` (virtual sockets). */ networking: "none" | "http" | "sockets"; /** `none`, or `spawn` — never `fork`, which cannot be honest here. */ processes: "none" | "spawn"; /** Where an environment survives: nowhere, memory only, or real storage. */ persistence: "none" | "memory" | "durable"; } interface PythonRuntimeManifest { format: typeof MANIFEST_FORMAT; schemaVersion: number; /** Stable identity of this build; also the cache key for its compiled module. */ runtimeId: string; engine: "cpython-wasm"; /** The interpreter's own version, e.g. "3.13.5". */ pythonVersion: string; profile: PythonProfile; hostAbi: { name: string; version: number; }; artifacts: { /** The Emscripten loader module. Its `.wasm` and `.data` sit beside it. */ moduleUrl: string; /** Optional integrity hashes, keyed by file name. */ hashes?: Record; }; capabilities: PythonCapabilities; } /** * Check a manifest before anything is loaded from it. * * Every failure here is one that would otherwise surface much later and much * less clearly — a missing capability as an ImportError, a wrong ABI as a * corrupted syscall. */ declare function validateManifest(value: unknown): PythonRuntimeManifest; /** * Dependency resolution for the owned Python runtime. * * The installer this replaces walked candidate versions and downloaded a whole * wheel for each one just to read its `METADATA`. That is why it needed an * arbitrary cap on how many candidates it would try: without one, discovering * that a package's last forty releases all need the same unavailable native * extension cost forty multi-megabyte downloads, and the install looked hung * rather than failed. The cap made the symptom bearable and the cause worse -- * a resolution that hit it reported a limit rather than the conflict, and a * legitimately deep graph failed for no reason. * * Three changes remove the need for it: * * * Dependency metadata is read from PEP 658 sidecars, so learning what a * release requires costs a few kilobytes rather than the wheel. * * Constraints propagate. A version excluded by an already-chosen package's * requirement is never fetched at all. * * Conflicts are learned. When a set of constraints proves unsatisfiable, * the proof is recorded, so the same subtree is not re-derived once per * parent version. * * What bounds the work now is a deadline and a cancellation signal, which are * honest limits: they say the search ran out of time, not that it ran out of * an arbitrary allowance. */ /** * One prebuilt SandboxedJs wheel, as published in a wheel index. * * `abiId` travels with the entry rather than being implied by the index it * came from. An index served for a different interpreter build would otherwise * look usable, and the wheel would fail at import rather than at resolution. */ interface PrebuiltWheel { name: string; version: string; filename: string; sha256: string; abiId: string; requires: string[]; } interface WheelIndex { /** The index format. Absent means "the only version there has ever been". */ schemaVersion?: number; /** Where `filename` is resolved against. */ baseUrl: string; wheels: PrebuiltWheel[]; /** Optional in-bundle wheel payloads, keyed by filename and base64 encoded. */ files?: Record; } /** * Which Python backend a container uses. * * The owned runtime is introduced behind an explicit choice rather than as a * silent replacement: the two backends have genuinely different process * semantics, and a container that switched between them on its own would * change whether `sys.modules` is shared, whether `os.getpid()` varies, and * what a failed import means. The old backend stays reachable until the parity * gates in docs/python/release-gates.md pass. */ type PythonBackendName = "sbx-cpython-wasm"; /** * The `python3` command. * * One backend: the owned distribution. CPython built from source, one * interpreter per process, everything reached through the `sbx_host_v1` kernel * ABI. The Pyodide integration it replaced cached a single interpreter per * container and gave each program fresh globals, so `sys.modules` leaked * between unrelated programs and every program reported the same pid. * * The command line is handed to the interpreter verbatim. Re-parsing Python's * flags here to decide what to do with them is how `-X`, `-W` and `-I` come to * be silently dropped; the interpreter's own entry point already knows them all. */ declare const PYTHON_VERSION = "3.13"; interface PythonOptions { /** Which interpreter to run. There is one, and it is the default. */ backend?: PythonBackendName; /** The owned runtime's release manifest. Required by `sbx-cpython-wasm`. */ manifest?: PythonRuntimeManifest; /** Where the built process worker is served from, for hosts that must say. */ workerUrl?: string; /** * Prebuilt wheels for this runtime's native ABI, which PyPI does not carry. * * Either the index itself, or the base URL its `index.json` is served from. * A package with a compiled extension cannot resolve without one, because * no published wheel targets wasm32-emscripten. */ wheelIndex?: WheelIndex | string | null; /** * Build a missing wheel instead of reporting it. * * `true` builds locally, which needs Node and the build pipeline. A URL asks * a build service -- which is how a browser gets a wheel built, having no * compiler of its own. See docs/python/build-on-miss.md. */ buildFromSource?: boolean | string; } declare function configurePython(options?: PythonOptions): void; /** * Whether this host can run Python at all. * * The release manifest is what names the interpreter's assets, so without one * there is nothing to load. Reporting that here lets a caller choose another * path rather than discovering it when a program fails to start. */ declare function isPythonAvailable(): Promise; /** * A promise-based filesystem façade for host code, shaped like `fs/promises` * so it reads naturally from the outside. */ /** Data accepted by the host-facing filesystem API. * * `Blob` includes browser `File` objects, which is what an `` returns. The bytes are copied into the container; no host * filesystem path is ever resolved by the sandbox. */ type FileData = string | Uint8Array | ArrayBuffer | ArrayBufferView | Blob; declare class ContainerFs { private readonly kernel; constructor(kernel: Kernel); private get vfs(); readFile(path: string): Promise; readFile(path: string, encoding: "utf8" | "utf-8"): Promise; writeFile(path: string, data: FileData, opts?: { mode?: number; }): Promise; appendFile(path: string, data: FileData): Promise; readdir(path: string): Promise; readdir(path: string, opts: { withFileTypes: true; }): Promise; mkdir(path: string, opts?: { recursive?: boolean; mode?: number; }): Promise; rm(path: string, opts?: { recursive?: boolean; force?: boolean; }): Promise; rename(from: string, to: string): Promise; copyFile(from: string, to: string): Promise; stat(path: string): Promise; lstat(path: string): Promise; exists(path: string): Promise; symlink(target: string, link: string): Promise; readlink(path: string): Promise; realpath(path: string): Promise; chmod(path: string, mode: number): Promise; chown(path: string, uid: number, gid: number): Promise; /** Every path beneath `root`, depth-first. */ walk(root?: string): Promise; /** Total bytes and file counts, as `df` reports them. */ usage(root?: string): Promise<{ files: number; dirs: number; bytes: number; }>; /** Read many files at once, keyed by path. */ readAll(paths: string[]): Promise>; /** Write a whole map of files, creating parents. */ writeAll(files: Record, opts?: { cwd?: string; }): Promise; } /** * A stateful shell session — `cd`, variables, functions and history persist * across calls, the way a terminal does. `Container.exec` is deliberately * stateless; this is the other half. */ interface SessionInit { cwd: string; env: Record; cred: Cred; hooks?: { onStdout?: (chunk: string) => void; onStderr?: (chunk: string) => void; }; } interface SessionRunOptions { stdin?: string | Uint8Array | InputStream; onStdout?: (chunk: string) => void; onStderr?: (chunk: string) => void; timeoutMs?: number; /** Present the session as attached to a terminal. */ tty?: boolean; columns?: number; rows?: number; } interface SessionResult { exitCode: number; stdout: string; stderr: string; output: string; } declare class Session { private readonly kernel; readonly shell: Shell; readonly proc: Process; private closed; constructor(kernel: Kernel, init: SessionInit); private readonly hooks; get cwd(): string; get env(): Record; get history(): string[]; /** Run a command line, keeping every side effect for the next call. */ run(command: string, opts?: SessionRunOptions): Promise; /** Stream a long-running command; resolves when it exits. */ stream(command: string, handlers?: { onStdout?: (chunk: string) => void; onStderr?: (chunk: string) => void; }): Promise; /** Feed the session an arbitrary output stream, for terminal integration. */ pipeTo(command: string, stdout: OutputStream, stderr: OutputStream, stdin?: InputStream): Promise; /** True when the last command asked the shell to exit. */ get isExiting(): boolean; close(): void; } /** * The public surface: a Linux-like container you can boot inside any Node * process, run commands in, and throw away. * * ```ts * const box = await createContainer({ files: { "/app/index.js": "console.log(1)" } }); * await box.exec("node /app/index.js"); * ``` */ interface ContainerOptions { /** * Files to seed the filesystem with, keyed by absolute (or `cwd`-relative) * path. Parent directories are created automatically — this is the fast way * to drop a whole project in and run it. */ files?: Record; /** Directory `files` keys are resolved against, and the default cwd. Default `/`. */ cwd?: string; hostname?: string; /** * Login user. `"root"` (default) runs privileged; any other name is created * with uid 1000 and sudo rights. Pass `null` for a root-only image. */ user?: string | null; env?: Record; /** RAM reported by `free`, `top` and `/proc/meminfo`. Default 2 GiB. */ memory?: number; /** CPU count reported by `nproc` and `/proc/cpuinfo`. Default 4. */ cpus?: number; network?: NetworkOptions; /** * Applications to install before the container is handed back, by name or * `name@version` — the same specifiers `pm install` takes. * * These are programs, not language packages: `pip` and `npm` install those. * Installing needs the registry to be reachable, so a container with * outbound access turned off has to carry them another way. */ modules?: string[]; timezone?: string; /** Default wall-clock limit for `exec`. Omit for no limit. */ timeoutMs?: number; /** Called for every byte any command writes to stdout, across the container. */ onStdout?: (chunk: string) => void; onStderr?: (chunk: string) => void; /** Invoked when an in-container HTTP server starts listening. */ onServerReady?: (port: number, url: string) => void; /** * Run on a JavaScript runtime you booted yourself. * * The container boots a {@link LocalRuntimePod} when this is omitted, which * is what almost every caller wants. Pass one to share a single runtime * across containers, to seed it differently, or to substitute an * implementation of your own — anything satisfying {@link RuntimePod} works. * * ```ts * const pod = await LocalRuntimePod.boot({ workdir: "/app" }); * const box = await createContainer({ pod, cwd: "/app" }); * ``` */ pod?: RuntimePod; /** * Where guest programs run. * * `"auto"` (the default) tries the worker runtime and reports any fallback. * `"worker"` requires a working guest worker and shared-memory channel: boot * rejects with the cause if either is unavailable, rather than letting * synchronous child-process calls fail later. `"realm"` opts out explicitly. * Processes requiring host-native modules can still run in the host realm. */ isolation?: "auto" | "worker" | "realm"; /** Receives the reason for an automatic fallback; defaults to console.warn. */ onRuntimeFallback?: (error: Error) => void; /** * Where to load the guest worker bundle from. * * Defaults to the copy shipped beside the main bundle, which is what a * published package wants. Worth setting when a bundler has moved or * rewritten it — or when running from source, where the built file is the * only one a Worker can load. */ workerUrl?: string | URL; /** Python runtime settings; a browser host uses this to locate the wasm. */ python?: PythonOptions; } interface ExecOptions { cwd?: string; env?: Record; /** Run as this user instead of the container default. */ user?: string; stdin?: string | Uint8Array; /** Stream output as it is produced, in addition to buffering it. */ onStdout?: (chunk: string) => void; onStderr?: (chunk: string) => void; timeoutMs?: number; /** Report the command as running on a terminal (affects `ls` colour, `-t`). */ tty?: boolean; columns?: number; rows?: number; } interface ExecResult { exitCode: number; stdout: string; stderr: string; /** stdout and stderr interleaved in write order. */ output: string; timedOut: boolean; durationMs: number; } interface SpawnHandle { pid: number; stdin: Pipe; stdout: Pipe; stderr: Pipe; /** Resolves with the exit code. */ wait(): Promise; kill(signal?: string): void; readonly exitCode: number | null; } interface HttpResponse { status: number; statusText: string; headers: Record; body: string; bytes: Uint8Array; json(): T; } /** Where bytes written by an upgraded server inside the container come out. */ interface SocketPeer { /** The server sent these. */ data(bytes: Uint8Array): void; /** The server hung up. */ close(): void; } /** The caller's end of a connection opened with {@link Container.connect}. */ interface SocketConnection { /** Send bytes to the server. */ send(bytes: Uint8Array): void; /** Hang up. */ close(): void; } declare class Container { readonly kernel: Kernel; readonly pod: RuntimePod; readonly fs: ContainerFs; readonly net: NetworkStack; private readonly defaults; private readonly hooks; private disposed; private defaultSession; private readonly restoreNodeChildProcessBridge; private constructor(); static create(opts?: ContainerOptions): Promise; /** * Drop a map of files into the container. Keys may be absolute or relative * to `opts.cwd`; parent directories are created as needed. */ mount(files: Record, opts?: { cwd?: string; mode?: number; }): this; private mountSync; /** Copy a directory tree from the host filesystem into the container. */ copyIn(hostPath: string, containerPath: string): Promise; /** Copy a file or directory out of the container onto the host. */ copyOut(containerPath: string, hostPath: string): Promise; /** Run a shell command line and collect its output. */ exec(command: string, opts?: ExecOptions): Promise; /** Run a program directly, without a shell parsing the arguments. */ run(argv: string[], opts?: ExecOptions): Promise; /** * Start a command and get streams back, for long-running processes such as a * dev server that you want to watch and later kill. */ spawn(command: string, opts?: ExecOptions): SpawnHandle; /** * A stateful shell session: `cd`, variables and functions persist between * calls, the way a terminal behaves. */ session(opts?: { cwd?: string; env?: Record; user?: string; }): Session; /** The container-wide session used by `shell()` shorthand helpers. */ get shell(): Session; /** * The streams one call collects into. * * They are detachable because a background job started by the command keeps * writing after the call has returned. Nothing reads the result any more by * then, so without `detach` a chatty server would grow the buffer for as long * as it ran; afterwards its output still reaches the container-wide taps. */ private makeStdio; /** Send an HTTP request to a server running inside the container. */ request(port: number, init?: { method?: string; path?: string; headers?: Record; body?: string | Uint8Array; }): Promise; /** * Open a connection to a server inside the container that upgrades out of * HTTP — in practice, a WebSocket. * * The counterpart to {@link request}, and the thing a dev server needs that * a request cannot provide. Bytes go in with `send`, come back through * `peer.data`, and neither side interprets them: the container runs whatever * WebSocket library the program chose, and the caller is responsible for * speaking the protocol it answers with. * * Null means there is nothing to talk to — no server on the port, or one * that never registered an `upgrade` handler. Both are worth reporting * rather than waiting out, because neither resolves on its own. */ connect(port: number, init: { method?: string; path?: string; headers?: Record; } | undefined, peer: SocketPeer): SocketConnection | null; /** * Deliver a request whose body is bytes, without letting them become text. * * A RuntimePod's public `request()` may run the body through `toString("utf8")` on * its way in, so anything above `0x7f` is replaced: a five-byte payload * containing `0x89` and `0xff` arrives as nine. That silently destroys every * upload — an image or a video reaches the server the wrong size and no * longer decodes, with no error raised anywhere. * * Its own dispatcher one layer down does preserve bytes, so a binary body * goes straight there. This reaches past the published surface deliberately, * so it is written to fail soft: any shape it does not recognise returns * `null` and the caller falls back to the ordinary path, which is exactly * the behaviour that existed before. Text bodies never come through here. */ private dispatchBinary; /** Wait until something inside the container answers on `port`. */ waitForPort(port: number, opts?: { timeoutMs?: number; intervalMs?: number; }): Promise; /** * Bridge a container port onto a real host port, so a browser (or anything * else on your machine) can reach a dev server running inside the sandbox. */ expose(port: number, opts?: { hostPort?: number; hostname?: string; }): Promise<{ url: string; port: number; close(): Promise; }>; /** A serialisable snapshot of the whole filesystem. */ snapshot(opts?: { shallow?: boolean; }): unknown; restore(snapshot: unknown): Promise; get hostname(): string; get user(): string; get cwd(): string; get env(): Record; private assertActive; /** Tear down every process and release the runtime pod. */ dispose(): void; get isDisposed(): boolean; } /** Boot a container. The one function most callers need. */ declare function createContainer(opts?: ContainerOptions): Promise; export { type PythonOptions as $, NullInput as A, type BinaryBackend as B, Container as C, NullOutput as D, type ExecContext as E, type FileData as F, type GroupEntry as G, type HttpResponse as H, type InputStream as I, type Job as J, Kernel as K, type ListeningPort as L, MANIFEST_FORMAT as M, type Node as N, type OutputStream as O, PYTHON_VERSION as P, type PasswdEntry as Q, Pipe as R, Shell as S, type Preparation as T, type PreparedBinary as U, Process as V, type ProcessKind as W, type ProcessOptions as X, type ProcessState as Y, ProcessTable as Z, type PythonCapabilities as _, type ShellIO as a, type PythonProfile as a0, type PythonRuntimeManifest as a1, type ResolvedExecutable as a2, type RunOptions as a3, type RunResult as a4, type SessionInit as a5, type SessionResult as a6, type SessionRunOptions as a7, ShellExit as a8, type ShellInit as a9, type ShellOptions as aa, type SpawnHandle as ab, type Stdio as ac, TeeOutput as ad, UserDatabase as ae, Variables as af, type WasmCommandArtifact as ag, type WasmTranslator as ah, binaryDigest as ai, braceExpand as aj, captureStdio as ak, configurePython as al, createContext as am, createTranslationBackend as an, createWasmCompatibilityBackend as ao, defineCommand as ap, expandWord as aq, expandWords as ar, inspectElf as as, installWasmCommands as at, isElfBinary as au, isPythonAvailable as av, resetPidCounter as aw, shellQuote as ax, validateManifest as ay, Session as b, type Command as c, createContainer as d, BinaryExecutionRegistry as e, type BinaryInfo as f, type BinaryRequest as g, BufferSink as h, CallbackSink as i, CommandRegistry as j, ContainerFs as k, type ContainerOptions as l, type ContextInit as m, type Env as n, type ExecOptions as o, type ExecResult as p, type ExecutionDecision as q, type ExecutionTier as r, FileInput as s, FileOutput as t, type KernelOptions as u, MANIFEST_SCHEMA_VERSION as v, type MountEntry as w, type NetInterface as x, type NetworkOptions as y, NetworkStack as z };