Kernel
The object kernel_wrapper exposes. A thin bridge to the
kernel worker: it forwards the kernel's RPC methods to JavaScript and
delivers the kernel's callbacks to handlers you register. Construct
it, register your handlers, then call start(). The page
must be cross-origin isolated, since the kernel runs threads.
Constructor
new Kernel(kernelUrl: string)
Creates the bridge. Nothing connects until start().
- kernelUrl
- Absolute URL of the kernel worker module script, e.g.
/kernel.js.
Methods
start(): Promise<void>
Spawns the kernel as a module Web Worker and connects the RPC channel. Provisioning the filesystem is your job once it resolves.
- returns
- A promise that resolves when the bridge is ready to take calls.
const kernel = new Kernel('/kernel.js');
kernel.onStreamOut((stream, bytes) => term.write(bytes));
await kernel.start();
await kernel.untar('/', sysrootBytes);
run(argv: string[], env: string[], cwd: string, piped: boolean): Promise<number>
Spawns a session running argv[0] with the given argument vector.
- argv
- The full argument vector;
argv[0]is the program to run. - env
- Environment as
"VAR=value"strings. - cwd
- Absolute working directory for the session.
- piped
-
falsegives the session a fresh tty;truegives it pipes for stdio and no controlling tty (the remote-exec shape, e.g. a language server). - returns
-
A promise resolving to the session id (
sid, equal to the leader's pid) at spawn time, not at exit. WatchonProcessEventfor the matchingSessionEndedto learn the exit code.
const sid = await kernel.run(['/usr/bin/sh'], ['HOME=/root'], '/root', false);
hangup(sid: number): void
Ends a whole session as if its terminal closed, tearing down its process group.
- sid
- The session id returned by
run.
resizeTty(ttyId: number, cols: number, rows: number): void
Tells the kernel a tty session's terminal changed size, delivering SIGWINCH to its foreground process group.
- ttyId
- The
stream_idfrom the session'sSessionStartedevent. - cols, rows
- The new terminal dimensions in cells.
writeFile(path: string, data: Uint8Array): void
Writes bytes to the kernel filesystem, creating parent directories as needed. A fire-and-forget notification: it returns immediately with no acknowledgement.
- path
- Absolute destination path.
- data
- The file contents.
readFile(path: string): Promise<Uint8Array>
Reads a file's current contents from the kernel filesystem.
- path
- Absolute path to read.
- returns
- A promise resolving to the file's bytes, rejecting if it cannot be read.
untar(path: string, data: Uint8Array): Promise<void>
Extracts a tar archive into the filesystem, rooted at
path. Usually called once after start() to
mount the sysroot at /.
- path
- Absolute directory to extract into.
- data
- The tar archive bytes.
- returns
- A promise that resolves when extraction completes, rejecting on a malformed archive.
Handlers
Register handlers before start() so no early event is
missed. onProcessEvent adds a listener; each stream
handler sets the single callback for its channel.
onProcessEvent(cb: (event: object) => void): void
Called for every process and session lifecycle event. Each event is a plain object keyed by its variant:
- SessionStarted
{ sid, stream_id, piped, argv }the session's stdio is ready; route io forstream_id(andresizeTtyit, for a tty).- SessionEnded
{ sid, result }the session finished;resultis{ Ok: code }(codeisnullon signal death) or{ Err: message }.- ProcessStarted
{ sid, pid, parent_pid, pgid, argv }- ProcessExited
{ sid, pid, result }
run resolves at spawn; SessionEnded is the completion signal.
onStreamOut(cb: (stream: number, data: Uint8Array) => void | Promise<void>): void
Called with a session's stdout bytes. If cb returns a
promise, the kernel's next write for that stream waits on it: this
is the backpressure ack, so resolve it once you have consumed the
bytes.
- stream
- The stream the bytes belong to (a session's
stream_id). - data
- The output bytes.
kernel.onStreamOut((stream, bytes) => { term.write(bytes); });
onStreamErr(cb: (stream: number, data: Uint8Array) => void | Promise<void>): void
Like onStreamOut, but for stderr (fd 2). Only piped
sessions emit it; a tty merges stderr into stdout. Returning a
promise applies the same backpressure.
onStreamIn(cb: (stream: number) => Promise<Uint8Array | null>): void
Asked for a session's stdin. The kernel long-polls: it calls
cb, awaits the result, feeds those bytes, and calls
again. Return a pending promise you resolve when input arrives.
- stream
- The stream requesting input.
- returns
- A promise resolving to the input bytes, or
nullfor end-of-input (EOF).
kernel.onStreamIn((stream) => nextKeystrokes(stream)); // Promise<Uint8Array | null>
onStreamClosed(cb: (stream: number) => void): void
Called when a stream is finished, after its last output has been
acknowledged; any pending onStreamIn for it is then
cancelled. This is the stream closing, not the session ending: watch
SessionEnded for that.
- stream
- The stream that closed.