@nimbus-sh/worker 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/facets/manager.d.ts +24 -0
- package/dist/facets/manager.d.ts.map +1 -1
- package/dist/facets/manager.js +73 -14
- package/dist/loaders/generated-workers.d.ts +2 -2
- package/dist/loaders/generated-workers.d.ts.map +1 -1
- package/dist/loaders/generated-workers.js +3 -3
- package/dist/runtime/facet-loader-host.d.ts +3 -2
- package/dist/runtime/facet-loader-host.d.ts.map +1 -1
- package/dist/runtime/facet-loader-host.js +1 -0
- package/dist/runtime/ruby-repl.js +1 -1
- package/dist/runtime/ruby-resident.d.ts +20 -0
- package/dist/runtime/ruby-resident.d.ts.map +1 -0
- package/dist/runtime/ruby-resident.js +278 -0
- package/dist/session/init.d.ts +16 -7
- package/dist/session/init.d.ts.map +1 -1
- package/dist/session/init.js +192 -208
- package/dist/session/keys.d.ts +11 -9
- package/dist/session/keys.d.ts.map +1 -1
- package/dist/session/keys.js +11 -9
- package/dist/session/nimbus-session.d.ts +11 -1
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +13 -57
- package/dist/session/programmatic.d.ts +1 -1
- package/dist/session/programmatic.d.ts.map +1 -1
- package/dist/session/programmatic.js +1 -1
- package/dist/session/routes.js +1 -1
- package/package.json +2 -2
- package/scripts/bundle-facet-workers.mjs +4 -3
- package/scripts/bundle-runtime.mjs +279 -44
- package/dist/npm/tarball-stream.d.ts +0 -93
- package/dist/npm/tarball-stream.d.ts.map +0 -1
- package/dist/npm/tarball-stream.js +0 -235
- package/dist/npm/tarball.d.ts +0 -34
- package/dist/npm/tarball.d.ts.map +0 -1
- package/dist/npm/tarball.js +0 -97
- package/dist/runtime/clang-runner.d.ts +0 -37
- package/dist/runtime/clang-runner.d.ts.map +0 -1
- package/dist/runtime/clang-runner.js +0 -865
- package/dist/runtime/ruby-gems.d.ts +0 -30
- package/dist/runtime/ruby-gems.d.ts.map +0 -1
- package/dist/runtime/ruby-gems.js +0 -636
- package/dist/runtime/ruby-runner.d.ts +0 -75
- package/dist/runtime/ruby-runner.d.ts.map +0 -1
- package/dist/runtime/ruby-runner.js +0 -1577
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ruby-resident.ts — a Ruby program that keeps serving, as a Durable Object
|
|
3
|
+
* facet.
|
|
4
|
+
*
|
|
5
|
+
* The half of the Ruby runtime that names workerd. Everything about running
|
|
6
|
+
* the interpreter is in `@nimbus-sh/core`; this is the substrate a program
|
|
7
|
+
* that outlives its invocation needs — an actor that stays alive between
|
|
8
|
+
* requests, with inbound HTTP routed into the socket the program bound. A
|
|
9
|
+
* host without one supplies no {@link RubyResidentStart}, and such a program
|
|
10
|
+
* is refused rather than quietly run as a one-shot that dies with the call.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import { buildRubyPreamble, normalizeRubyFacetResult, } from '@nimbus-sh/core/runtime/ruby-runner.js';
|
|
14
|
+
import { VIRTUAL_SOCKET_KERNEL_SRC } from '@nimbus-sh/core/runtime/virtual-socket-kernel.generated.js';
|
|
15
|
+
const RubySocketProcessBootResponseSchema = z.object({
|
|
16
|
+
state: z.string().optional(),
|
|
17
|
+
port: z.number().optional(),
|
|
18
|
+
stdout: z.string().optional(),
|
|
19
|
+
stderr: z.string().optional(),
|
|
20
|
+
result: z.unknown().optional(),
|
|
21
|
+
}).passthrough();
|
|
22
|
+
/**
|
|
23
|
+
* Start a Ruby program that binds a port as its own process, so it outlives
|
|
24
|
+
* the invocation that started it.
|
|
25
|
+
*/
|
|
26
|
+
export function rubyResidentStart(facetMgr) {
|
|
27
|
+
return async function startResidentRuby(args) {
|
|
28
|
+
const command = args.command;
|
|
29
|
+
const workerCode = buildRubySocketProcessWorker(buildRubyPreamble());
|
|
30
|
+
const spawned = await facetMgr.spawnWorker(workerCode, command, args.cwd, {
|
|
31
|
+
compatibilityFlags: ['nodejs_compat'],
|
|
32
|
+
// By path, not by value: the image is 34.3 MiB — more than a single RPC
|
|
33
|
+
// value may carry — so whichever host runs this process reads it itself.
|
|
34
|
+
vfsWasmModules: { 'ruby+stdlib.wasm': args.wasmVfsPath },
|
|
35
|
+
startArgs: args.startArgs,
|
|
36
|
+
}).catch(() => null);
|
|
37
|
+
if (!spawned) {
|
|
38
|
+
return { exitCode: 1, stdout: '', stderr: 'ruby process boot failed\n' };
|
|
39
|
+
}
|
|
40
|
+
const parsed = RubySocketProcessBootResponseSchema.safeParse(spawned.boot);
|
|
41
|
+
if (!parsed.success) {
|
|
42
|
+
facetMgr.finishProcess(spawned.pid, 1, 'ruby process boot failed');
|
|
43
|
+
return {
|
|
44
|
+
exitCode: 1,
|
|
45
|
+
stdout: '',
|
|
46
|
+
stderr: 'ruby process boot failed\n',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const boot = parsed.data;
|
|
50
|
+
if (boot.state === 'listening' && typeof boot.port === 'number' && boot.port > 0) {
|
|
51
|
+
facetMgr.registerPort(spawned.pid, Number(boot.port));
|
|
52
|
+
const routeablePorts = await facetMgr.waitForRouteablePorts(spawned.pid);
|
|
53
|
+
const routeablePort = routeablePorts.includes(Number(boot.port)) ? Number(boot.port) : routeablePorts[0];
|
|
54
|
+
if (!routeablePort) {
|
|
55
|
+
facetMgr.kill(spawned.pid);
|
|
56
|
+
return {
|
|
57
|
+
exitCode: 1,
|
|
58
|
+
stdout: boot.stdout || '',
|
|
59
|
+
stderr: `${boot.stderr || ''}ruby: virtual socket port ${boot.port} failed to attach a route handler\n`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
exitCode: 0,
|
|
64
|
+
stdout: `${boot.stdout || ''}\x1b[2m[started (long-running): pid=${spawned.pid} cmd="${command}" port=${routeablePort}]\x1b[0m\n`,
|
|
65
|
+
stderr: boot.stderr || '',
|
|
66
|
+
spawnedPid: spawned.pid,
|
|
67
|
+
port: routeablePort,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const reservedPorts = await facetMgr.waitForRouteablePorts(spawned.pid);
|
|
71
|
+
if (reservedPorts.length > 0) {
|
|
72
|
+
return {
|
|
73
|
+
exitCode: 0,
|
|
74
|
+
stdout: `${boot.stdout || ''}\x1b[2m[started (long-running): pid=${spawned.pid} cmd="${command}" port=${reservedPorts[0]}]\x1b[0m\n`,
|
|
75
|
+
stderr: boot.stderr || '',
|
|
76
|
+
spawnedPid: spawned.pid,
|
|
77
|
+
port: reservedPorts[0],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (boot.state === 'exited') {
|
|
81
|
+
const result = normalizeRubyFacetResult(boot.result) || {
|
|
82
|
+
exitCode: 1,
|
|
83
|
+
stdout: '',
|
|
84
|
+
stderr: 'ruby process returned an invalid exit payload\n',
|
|
85
|
+
};
|
|
86
|
+
facetMgr.finishProcess(spawned.pid, result.exitCode, result.stderr || 'ruby process exited');
|
|
87
|
+
return {
|
|
88
|
+
exitCode: result.exitCode,
|
|
89
|
+
stdout: result.stdout,
|
|
90
|
+
stderr: result.stderr || result.error || '',
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
exitCode: 0,
|
|
95
|
+
stdout: `${boot.stdout || ''}\x1b[2m[started (long-running): pid=${spawned.pid} cmd="${command}"]\x1b[0m\n`,
|
|
96
|
+
stderr: boot.stderr || '',
|
|
97
|
+
spawnedPid: spawned.pid,
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
export function buildRubySocketProcessWorker(preamble) {
|
|
102
|
+
return [
|
|
103
|
+
'import { DurableObject } from "cloudflare:workers";',
|
|
104
|
+
"import __NIMBUS_WASM_ruby_stdlib from './ruby+stdlib.wasm';",
|
|
105
|
+
'globalThis.__NIMBUS_WASM = globalThis.__NIMBUS_WASM || {};',
|
|
106
|
+
"globalThis.__NIMBUS_WASM['ruby+stdlib.wasm'] = __NIMBUS_WASM_ruby_stdlib;",
|
|
107
|
+
'',
|
|
108
|
+
VIRTUAL_SOCKET_KERNEL_SRC,
|
|
109
|
+
'',
|
|
110
|
+
// Listener lifecycle only. Socket bytes never cross this bridge: Ruby opens
|
|
111
|
+
// both accepted and dialed connections as file descriptors and reads and
|
|
112
|
+
// writes them as ordinary IO.
|
|
113
|
+
'globalThis.__nimbusRubySockets = {',
|
|
114
|
+
' listen(port) { return globalThis.__nimbusVirtualSockets.listen(Number(port)); },',
|
|
115
|
+
' closeListener(port) { globalThis.__nimbusVirtualSockets.closeListener(Number(port)); return true; },',
|
|
116
|
+
' pending(port) { return globalThis.__nimbusVirtualSockets.pending(Number(port)); },',
|
|
117
|
+
' acceptNowJson(port) { const conn = globalThis.__nimbusVirtualSockets.acceptNow(Number(port)); return conn ? JSON.stringify(conn) : ""; },',
|
|
118
|
+
'};',
|
|
119
|
+
'',
|
|
120
|
+
// Outbound half of the same loopback the shell's curl and node's patched
|
|
121
|
+
// fetch use: one mechanism, reached here through the supervisor RPC.
|
|
122
|
+
'globalThis.__nimbusVirtualSocketRouteLoopback = function __nimbusVirtualSocketRouteLoopback(port, request) {',
|
|
123
|
+
' const supervisor = globalThis.__nimbusRubySupervisor;',
|
|
124
|
+
' if (!supervisor || typeof supervisor.routeLoopback !== "function") {',
|
|
125
|
+
' return Promise.reject(new Error("this Ruby process has no supervisor binding for loopback routing"));',
|
|
126
|
+
' }',
|
|
127
|
+
' return Promise.resolve(supervisor.routeLoopback(Number(port), request));',
|
|
128
|
+
'};',
|
|
129
|
+
'',
|
|
130
|
+
'globalThis.__nimbusVirtualPortRegistrationPromises = globalThis.__nimbusVirtualPortRegistrationPromises || [];',
|
|
131
|
+
'globalThis.__nimbusVirtualSocketDidListen = function __nimbusVirtualSocketDidListen(port) {',
|
|
132
|
+
' const supervisor = globalThis.__nimbusRubySupervisor;',
|
|
133
|
+
' if (!supervisor || typeof supervisor.registerPort !== "function") return;',
|
|
134
|
+
' try {',
|
|
135
|
+
' const p = supervisor.registerPort(Number(port)).catch((e) => {',
|
|
136
|
+
' const msg = e && e.message ? e.message : String(e);',
|
|
137
|
+
' (globalThis.__nimbusRubyStderr || (globalThis.__nimbusRubyStderr = [])).push("[ruby-runner] port registration failed: " + msg + "\\n");',
|
|
138
|
+
' });',
|
|
139
|
+
' globalThis.__nimbusVirtualPortRegistrationPromises.push(p);',
|
|
140
|
+
' } catch (e) {',
|
|
141
|
+
' const msg = e && e.message ? e.message : String(e);',
|
|
142
|
+
' (globalThis.__nimbusRubyStderr || (globalThis.__nimbusRubyStderr = [])).push("[ruby-runner] port registration failed: " + msg + "\\n");',
|
|
143
|
+
' }',
|
|
144
|
+
'};',
|
|
145
|
+
'',
|
|
146
|
+
preamble,
|
|
147
|
+
'',
|
|
148
|
+
// Drive the process when a connection is queued. This is the whole of the
|
|
149
|
+
// runtime's involvement in serving: it knows nothing about what is
|
|
150
|
+
// listening, only that the process should run until it parks.
|
|
151
|
+
//
|
|
152
|
+
// Steps go through the shared resume queue in the preamble, so a handler
|
|
153
|
+
// that parks does not stall other connections and no two drivers can enter
|
|
154
|
+
// a live fiber at once.
|
|
155
|
+
// Timed work the process still owes: the wall-clock moment its earliest
|
|
156
|
+
// sleeper is due. It lives on the global rather than in one driver's
|
|
157
|
+
// closure because no single request may own it. A timer belongs to the
|
|
158
|
+
// request context that created it, and workerd cancels that timer without
|
|
159
|
+
// a word when the request ends - so a driver anchored to the first
|
|
160
|
+
// connection stops dead the moment that connection answers, and every
|
|
161
|
+
// other connection waits out the response timeout instead.
|
|
162
|
+
'globalThis.__nimbusRubyWakeAt = globalThis.__nimbusRubyWakeAt || null;',
|
|
163
|
+
'globalThis.__nimbusRubyIdleDrivers = globalThis.__nimbusRubyIdleDrivers || new Set();',
|
|
164
|
+
'function __nimbusRubyNoteWake(wakeAfter) {',
|
|
165
|
+
' globalThis.__nimbusRubyWakeAt = (wakeAfter === null || wakeAfter === undefined)',
|
|
166
|
+
' ? null',
|
|
167
|
+
' : Date.now() + Math.max(0, wakeAfter) * 1000;',
|
|
168
|
+
' if (globalThis.__nimbusRubyWakeAt === null) return;',
|
|
169
|
+
' const waiting = Array.from(globalThis.__nimbusRubyIdleDrivers);',
|
|
170
|
+
' globalThis.__nimbusRubyIdleDrivers.clear();',
|
|
171
|
+
' for (const wake of waiting) wake();',
|
|
172
|
+
'}',
|
|
173
|
+
// So instead every live request drives, for as long as it is live, and the
|
|
174
|
+
// moment one of them answers the others are already carrying the work.
|
|
175
|
+
// Steps are serialized by the resume queue, and a driver that wakes to
|
|
176
|
+
// find the deadline already moved knows another one got there first.
|
|
177
|
+
'async function __nimbusRubyDrive() {',
|
|
178
|
+
' for (;;) {',
|
|
179
|
+
' const due = globalThis.__nimbusRubyWakeAt;',
|
|
180
|
+
' if (due === null) {',
|
|
181
|
+
' // Nothing is due yet. Stay available anyway: this request holds a',
|
|
182
|
+
' // live context, and whichever request discovers the next piece of',
|
|
183
|
+
' // timed work may answer and be gone before that work comes due.',
|
|
184
|
+
' await new Promise((resolve) => globalThis.__nimbusRubyIdleDrivers.add(resolve));',
|
|
185
|
+
' continue;',
|
|
186
|
+
' }',
|
|
187
|
+
' const delay = due - Date.now();',
|
|
188
|
+
' if (delay > 0) await new Promise((resolve) => setTimeout(resolve, delay));',
|
|
189
|
+
' if (globalThis.__nimbusRubyWakeAt !== due) continue;',
|
|
190
|
+
' const step = await globalThis.__nimbusRubyStep();',
|
|
191
|
+
' if (!step.resumed || !step.alive) { globalThis.__nimbusRubyWakeAt = null; return; }',
|
|
192
|
+
' __nimbusRubyNoteWake(step.wakeAfter);',
|
|
193
|
+
' }',
|
|
194
|
+
'}',
|
|
195
|
+
'globalThis.__nimbusVirtualSocketRequestQueued = async function __nimbusVirtualSocketRequestQueued(port) {',
|
|
196
|
+
' const step = await globalThis.__nimbusRubyStep();',
|
|
197
|
+
' if (!step.resumed) return false;',
|
|
198
|
+
' __nimbusRubyNoteWake(step.wakeAfter);',
|
|
199
|
+
' __nimbusRubyDrive().catch((e) => {',
|
|
200
|
+
' (globalThis.__nimbusRubyStderr || (globalThis.__nimbusRubyStderr = [])).push(',
|
|
201
|
+
' "[ruby-runner] driving the process failed: " + ((e && e.message) || e) + "\\n");',
|
|
202
|
+
' });',
|
|
203
|
+
' return true;',
|
|
204
|
+
'};',
|
|
205
|
+
'',
|
|
206
|
+
'async function __nimbusStartRubyProcess(args) {',
|
|
207
|
+
' if (!globalThis.__nimbusRubyProcessPromise) {',
|
|
208
|
+
' const stdoutStart = (globalThis.__nimbusRubyStdout || []).length;',
|
|
209
|
+
' const stderrStart = (globalThis.__nimbusRubyStderr || []).length;',
|
|
210
|
+
' globalThis.__nimbusRubyProcessOutputStart = { stdoutStart, stderrStart };',
|
|
211
|
+
' globalThis.__nimbusRubyProcessArgs = {',
|
|
212
|
+
' userCode: args.userCode,',
|
|
213
|
+
' rbArgv: args.rbArgv || [],',
|
|
214
|
+
' userEnv: args.userEnv || {},',
|
|
215
|
+
' progName: args.progName || "ruby",',
|
|
216
|
+
' cwd: args.cwd || "/home/user",',
|
|
217
|
+
' fsSnapshot: args.fsSnapshot,',
|
|
218
|
+
' };',
|
|
219
|
+
' globalThis.__nimbusRubyProcessPromise = globalThis.__rubyRun(globalThis.__nimbusRubyProcessArgs).then((result) => {',
|
|
220
|
+
' globalThis.__nimbusRubyProcessResult = result;',
|
|
221
|
+
' return result;',
|
|
222
|
+
' });',
|
|
223
|
+
' }',
|
|
224
|
+
' const started = globalThis.__nimbusRubyProcessOutputStart || { stdoutStart: 0, stderrStart: 0 };',
|
|
225
|
+
' const listen = globalThis.__nimbusVirtualSockets.waitForListen(10_000).then((port) => ({ state: port ? "listening" : "pending", port }));',
|
|
226
|
+
' const exit = globalThis.__nimbusRubyProcessPromise.then((result) => ({ state: "exited", result }));',
|
|
227
|
+
' const first = await Promise.race([listen, exit]);',
|
|
228
|
+
' const registrations = globalThis.__nimbusVirtualPortRegistrationPromises || [];',
|
|
229
|
+
' if (registrations.length > 0) await Promise.allSettled(registrations.splice(0));',
|
|
230
|
+
' const stdout = (globalThis.__nimbusRubyStdout || []).slice(started.stdoutStart).join("");',
|
|
231
|
+
' const stderr = (globalThis.__nimbusRubyStderr || []).slice(started.stderrStart).join("");',
|
|
232
|
+
' if (first.state === "listening") return { state: "listening", port: first.port, stdout, stderr };',
|
|
233
|
+
' if (first.state === "exited") return { state: "exited", result: first.result, stdout, stderr };',
|
|
234
|
+
' const currentPort = globalThis.__nimbusVirtualSockets.firstListeningPort();',
|
|
235
|
+
' if (currentPort) return { state: "listening", port: currentPort, stdout, stderr };',
|
|
236
|
+
' return { state: "running", stdout, stderr };',
|
|
237
|
+
'}',
|
|
238
|
+
'',
|
|
239
|
+
// Only adopt a real binding: routed handleHttpRequest/fetch hops resolve
|
|
240
|
+
// the entrypoint without a supervisor, and overwriting with undefined
|
|
241
|
+
// would drop the live stub the process needs for its whole lifetime.
|
|
242
|
+
'function __nimbusAdoptRubySupervisor(env) {',
|
|
243
|
+
' const supervisor = env && env.SUPERVISOR;',
|
|
244
|
+
' if (supervisor) globalThis.__nimbusRubySupervisor = supervisor;',
|
|
245
|
+
// The WASI filesystem takes the same stub. That is what turns the
|
|
246
|
+
// spawn-time seed into a cache over the session VFS, so a server that
|
|
247
|
+
// never exits still persists its writes instead of losing them entirely.
|
|
248
|
+
' __wasiAdoptSupervisor(supervisor);',
|
|
249
|
+
'}',
|
|
250
|
+
// A resident process parks between requests, and parking is the only
|
|
251
|
+
// moment "durable while running" can be made true: by the time the caller
|
|
252
|
+
// holds a response, everything the request wrote has reached the VFS.
|
|
253
|
+
'async function __nimbusParkRuby(value) {',
|
|
254
|
+
// Revalidate drains first, then spends ONE round trip on the subtree
|
|
255
|
+
// revision. An unchanged subtree keeps the whole cache; a changed one
|
|
256
|
+
// drops the clean half so the next read sees another process's writes.
|
|
257
|
+
' await __wasiRevalidateFS();',
|
|
258
|
+
' return value;',
|
|
259
|
+
'}',
|
|
260
|
+
'export class NimbusProcess extends DurableObject {',
|
|
261
|
+
' async startProcess(args) {',
|
|
262
|
+
' __nimbusAdoptRubySupervisor(this.env);',
|
|
263
|
+
' return __nimbusParkRuby(await __nimbusStartRubyProcess(args || {}));',
|
|
264
|
+
' }',
|
|
265
|
+
' async fetch(request) {',
|
|
266
|
+
' __nimbusAdoptRubySupervisor(this.env);',
|
|
267
|
+
' return this.handleHttpRequest(request);',
|
|
268
|
+
' }',
|
|
269
|
+
' async handleHttpRequest(request) {',
|
|
270
|
+
' __nimbusAdoptRubySupervisor(this.env);',
|
|
271
|
+
' const hinted = Number(request.headers.get("X-Nimbus-Port") || 0);',
|
|
272
|
+
' const port = hinted || Array.from(globalThis.__nimbusVirtualSockets.listeners.keys())[0];',
|
|
273
|
+
' if (!port) return new Response("Nimbus Ruby process has no listening virtual socket", { status: 502 });',
|
|
274
|
+
' return __nimbusParkRuby(await globalThis.__nimbusVirtualSockets.handleHttpRequest(port, request));',
|
|
275
|
+
' }',
|
|
276
|
+
'}',
|
|
277
|
+
].join('\n');
|
|
278
|
+
}
|
package/dist/session/init.d.ts
CHANGED
|
@@ -3,12 +3,21 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Why this is one big function and not a class:
|
|
5
5
|
* initSession runs once per /ws upgrade and walks the session
|
|
6
|
-
* through Phase R (rehydrate from SQL), Phase B (
|
|
7
|
-
*
|
|
8
|
-
* (cold-only) Phase O (MOTD + framework hint). The
|
|
9
|
-
* lots of locals (vfs, kernel, registry, shell) and
|
|
10
|
-
* matters strictly — there's no interesting reuse boundary
|
|
11
|
-
* class decomposition would expose.
|
|
6
|
+
* through Phase R (rehydrate from SQL), Phase B (compose the
|
|
7
|
+
* workspace + register the session's commands), Phase W (attach
|
|
8
|
+
* terminal), and (cold-only) Phase O (MOTD + framework hint). The
|
|
9
|
+
* phases share lots of locals (vfs, kernel, registry, shell) and
|
|
10
|
+
* ordering matters strictly — there's no interesting reuse boundary
|
|
11
|
+
* that a class decomposition would expose.
|
|
12
|
+
*
|
|
13
|
+
* What it no longer does is COMPOSE the operating system. The kernel,
|
|
14
|
+
* the provider mounts, the command registry, the coreutils, the exec
|
|
15
|
+
* resolver, the default environment and the shell come from
|
|
16
|
+
* `NimbusWorkspace` (@nimbus-sh/core/workspace), which an embedder off
|
|
17
|
+
* Cloudflare builds the same way. What stays here is everything that
|
|
18
|
+
* only makes sense with a socket, a Durable Object and a product behind
|
|
19
|
+
* it: the terminal and its scrollback, the phase machine, the persisted
|
|
20
|
+
* shell state, npm, git, vite, wrangler and the facet-backed runtimes.
|
|
12
21
|
*
|
|
13
22
|
* The function is intentionally written so that a reader sees:
|
|
14
23
|
* 1. setPhase('rehydrate') ...
|
|
@@ -38,6 +47,6 @@ type InitHost = SessionInternal & {
|
|
|
38
47
|
readonly ctx: any;
|
|
39
48
|
readonly env: any;
|
|
40
49
|
};
|
|
41
|
-
export declare function initSession(self: InitHost, ws: WebSocket): void
|
|
50
|
+
export declare function initSession(self: InitHost, ws: WebSocket): Promise<void>;
|
|
42
51
|
export {};
|
|
43
52
|
//# sourceMappingURL=init.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/session/init.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/session/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AA6EH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;;;;GAQG;AACH,KAAK,QAAQ,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;CAAE,CAAC;AAa3E,wBAAsB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAksF9E"}
|