@nimbus-sh/worker 0.7.0 → 0.8.0
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/dist/facets/manager.d.ts.map +1 -1
- package/dist/facets/manager.js +16 -5
- package/dist/facets/real-vite-hmr.d.ts +3 -1
- package/dist/facets/real-vite-hmr.d.ts.map +1 -1
- package/dist/facets/real-vite-hmr.js +18 -8
- package/dist/facets/ws-terminal.d.ts +9 -31
- package/dist/facets/ws-terminal.d.ts.map +1 -1
- package/dist/facets/ws-terminal.js +58 -51
- package/dist/hosted/commands.d.ts +12 -0
- package/dist/hosted/commands.d.ts.map +1 -0
- package/dist/hosted/commands.js +1658 -0
- package/dist/hosted/runtime.d.ts +114 -0
- package/dist/hosted/runtime.d.ts.map +1 -0
- package/dist/hosted/runtime.js +288 -0
- package/dist/hosted/services.d.ts +40 -0
- package/dist/hosted/services.d.ts.map +1 -0
- package/dist/hosted/services.js +512 -0
- package/dist/runtime/bash-repl.d.ts +1 -1
- package/dist/runtime/bash-repl.d.ts.map +1 -1
- package/dist/runtime/bash-repl.js +38 -4
- package/dist/runtime/bun-runner.js +1 -1
- package/dist/runtime/node-runner.d.ts +1 -1
- package/dist/runtime/node-runner.d.ts.map +1 -1
- package/dist/runtime/node-runner.js +2 -2
- package/dist/runtime/opencode-facet-runner.js +14 -14
- package/dist/runtime/package-manager.d.ts +35 -122
- package/dist/runtime/package-manager.d.ts.map +1 -1
- package/dist/runtime/package-manager.js +61 -596
- package/dist/runtime/process-logs-api.d.ts +1 -1
- package/dist/runtime/process-logs-api.d.ts.map +1 -1
- package/dist/runtime/process-logs-api.js +1 -1
- package/dist/runtime/python-repl.d.ts +2 -1
- package/dist/runtime/python-repl.d.ts.map +1 -1
- package/dist/runtime/python-repl.js +82 -59
- package/dist/runtime/repl-session.d.ts +9 -47
- package/dist/runtime/repl-session.d.ts.map +1 -1
- package/dist/runtime/repl-session.js +105 -105
- package/dist/runtime/runtime-catalog.d.ts +13 -0
- package/dist/runtime/runtime-catalog.d.ts.map +1 -1
- package/dist/runtime/runtime-catalog.js +88 -0
- package/dist/session/agent.d.ts +1 -21
- package/dist/session/agent.d.ts.map +1 -1
- package/dist/session/ai.d.ts +5 -1
- package/dist/session/ai.d.ts.map +1 -1
- package/dist/session/ai.js +7 -0
- package/dist/session/hibernation.d.ts +2 -1
- package/dist/session/hibernation.d.ts.map +1 -1
- package/dist/session/hibernation.js +7 -4
- package/dist/session/init.d.ts +1 -36
- package/dist/session/init.d.ts.map +1 -1
- package/dist/session/init.js +17 -1773
- package/dist/session/loopback.d.ts +2 -29
- package/dist/session/loopback.d.ts.map +1 -1
- package/dist/session/loopback.js +3 -27
- package/dist/session/nimbus-session.d.ts +22 -13
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +67 -484
- package/dist/session/npm-install-port.d.ts +3 -1
- package/dist/session/npm-install-port.d.ts.map +1 -1
- package/dist/session/programmatic.d.ts +5 -38
- package/dist/session/programmatic.d.ts.map +1 -1
- package/dist/session/programmatic.js +16 -48
- package/dist/session/rpc.d.ts.map +1 -1
- package/dist/session/rpc.js +1 -2
- package/dist/session/supervisor-op.d.ts +2 -2
- package/dist/session/supervisor-op.d.ts.map +1 -1
- package/dist/session/supervisor-op.js +11 -3
- package/dist/workspace-host.d.ts +6 -0
- package/dist/workspace-host.d.ts.map +1 -0
- package/dist/workspace-host.js +5 -0
- package/dist/workspace.d.ts +2 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +1 -0
- package/package.json +16 -11
|
@@ -11,46 +11,12 @@
|
|
|
11
11
|
* live in src/runtime/<name>-repl.ts and implement the ReplAdapter
|
|
12
12
|
* interface declared below.
|
|
13
13
|
*/
|
|
14
|
+
import { errorText } from '@nimbus-sh/core/_shared/error-text.js';
|
|
14
15
|
import { normalizeTerminalNewlines } from '@nimbus-sh/core/_shared/terminal.js';
|
|
15
|
-
/**
|
|
16
|
-
* Manages an interactive REPL session: stdin buffering with minimal
|
|
17
|
-
* readline UX (line-mode), output routing to the WS terminal, prompt
|
|
18
|
-
* rendering, and adapter dispatch.
|
|
19
|
-
*
|
|
20
|
-
* The shell creates a ReplSession when a runtime's `startRepl` hook
|
|
21
|
-
* fires; the session installs a `replCallback` on the WebSocketTerminal
|
|
22
|
-
* (via attachRepl()) and runs until the adapter signals 'exit' or the
|
|
23
|
-
* user presses Ctrl-D on an empty line.
|
|
24
|
-
*
|
|
25
|
-
* No setTimeout in the read loop — the session is driven entirely by
|
|
26
|
-
* keystroke arrival on the WS, with awaits gating the adapter's push().
|
|
27
|
-
*/
|
|
28
16
|
export class ReplSession {
|
|
29
17
|
adapter;
|
|
18
|
+
detachRepl = null;
|
|
30
19
|
terminal;
|
|
31
|
-
detachReplCb = null;
|
|
32
|
-
/**
|
|
33
|
-
* REPL-R7-1 (2026-05-12): optional reference to the Nimbus shell.
|
|
34
|
-
*
|
|
35
|
-
* Required when the REPL is launched from a multi-line WS frame
|
|
36
|
-
* (e.g. user pastes `python\nexit(7)`). The shell input handler
|
|
37
|
-
* splits the frame on \r\n and pushes lines AFTER
|
|
38
|
-
* the first into `shell.pasteQueue`, which is drained ONLY when
|
|
39
|
-
* the shell becomes idle (after executeLine returns). While our
|
|
40
|
-
* REPL is running, those pasteQueue lines sit there waiting and
|
|
41
|
-
* the REPL itself receives no input → user sees a hung `>>> `
|
|
42
|
-
* prompt that never responds.
|
|
43
|
-
*
|
|
44
|
-
* If `shell` is provided, ReplSession will, immediately after
|
|
45
|
-
* attaching its replCallback, drain shell.pasteQueue and feed the
|
|
46
|
-
* lines into the callback (suffixed with \r each — matches what
|
|
47
|
-
* the WS frame originally would have looked like). This makes the
|
|
48
|
-
* paste path work transparently for REPL launches.
|
|
49
|
-
*
|
|
50
|
-
* The shell reference is optional so existing adapters (bun, node,
|
|
51
|
-
* ruby) that haven't been updated keep working with their
|
|
52
|
-
* pre-fix behavior.
|
|
53
|
-
*/
|
|
54
20
|
shellRef = null;
|
|
55
21
|
/** Current line buffer (chars typed since the last enter). */
|
|
56
22
|
lineBuf = '';
|
|
@@ -63,9 +29,11 @@ export class ReplSession {
|
|
|
63
29
|
/** Per-session history ring (most recent first). Capped at 100. */
|
|
64
30
|
history = [];
|
|
65
31
|
historyIdx = -1;
|
|
66
|
-
/** Resolves when close() has been called and the session ended. */
|
|
67
32
|
closedResolve = null;
|
|
68
33
|
closedPromise;
|
|
34
|
+
pendingInterrupt = null;
|
|
35
|
+
activePush = null;
|
|
36
|
+
ending = null;
|
|
69
37
|
/** Exit code captured from adapter's last 'exit' return. */
|
|
70
38
|
exitCode = 0;
|
|
71
39
|
/**
|
|
@@ -109,68 +77,64 @@ export class ReplSession {
|
|
|
109
77
|
// 3. Install the input handler.
|
|
110
78
|
// REPL-A1b: per-frame data appended to inputQueue; single drain
|
|
111
79
|
// task ensures serial processing across multiple WS frames.
|
|
112
|
-
this.
|
|
80
|
+
this.detachRepl = this.terminal.attachRepl((data) => {
|
|
81
|
+
// Ctrl-C is the one input byte that must not queue behind a busy
|
|
82
|
+
// push: it is the user's abort, and it only works if it runs now.
|
|
83
|
+
if (this.busy && data.includes('\x03')) {
|
|
84
|
+
this.inputQueue = '';
|
|
85
|
+
data = data.slice(data.lastIndexOf('\x03') + 1);
|
|
86
|
+
this.interruptBusy();
|
|
87
|
+
if (data.length === 0)
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (this.ending)
|
|
91
|
+
return;
|
|
113
92
|
this.inputQueue += data;
|
|
114
93
|
if (!this.draining) {
|
|
115
94
|
this.draining = true;
|
|
116
95
|
void this.drainInput();
|
|
117
96
|
}
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
// each into the replCallback as `line + \r` so handleInput
|
|
126
|
-
// processes it through the normal Enter-triggered submitLine
|
|
127
|
-
// path — same behavior as if the user had typed and pressed
|
|
128
|
-
// Enter for each line.
|
|
129
|
-
//
|
|
130
|
-
// Best-effort: if shellRef is null or pasteQueue is missing,
|
|
131
|
-
// skip silently. Mutate the queue (shift) so the shell doesn't
|
|
132
|
-
// try to re-process the same items when it drains its own queue
|
|
133
|
-
// after this REPL exits.
|
|
134
|
-
if (this.shellRef && Array.isArray(this.shellRef.pasteQueue)) {
|
|
135
|
-
const pq = this.shellRef.pasteQueue;
|
|
136
|
-
if (pq.length > 0) {
|
|
137
|
-
const drained = pq.splice(0).filter(line => line !== undefined && line !== null);
|
|
138
|
-
if (drained.length > 0) {
|
|
139
|
-
// Feed via inputQueue + draining (same path as a real WS
|
|
140
|
-
// frame). Each line ends with \r so handleInput's
|
|
141
|
-
// submitLine fires per line.
|
|
142
|
-
this.inputQueue += drained.join('\r') + '\r';
|
|
143
|
-
if (!this.draining) {
|
|
144
|
-
this.draining = true;
|
|
145
|
-
void this.drainInput();
|
|
146
|
-
}
|
|
147
|
-
}
|
|
97
|
+
}, () => this.endSession(this.exitCode));
|
|
98
|
+
const queued = this.shellRef?.takeQueuedInput() ?? [];
|
|
99
|
+
if (queued.length > 0) {
|
|
100
|
+
this.inputQueue += queued.join('\r') + '\r';
|
|
101
|
+
if (!this.draining) {
|
|
102
|
+
this.draining = true;
|
|
103
|
+
void this.drainInput();
|
|
148
104
|
}
|
|
149
105
|
}
|
|
150
106
|
// 4. Wait until close() is called.
|
|
151
107
|
await this.closedPromise;
|
|
152
108
|
return this.exitCode;
|
|
153
109
|
}
|
|
154
|
-
/**
|
|
155
|
-
* REPL-A1b: drain the input queue serially. Pulls data off
|
|
156
|
-
* inputQueue, runs handleInput, and reads any data that arrived
|
|
157
|
-
* during the await. Exits when queue is empty. Only ONE drainInput
|
|
158
|
-
* runs at a time (guarded by draining flag set in attachRepl
|
|
159
|
-
* callback).
|
|
160
|
-
*/
|
|
161
110
|
async drainInput() {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
111
|
+
try {
|
|
112
|
+
while (this.inputQueue.length > 0 && !this.ending) {
|
|
113
|
+
const chunk = this.inputQueue;
|
|
114
|
+
this.inputQueue = '';
|
|
115
|
+
await this.handleInput(chunk);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
if (!this.ending) {
|
|
120
|
+
this.terminal.write('[repl] ' + errorText(error) + '\r\n');
|
|
121
|
+
try {
|
|
122
|
+
await this.endSession(1);
|
|
123
|
+
}
|
|
124
|
+
catch { /* run() reports the cleanup failure as exit 1. */ }
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
this.draining = false;
|
|
166
129
|
}
|
|
167
|
-
this.draining = false;
|
|
168
130
|
}
|
|
169
131
|
/** Process an input chunk. May contain multiple characters (paste
|
|
170
132
|
* or rapid typing) — we iterate char-by-char to handle each
|
|
171
133
|
* control byte individually. */
|
|
172
134
|
async handleInput(data) {
|
|
173
135
|
for (let i = 0; i < data.length; i++) {
|
|
136
|
+
if (this.ending)
|
|
137
|
+
return;
|
|
174
138
|
const ch = data[i];
|
|
175
139
|
// CTRL-D (0x04): on empty line, close cleanly.
|
|
176
140
|
if (ch === '\x04') {
|
|
@@ -185,10 +149,7 @@ export class ReplSession {
|
|
|
185
149
|
// CTRL-C (0x03): cancel current line / block.
|
|
186
150
|
if (ch === '\x03') {
|
|
187
151
|
if (this.busy) {
|
|
188
|
-
|
|
189
|
-
// in v1 (no SIGINT plumbing). Buffer the cancel for after.
|
|
190
|
-
// For now: just display ^C and let the runtime finish.
|
|
191
|
-
this.terminal.write('^C\r\n');
|
|
152
|
+
this.interruptBusy();
|
|
192
153
|
continue;
|
|
193
154
|
}
|
|
194
155
|
// Idle: discard current buffer, reset, fresh prompt.
|
|
@@ -255,7 +216,20 @@ export class ReplSession {
|
|
|
255
216
|
}
|
|
256
217
|
}
|
|
257
218
|
}
|
|
258
|
-
|
|
219
|
+
interruptBusy() {
|
|
220
|
+
if (this.ending || this.pendingInterrupt)
|
|
221
|
+
return;
|
|
222
|
+
this.terminal.write('^C\r\n');
|
|
223
|
+
this.terminal.flushNow();
|
|
224
|
+
if (!this.adapter.interrupt)
|
|
225
|
+
return;
|
|
226
|
+
try {
|
|
227
|
+
this.pendingInterrupt = Promise.resolve(this.adapter.interrupt()).then(() => ({ kind: 'interrupted' }), (error) => ({ kind: 'failed', message: errorText(error) }));
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
this.pendingInterrupt = Promise.resolve({ kind: 'failed', message: errorText(error) });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
259
233
|
async submitLine() {
|
|
260
234
|
this.terminal.write('\r\n');
|
|
261
235
|
const line = this.lineBuf;
|
|
@@ -274,15 +248,31 @@ export class ReplSession {
|
|
|
274
248
|
this.busy = true;
|
|
275
249
|
let result;
|
|
276
250
|
try {
|
|
277
|
-
|
|
251
|
+
this.activePush = this.adapter.push(fullSource);
|
|
252
|
+
result = await this.activePush;
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
result = { kind: 'error', stderr: '[repl] adapter threw: ' + errorText(error) + '\n' };
|
|
278
256
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
257
|
+
finally {
|
|
258
|
+
this.activePush = null;
|
|
259
|
+
}
|
|
260
|
+
const pending = this.pendingInterrupt;
|
|
261
|
+
if (pending) {
|
|
262
|
+
const outcome = await pending;
|
|
263
|
+
if (this.pendingInterrupt === pending)
|
|
264
|
+
this.pendingInterrupt = null;
|
|
265
|
+
if (outcome.kind === 'interrupted') {
|
|
266
|
+
result = { kind: 'error', stderr: 'KeyboardInterrupt\n[repl] execution interrupted; interpreter state reset.\n' };
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
this.terminal.write('[repl] interrupt failed: ' + outcome.message + '\r\n');
|
|
270
|
+
this.terminal.flushNow();
|
|
271
|
+
}
|
|
284
272
|
}
|
|
285
273
|
this.busy = false;
|
|
274
|
+
if (this.ending)
|
|
275
|
+
return;
|
|
286
276
|
// REPL-A1 (master plan §1): emit stdout, stderr, and the next-prompt
|
|
287
277
|
// as three discrete WS frames in deterministic order. Without
|
|
288
278
|
// flushNow() between them, the 5 ms coalescer in WebSocketTerminal
|
|
@@ -364,23 +354,33 @@ export class ReplSession {
|
|
|
364
354
|
this.cursorPos = text.length;
|
|
365
355
|
this.terminal.write(text);
|
|
366
356
|
}
|
|
367
|
-
|
|
368
|
-
|
|
357
|
+
endSession(code) {
|
|
358
|
+
if (this.ending)
|
|
359
|
+
return this.ending;
|
|
369
360
|
this.exitCode = code;
|
|
370
|
-
|
|
361
|
+
this.inputQueue = '';
|
|
362
|
+
this.ending = Promise.resolve().then(async () => {
|
|
363
|
+
let failure = null;
|
|
371
364
|
try {
|
|
372
|
-
this.
|
|
365
|
+
await this.adapter.close();
|
|
373
366
|
}
|
|
374
|
-
catch {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
this.
|
|
367
|
+
catch (error) {
|
|
368
|
+
failure = error instanceof Error ? error : new Error(String(error));
|
|
369
|
+
this.exitCode = 1;
|
|
370
|
+
this.terminal.write('[repl] cleanup failed: ' + failure.message + '\r\n');
|
|
371
|
+
this.terminal.flushNow();
|
|
372
|
+
}
|
|
373
|
+
if (this.activePush)
|
|
374
|
+
await this.activePush.catch(() => { });
|
|
375
|
+
if (this.pendingInterrupt)
|
|
376
|
+
await this.pendingInterrupt;
|
|
377
|
+
this.detachRepl?.();
|
|
378
|
+
this.detachRepl = null;
|
|
379
|
+
this.closedResolve?.();
|
|
383
380
|
this.closedResolve = null;
|
|
384
|
-
|
|
381
|
+
if (failure)
|
|
382
|
+
throw failure;
|
|
383
|
+
});
|
|
384
|
+
return this.ending;
|
|
385
385
|
}
|
|
386
386
|
}
|
|
@@ -46,6 +46,8 @@
|
|
|
46
46
|
* makes a stale pin a cache miss rather than an outage.
|
|
47
47
|
*/
|
|
48
48
|
import { type ManifestFile, type RuntimeManifest } from '@nimbus-sh/core/runtime/runtime-manifest.js';
|
|
49
|
+
import { type RuntimeSource } from '@nimbus-sh/core/runtime/runtime-package.js';
|
|
50
|
+
import { type RuntimePackageAbi } from '@nimbus-sh/core/runtime/os-contracts.js';
|
|
49
51
|
/** Minimal R2Bucket shape we depend on. */
|
|
50
52
|
type R2BucketLike = {
|
|
51
53
|
get(key: string): Promise<{
|
|
@@ -102,5 +104,16 @@ export declare function fetchManifest(env: RuntimeCatalogEnv, entry: CatalogVers
|
|
|
102
104
|
* execution in whichever session installs it.
|
|
103
105
|
*/
|
|
104
106
|
export declare function fetchBlob(env: RuntimeCatalogEnv, file: ManifestFile): Promise<Uint8Array>;
|
|
107
|
+
export declare function runtimeAbiForCatalogName(name: string): RuntimePackageAbi;
|
|
108
|
+
/**
|
|
109
|
+
* The R2 catalog as a core `RuntimeSource` — the worker adapter half of the
|
|
110
|
+
* install path, so a workspace composed inside this Worker resolves
|
|
111
|
+
* `nimbus install <spec>` against the same bucket and digest chain the
|
|
112
|
+
* session's installer always used. Aliases resolve the way the old
|
|
113
|
+
* resolver did: `python` redirects to `cpython` unless a version pins it,
|
|
114
|
+
* and any bin a runtime's default manifest declares resolves to that
|
|
115
|
+
* runtime — except a superseded one, which never answers for a bin.
|
|
116
|
+
*/
|
|
117
|
+
export declare function runtimeCatalogSource(env: RuntimeCatalogEnv): RuntimeSource;
|
|
105
118
|
export {};
|
|
106
119
|
//# sourceMappingURL=runtime-catalog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-catalog.d.ts","sourceRoot":"","sources":["../../src/runtime/runtime-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAKH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,eAAe,EACrB,MAAM,6CAA6C,CAAC;AAErD,2CAA2C;AAC3C,KAAK,YAAY,GAAG;IAClB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QACxB,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;QACpC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;KACzB,GAAG,IAAI,CAAC,CAAC;CACX,GAAG,IAAI,GAAG,SAAS,CAAC;AAErB,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,oBAAoB,CAAC,EAAE,YAAY,CAAC;CACrC;AAID,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB;2EACuE;IACvE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CAC/C;AAiBD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAElE;AA4DD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAuBlF;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,eAAe,CAAC,CA8B1B;AAED;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,iBAAiB,EACtB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,UAAU,CAAC,CA4BrB"}
|
|
1
|
+
{"version":3,"file":"runtime-catalog.d.ts","sourceRoot":"","sources":["../../src/runtime/runtime-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAKH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,eAAe,EACrB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,yCAAyC,CAAC;AAEjD,2CAA2C;AAC3C,KAAK,YAAY,GAAG;IAClB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QACxB,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;QACpC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;KACzB,GAAG,IAAI,CAAC,CAAC;CACX,GAAG,IAAI,GAAG,SAAS,CAAC;AAErB,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,oBAAoB,CAAC,EAAE,YAAY,CAAC;CACrC;AAID,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB;2EACuE;IACvE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CAC/C;AAiBD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAElE;AA4DD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAuBlF;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,eAAe,CAAC,CA8B1B;AAED;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,iBAAiB,EACtB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,UAAU,CAAC,CA4BrB;AAID,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAExE;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,iBAAiB,GAAG,aAAa,CAwE1E"}
|
|
@@ -49,6 +49,9 @@ import { z } from 'zod/v4';
|
|
|
49
49
|
import { sha256Hex } from '@nimbus-sh/core/_shared/crypto.js';
|
|
50
50
|
import { RUNTIME_CATALOG_SHA256 } from '../runtime-catalog.generated.js';
|
|
51
51
|
import { HexSha256Schema, parseRuntimeManifest, } from '@nimbus-sh/core/runtime/runtime-manifest.js';
|
|
52
|
+
import { runtimeEntrypoints } from '@nimbus-sh/core/runtime/installed-runtimes.js';
|
|
53
|
+
import { splitRuntimeSpec, SUPERSEDED_RUNTIMES, } from '@nimbus-sh/core/runtime/runtime-package.js';
|
|
54
|
+
import { NIMBUS_RUNTIME_ABIS, NATIVE_UNSUPPORTED_ABI, } from '@nimbus-sh/core/runtime/os-contracts.js';
|
|
52
55
|
const CatalogVersionEntrySchema = z.object({
|
|
53
56
|
manifest: z.string().min(1),
|
|
54
57
|
manifest_sha256: HexSha256Schema.optional(),
|
|
@@ -192,6 +195,91 @@ export async function fetchBlob(env, file) {
|
|
|
192
195
|
await l2Put(verified, 'application/octet-stream');
|
|
193
196
|
return verified.bytes;
|
|
194
197
|
}
|
|
198
|
+
// ── RuntimeSource ────────────────────────────────────────────────────
|
|
199
|
+
export function runtimeAbiForCatalogName(name) {
|
|
200
|
+
return NIMBUS_RUNTIME_ABIS[name] ?? NATIVE_UNSUPPORTED_ABI;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* The R2 catalog as a core `RuntimeSource` — the worker adapter half of the
|
|
204
|
+
* install path, so a workspace composed inside this Worker resolves
|
|
205
|
+
* `nimbus install <spec>` against the same bucket and digest chain the
|
|
206
|
+
* session's installer always used. Aliases resolve the way the old
|
|
207
|
+
* resolver did: `python` redirects to `cpython` unless a version pins it,
|
|
208
|
+
* and any bin a runtime's default manifest declares resolves to that
|
|
209
|
+
* runtime — except a superseded one, which never answers for a bin.
|
|
210
|
+
*/
|
|
211
|
+
export function runtimeCatalogSource(env) {
|
|
212
|
+
return {
|
|
213
|
+
async list() {
|
|
214
|
+
const catalog = await fetchCatalog(env);
|
|
215
|
+
return Object.entries(catalog.runtimes)
|
|
216
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
217
|
+
.map(([name, entry]) => ({
|
|
218
|
+
name,
|
|
219
|
+
abi: runtimeAbiForCatalogName(name),
|
|
220
|
+
defaultVersion: entry.default,
|
|
221
|
+
versions: Object.entries(entry.versions)
|
|
222
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
223
|
+
.map(([version, v]) => ({
|
|
224
|
+
version,
|
|
225
|
+
sizeBytes: v.size_bytes,
|
|
226
|
+
license: v.license,
|
|
227
|
+
})),
|
|
228
|
+
}));
|
|
229
|
+
},
|
|
230
|
+
async resolve(spec) {
|
|
231
|
+
const { name, versionOverride } = splitRuntimeSpec(spec);
|
|
232
|
+
const catalog = await fetchCatalog(env);
|
|
233
|
+
// `python` is CPython now: a bare spec follows the supersession, an
|
|
234
|
+
// explicit `python@<version>` is a deliberate request and bypasses it.
|
|
235
|
+
const superseding = versionOverride === null ? SUPERSEDED_RUNTIMES[name] : undefined;
|
|
236
|
+
const runtimeName = (superseding !== undefined && catalog.runtimes[superseding] ? superseding : null)
|
|
237
|
+
?? (catalog.runtimes[name] ? name : null);
|
|
238
|
+
let resolved = runtimeName;
|
|
239
|
+
if (resolved === null) {
|
|
240
|
+
// Bin-name aliasing is catalog-driven: any command a runtime
|
|
241
|
+
// provides resolves to that runtime. A superseded runtime does not
|
|
242
|
+
// answer for a command name either — its runner is no longer
|
|
243
|
+
// registered, and the successor declares the same commands further
|
|
244
|
+
// down this same loop.
|
|
245
|
+
for (const [candidate, entry] of Object.entries(catalog.runtimes)) {
|
|
246
|
+
if (versionOverride === null
|
|
247
|
+
&& SUPERSEDED_RUNTIMES[candidate] !== undefined
|
|
248
|
+
&& catalog.runtimes[SUPERSEDED_RUNTIMES[candidate]])
|
|
249
|
+
continue;
|
|
250
|
+
const versionEntry = entry.versions[entry.default];
|
|
251
|
+
if (!versionEntry)
|
|
252
|
+
continue;
|
|
253
|
+
try {
|
|
254
|
+
const manifest = await fetchManifest(env, versionEntry);
|
|
255
|
+
if (runtimeEntrypoints(manifest).some((ep) => ep.binName === name)) {
|
|
256
|
+
resolved = candidate;
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
// A bad manifest should not prevent canonical catalog names from
|
|
262
|
+
// resolving; it only suppresses bin-name aliasing for that runtime.
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (resolved === null)
|
|
267
|
+
return null;
|
|
268
|
+
const entry = catalog.runtimes[resolved];
|
|
269
|
+
const version = versionOverride ?? entry.default;
|
|
270
|
+
const versionEntry = entry.versions[version];
|
|
271
|
+
if (!versionEntry) {
|
|
272
|
+
throw new Error(`'${resolved}@${version}' not in catalog`);
|
|
273
|
+
}
|
|
274
|
+
const manifest = await fetchManifest(env, versionEntry);
|
|
275
|
+
const pkg = {
|
|
276
|
+
manifest,
|
|
277
|
+
readBlob: (file) => fetchBlob(env, file),
|
|
278
|
+
};
|
|
279
|
+
return pkg;
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
}
|
|
195
283
|
/** Read the entry at `address`, or null on miss, on a stripped Cache API,
|
|
196
284
|
* or when what came back does not hash to the key it was found under. */
|
|
197
285
|
async function l2Get(address) {
|
package/dist/session/agent.d.ts
CHANGED
|
@@ -9,28 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { type SessionAiHost } from './ai.js';
|
|
11
11
|
import { type ProgrammaticHost } from './programmatic.js';
|
|
12
|
-
interface AgentStorage {
|
|
13
|
-
get(key: string): Promise<unknown>;
|
|
14
|
-
put(key: string, value: unknown): Promise<void>;
|
|
15
|
-
delete(key: string): Promise<void>;
|
|
16
|
-
deleteAll(): Promise<void>;
|
|
17
|
-
deleteAlarm(): Promise<void>;
|
|
18
|
-
list<T = unknown>(options: {
|
|
19
|
-
prefix: string;
|
|
20
|
-
}): Promise<Map<string, T>>;
|
|
21
|
-
transaction<T>(body: (txn: {
|
|
22
|
-
get(key: string): Promise<unknown>;
|
|
23
|
-
put(key: string, value: unknown): Promise<void>;
|
|
24
|
-
delete(key: string): Promise<unknown>;
|
|
25
|
-
list<T2 = unknown>(options: {
|
|
26
|
-
prefix: string;
|
|
27
|
-
}): Promise<Map<string, T2>>;
|
|
28
|
-
}) => Promise<T>): Promise<T>;
|
|
29
|
-
}
|
|
30
12
|
interface Host extends ProgrammaticHost, SessionAiHost {
|
|
31
|
-
ctx:
|
|
32
|
-
storage: AgentStorage;
|
|
33
|
-
};
|
|
13
|
+
ctx: ProgrammaticHost['ctx'];
|
|
34
14
|
env: ProgrammaticHost['env'] & Record<string, unknown>;
|
|
35
15
|
}
|
|
36
16
|
interface OAuthStatePayload {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/session/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgCH,OAAO,EASL,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAYL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/session/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgCH,OAAO,EASL,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAYL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAkB3B,UAAU,IAAK,SAAQ,gBAAgB,EAAE,aAAa;IACpD,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC7B,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxD;AAED,UAAU,iBAAiB;IACzB,CAAC,EAAE,CAAC,CAAC;IACL,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AA2BD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2ClG;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,iBAAiB,GAAG,IAAI,CAQxF"}
|
package/dist/session/ai.d.ts
CHANGED
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
*/
|
|
41
41
|
import type { LanguageModel } from 'ai';
|
|
42
42
|
import { z } from 'zod/v4';
|
|
43
|
+
import type { PortRegistry } from '@nimbus-sh/core/runtime/port-registry.js';
|
|
43
44
|
import { type NimbusCloudflareAccount } from './agent-oauth.js';
|
|
44
45
|
export interface SessionAiHost {
|
|
45
46
|
env: Record<string, unknown>;
|
|
@@ -47,10 +48,13 @@ export interface SessionAiHost {
|
|
|
47
48
|
storage: {
|
|
48
49
|
get(key: string): Promise<unknown>;
|
|
49
50
|
put(key: string, value: unknown): Promise<void>;
|
|
50
|
-
delete(key: string): Promise<void>;
|
|
51
|
+
delete(key: string): Promise<boolean | void>;
|
|
51
52
|
};
|
|
52
53
|
};
|
|
53
54
|
}
|
|
55
|
+
export declare function routeSessionLoopback(host: SessionAiHost & {
|
|
56
|
+
portRegistry: PortRegistry;
|
|
57
|
+
}, port: number, request: Request): Promise<Response | null>;
|
|
54
58
|
/** DO storage key holding this session's Cloudflare credential of record. */
|
|
55
59
|
export declare const SESSION_AI_CREDENTIAL_KEY = "nimbus:ai:credential";
|
|
56
60
|
export declare const DEFAULT_SESSION_AI_MODEL = "@cf/zai-org/glm-5.2";
|
package/dist/session/ai.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/session/ai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/session/ai.ts"],"names":[],"mappings":"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"}
|
package/dist/session/ai.js
CHANGED
|
@@ -41,8 +41,15 @@
|
|
|
41
41
|
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
|
42
42
|
import { z } from 'zod/v4';
|
|
43
43
|
import { NIMBUS_AI_GATEWAY_PORT } from '@nimbus-sh/core/constants.js';
|
|
44
|
+
import { routeRuntimeLoopback } from './loopback.js';
|
|
44
45
|
import { NIMBUS_AI_TOKEN_ENV, mintSessionAiToken } from '@nimbus-sh/core/_shared/ai-egress.js';
|
|
45
46
|
import { NIMBUS_AGENT_AUTH_COOKIE, NIMBUS_CLOUDFLARE_API, fetchNimbusCloudflareAccounts, fetchNimbusCloudflareUserInfo, loadNimbusAgentOAuthFromRequest, readNimbusAgentCookieSecret, readNimbusAgentOAuthConfig, readNimbusCookie, requestNimbusCloudflareOAuthToken, } from './agent-oauth.js';
|
|
47
|
+
export function routeSessionLoopback(host, port, request) {
|
|
48
|
+
// A credential-backed gateway is private, not a shareable port entry.
|
|
49
|
+
if (port === NIMBUS_AI_GATEWAY_PORT)
|
|
50
|
+
return handleSessionAiRequest(host, request);
|
|
51
|
+
return routeRuntimeLoopback(host.portRegistry, port, request);
|
|
52
|
+
}
|
|
46
53
|
/** DO storage key holding this session's Cloudflare credential of record. */
|
|
47
54
|
export const SESSION_AI_CREDENTIAL_KEY = 'nimbus:ai:credential';
|
|
48
55
|
/**
|
|
@@ -80,6 +80,7 @@ export declare function wireHibernationOnConstruct(ctx: any): WsHibernationConfi
|
|
|
80
80
|
* (per /api/_test/hib/simulate flow; plan §VI.7 F.2 invariant).
|
|
81
81
|
*/
|
|
82
82
|
export declare function wireProcessLogPersist(host: HibHost, ctx: any): void;
|
|
83
|
+
export declare function installLogPersistence(host: Pick<HibHost, '_w9PersistWired' | '_w9SchemaInit' | 'processes'>, ctx: DurableObjectState, onActivity: () => void): void;
|
|
83
84
|
/**
|
|
84
85
|
* W1: arm the log-janitor alarm cycle for this instance. Called from the
|
|
85
86
|
* log-activity hook so only sessions that actually produce process logs
|
|
@@ -103,7 +104,7 @@ export declare function wireProcessLogPersist(host: HibHost, ctx: any): void;
|
|
|
103
104
|
export declare function clearDestroyedTombstone(host: HibHost, ctx: any): void;
|
|
104
105
|
export declare function ensureLogJanitor(host: HibHost, ctx: any): void;
|
|
105
106
|
/** W9: idempotent SQL schema bootstrap. */
|
|
106
|
-
export declare function ensureHibSchema(host: HibHost, ctx: any): void;
|
|
107
|
+
export declare function ensureHibSchema(host: Pick<HibHost, '_w9SchemaInit'>, ctx: any): void;
|
|
107
108
|
/**
|
|
108
109
|
* W1: this session's canonical alarm-reason strings, registered on the
|
|
109
110
|
* fabric's reason map. Forward-compat: the dispatcher silently drops unknown
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hibernation.d.ts","sourceRoot":"","sources":["../../src/session/hibernation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uDAAuD,CAAC;AACtG,OAAO,EAA0B,KAAK,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AACpH,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAGrE,YAAY,EAAE,yBAAyB,EAAE,CAAC;AAE1C;;;;;;GAMG;AACH,MAAM,WAAW,OAAQ,SAAQ,SAAS;IACxC,SAAS,EAAE,wBAAwB,CAAC;IACpC,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,GAAG,CAAC;IACnB,4EAA4E;IAC5E,eAAe,EAAE,OAAO,CAAC;IACzB,uEAAuE;IACvE,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,GAAG,GAAG,yBAAyB,CAY9E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"hibernation.d.ts","sourceRoot":"","sources":["../../src/session/hibernation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uDAAuD,CAAC;AACtG,OAAO,EAA0B,KAAK,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AACpH,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAGrE,YAAY,EAAE,yBAAyB,EAAE,CAAC;AAE1C;;;;;;GAMG;AACH,MAAM,WAAW,OAAQ,SAAQ,SAAS;IACxC,SAAS,EAAE,wBAAwB,CAAC;IACpC,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,GAAG,CAAC;IACnB,4EAA4E;IAC5E,eAAe,EAAE,OAAO,CAAC;IACzB,uEAAuE;IACvE,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,GAAG,GAAG,yBAAyB,CAY9E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAKnE;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,eAAe,GAAG,WAAW,CAAC,EACtE,GAAG,EAAE,kBAAkB,EACvB,UAAU,EAAE,MAAM,IAAI,GACrB,IAAI,CA0GN;AAED;;;;;;;;;;GAUG;AACH;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAMrE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAc9D;AAED,2CAA2C;AAC3C,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAqBpF;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAEzE;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAqB9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,GAAG,EACR,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,EAC7C,oBAAoB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAC1C,SAAS,CAAC,EAAE,mBAAmB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAuCf;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAMhD"}
|
|
@@ -75,6 +75,12 @@ export function wireHibernationOnConstruct(ctx) {
|
|
|
75
75
|
* (per /api/_test/hib/simulate flow; plan §VI.7 F.2 invariant).
|
|
76
76
|
*/
|
|
77
77
|
export function wireProcessLogPersist(host, ctx) {
|
|
78
|
+
installLogPersistence(host, ctx, () => {
|
|
79
|
+
scheduleHibFlush(host, ctx);
|
|
80
|
+
ensureLogJanitor(host, ctx);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
export function installLogPersistence(host, ctx, onActivity) {
|
|
78
84
|
if (host._w9PersistWired)
|
|
79
85
|
return;
|
|
80
86
|
host._w9PersistWired = true;
|
|
@@ -174,10 +180,7 @@ export function wireProcessLogPersist(host, ctx) {
|
|
|
174
180
|
// every boot, including boots caused by a destroyed session's own
|
|
175
181
|
// leftover alarm, making every session DO ever created fire an alarm
|
|
176
182
|
// every ~60s forever (see dispatchAlarm's re-arm condition below).
|
|
177
|
-
host.processes.setLogPersist(adapter,
|
|
178
|
-
scheduleHibFlush(host, ctx);
|
|
179
|
-
ensureLogJanitor(host, ctx);
|
|
180
|
-
});
|
|
183
|
+
host.processes.setLogPersist(adapter, onActivity);
|
|
181
184
|
}
|
|
182
185
|
/**
|
|
183
186
|
* W1: arm the log-janitor alarm cycle for this instance. Called from the
|
package/dist/session/init.d.ts
CHANGED
|
@@ -1,38 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* session/init.ts — initSession boot + shell-command registrations.
|
|
3
|
-
*
|
|
4
|
-
* Why this is one big function and not a class:
|
|
5
|
-
* initSession runs once per /ws upgrade and walks the session
|
|
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.
|
|
21
|
-
*
|
|
22
|
-
* The function is intentionally written so that a reader sees:
|
|
23
|
-
* 1. setPhase('rehydrate') ...
|
|
24
|
-
* 2. setPhase('build') ... (~95% of the LOC)
|
|
25
|
-
* 3. setPhase('online') if (cold)
|
|
26
|
-
* 4. self._b4Phase = 'hydrated'
|
|
27
|
-
*
|
|
28
|
-
* `self` is typed as InitHost, a narrow view of SessionInternal plus readonly
|
|
29
|
-
* ctx/env, so this module can use the session internals it owns without
|
|
30
|
-
* depending on the full Durable Object class surface.
|
|
31
|
-
*
|
|
32
|
-
* Imports and class delegators on NimbusSession preserve back-compat:
|
|
33
|
-
* - acceptShellWebSocket → self.initSession(ws) (S7 will extract).
|
|
34
|
-
* - The class still has `initSession(ws)` as a delegator method.
|
|
35
|
-
*/
|
|
36
1
|
import type { SessionInternal } from './internal.js';
|
|
37
2
|
/**
|
|
38
3
|
* `initSession` reads `this.ctx` and `this.env` extensively (~14 sites).
|
|
@@ -61,6 +26,6 @@ type InitHost = SessionInternal & {
|
|
|
61
26
|
export interface InitSessionOptions {
|
|
62
27
|
resume?: 'reconnect' | 'wake';
|
|
63
28
|
}
|
|
64
|
-
export declare function initSession(self: InitHost, ws: WebSocket, options?: InitSessionOptions): Promise<void>;
|
|
29
|
+
export declare function initSession(self: InitHost, ws: WebSocket | null, options?: InitSessionOptions): Promise<void>;
|
|
65
30
|
export {};
|
|
66
31
|
//# sourceMappingURL=init.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/session/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/session/init.ts"],"names":[],"mappings":"AAyBA,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;AAQ3E;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;CAC/B;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,QAAQ,EACd,EAAE,EAAE,SAAS,GAAG,IAAI,EACpB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAicf"}
|