@nimbus-sh/worker 0.6.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/README.md +2 -2
- package/dist/cirrus-npm-cjs.generated.d.ts +1 -1
- package/dist/cirrus-npm-cjs.generated.js +1 -1
- package/dist/facets/cirrus-real.d.ts.map +1 -1
- package/dist/facets/cirrus-real.js +6 -5
- package/dist/facets/compose.d.ts +148 -0
- package/dist/facets/compose.d.ts.map +1 -0
- package/dist/facets/compose.js +146 -0
- package/dist/facets/durable-images.d.ts +9 -5
- package/dist/facets/durable-images.d.ts.map +1 -1
- package/dist/facets/durable-images.js +17 -7
- package/dist/facets/esbuild-bundle-pool.d.ts +49 -0
- package/dist/facets/esbuild-bundle-pool.d.ts.map +1 -0
- package/dist/facets/esbuild-bundle-pool.js +122 -0
- package/dist/facets/exec-telemetry.d.ts +8 -0
- package/dist/facets/exec-telemetry.d.ts.map +1 -1
- package/dist/facets/manager.d.ts +240 -109
- package/dist/facets/manager.d.ts.map +1 -1
- package/dist/facets/manager.js +677 -342
- package/dist/facets/process.d.ts +20 -16
- package/dist/facets/process.d.ts.map +1 -1
- package/dist/facets/process.js +59 -28
- package/dist/facets/real-vite-fs-shim.js +2 -2
- 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/vite-dev-server.d.ts +25 -47
- package/dist/facets/vite-dev-server.d.ts.map +1 -1
- package/dist/facets/vite-dev-server.js +185 -219
- package/dist/facets/wasm-image-digest.d.ts +25 -0
- package/dist/facets/wasm-image-digest.d.ts.map +1 -0
- package/dist/facets/wasm-image-digest.js +25 -0
- package/dist/facets/wasm-swap-registry.d.ts +51 -92
- package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
- package/dist/facets/wasm-swap-registry.js +68 -227
- 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/git/network-facet.d.ts.map +1 -1
- package/dist/git/network-facet.js +6 -5
- 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/loaders/child-process/spawn-pool.d.ts +3 -2
- package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
- package/dist/loaders/child-process/spawn-pool.js +3 -2
- 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/loaders/npm-resolve-preamble.d.ts +3 -6
- package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
- package/dist/loaders/npm-resolve-preamble.js +34 -108
- package/dist/node-shims-artifact.generated.js +3 -3
- package/dist/npm/install-batch-facet.d.ts +3 -2
- package/dist/npm/install-batch-facet.d.ts.map +1 -1
- package/dist/npm/install-batch-facet.js +45 -15
- package/dist/npm/installer.d.ts +22 -17
- package/dist/npm/installer.d.ts.map +1 -1
- package/dist/npm/installer.js +209 -193
- package/dist/npm/pre-bundle-facet.d.ts +1 -1
- package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
- package/dist/npm/pre-bundle-facet.js +1 -1
- package/dist/npm/resolve-facet.d.ts +6 -0
- package/dist/npm/resolve-facet.d.ts.map +1 -1
- package/dist/npm/resolve-one-facet.d.ts +21 -20
- package/dist/npm/resolve-one-facet.d.ts.map +1 -1
- package/dist/npm/resolve-one-facet.js +85 -84
- package/dist/npm/semver.d.ts +59 -0
- package/dist/npm/semver.d.ts.map +1 -0
- package/dist/npm/semver.js +226 -0
- package/dist/router/remote-api.js +31 -1
- 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/html-entrypoint.d.ts +7 -0
- package/dist/runtime/html-entrypoint.d.ts.map +1 -1
- package/dist/runtime/html-entrypoint.js +18 -2
- package/dist/runtime/node-runner.d.ts +4 -1
- package/dist/runtime/node-runner.d.ts.map +1 -1
- package/dist/runtime/node-runner.js +9 -2
- package/dist/runtime/node-shims.d.ts.map +1 -1
- package/dist/runtime/node-shims.js +305 -29
- package/dist/runtime/opencode-facet-runner.js +16 -16
- 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/helpers.d.ts +38 -0
- package/dist/session/helpers.d.ts.map +1 -1
- package/dist/session/helpers.js +76 -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-phases.d.ts +1 -1
- package/dist/session/init-phases.d.ts.map +1 -1
- package/dist/session/init-phases.js +2 -12
- package/dist/session/init.d.ts +15 -36
- package/dist/session/init.d.ts.map +1 -1
- package/dist/session/init.js +50 -2327
- 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 +77 -34
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +126 -514
- package/dist/session/npm-install-port.d.ts +18 -0
- package/dist/session/npm-install-port.d.ts.map +1 -0
- package/dist/session/npm-install-port.js +37 -0
- package/dist/session/port-capability.d.ts +44 -0
- package/dist/session/port-capability.d.ts.map +1 -1
- package/dist/session/port-capability.js +110 -0
- package/dist/session/programmatic.d.ts +36 -43
- package/dist/session/programmatic.d.ts.map +1 -1
- package/dist/session/programmatic.js +109 -115
- package/dist/session/routes.d.ts +30 -17
- package/dist/session/routes.d.ts.map +1 -1
- package/dist/session/routes.js +42 -131
- package/dist/session/rpc.d.ts +15 -15
- package/dist/session/rpc.d.ts.map +1 -1
- package/dist/session/rpc.js +98 -49
- package/dist/session/serving-port.d.ts +27 -0
- package/dist/session/serving-port.d.ts.map +1 -0
- package/dist/session/serving-port.js +27 -0
- package/dist/session/start-real-vite.d.ts +12 -0
- package/dist/session/start-real-vite.d.ts.map +1 -1
- package/dist/session/start-real-vite.js +4 -4
- package/dist/session/supervisor-op.d.ts +4 -4
- package/dist/session/supervisor-op.d.ts.map +1 -1
- package/dist/session/supervisor-op.js +24 -10
- package/dist/session/supervisor-rpc.d.ts +7 -7
- package/dist/session/supervisor-rpc.d.ts.map +1 -1
- package/dist/session/supervisor-rpc.js +4 -0
- package/dist/session/vite-command.d.ts +18 -0
- package/dist/session/vite-command.d.ts.map +1 -0
- package/dist/session/vite-command.js +609 -0
- package/dist/session/ws.d.ts +61 -0
- package/dist/session/ws.d.ts.map +1 -1
- package/dist/session/ws.js +122 -12
- package/dist/shell/npm-bin-entrypoints.d.ts +0 -35
- package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
- package/dist/shell/npm-bin-entrypoints.js +12 -85
- 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 +34 -9
- package/public/_assets/runtime/{node-shims-9e1380d9ee430fcc.js → node-shims-8f8c64edd2a1f0f5.js} +305 -29
- package/public/index.html +1 -1
- package/scripts/bundle-facet-workers.mjs +1 -1
- package/scripts/bundle-npm-cjs.mjs +2 -2
- package/dist/facets/on-demand-bundle-gate.d.ts +0 -65
- package/dist/facets/on-demand-bundle-gate.d.ts.map +0 -1
- package/dist/facets/on-demand-bundle-gate.js +0 -125
- package/dist/npm/install-args.d.ts +0 -21
- package/dist/npm/install-args.d.ts.map +0 -1
- package/dist/npm/install-args.js +0 -70
- package/dist/npm/npm-log.d.ts +0 -31
- package/dist/npm/npm-log.d.ts.map +0 -1
- package/dist/npm/npm-log.js +0 -51
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-logs-api.d.ts","sourceRoot":"","sources":["../../src/runtime/process-logs-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uDAAuD,CAAC;AAEtG;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,wBAAwB,CAAC;IACpC;;;;OAIG;IACH,GAAG,EAAE;QACH,eAAe,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;KACvD,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"process-logs-api.d.ts","sourceRoot":"","sources":["../../src/runtime/process-logs-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uDAAuD,CAAC;AAEtG;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,wBAAwB,CAAC;IACpC;;;;OAIG;IACH,GAAG,EAAE;QACH,eAAe,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;KACvD,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,SAAS,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,YAAY,GAAG,IAAI,EAC7B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI,CAON;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,iBAAiB,GACtB,QAAQ,CA8EV;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,wBAAwB,EACnC,GAAG,EAAE;IAAE,aAAa,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,CAAA;CAAE,GACjD,IAAI,CA8CN;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,wBAAwB,GAClC,QAAQ,CAsCV;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK7D"}
|
|
@@ -30,7 +30,7 @@ export function notifyTerminalEvent(terminal, event) {
|
|
|
30
30
|
if (!terminal)
|
|
31
31
|
return;
|
|
32
32
|
try {
|
|
33
|
-
terminal.ws
|
|
33
|
+
terminal.ws?.send(JSON.stringify(event));
|
|
34
34
|
}
|
|
35
35
|
catch {
|
|
36
36
|
/* socket closed or congested — dropping is the right behavior here */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Shell } from '@nimbus-sh/core/substrate/lifo/shell/Shell.js';
|
|
1
2
|
/**
|
|
2
3
|
* python-repl.ts — the interactive `python` prompt.
|
|
3
4
|
*
|
|
@@ -40,7 +41,7 @@ export interface PythonReplDeps {
|
|
|
40
41
|
* ReplSession lets it drain that queue on attach, which is the difference
|
|
41
42
|
* between the pasted tail arriving and the prompt hanging.
|
|
42
43
|
*/
|
|
43
|
-
shell?:
|
|
44
|
+
shell?: Pick<Shell, 'takeQueuedInput'>;
|
|
44
45
|
/**
|
|
45
46
|
* The invoking process's pid.
|
|
46
47
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python-repl.d.ts","sourceRoot":"","sources":["../../src/runtime/python-repl.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"python-repl.d.ts","sourceRoot":"","sources":["../../src/runtime/python-repl.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,+CAA+C,CAAC;AAE3E;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAoBnF,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,YAAY,CAAC;IACvB,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,mFAAmF;IACnF,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,eAAe,CAAC;IAC1B;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;IACvC;;;;;;;;OAQG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAySD,wBAAsB,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAIzE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,KAAK,GAAG,aAAa,GAAG,UAAU,CAAC,GAC1E,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
|
@@ -1,24 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* A long-lived facet holds one interpreter and each submitted line is run in
|
|
5
|
-
* it, so definitions, imports and open files survive between prompts. That is
|
|
6
|
-
* the whole reason the interpreter is built as a WASI reactor: a command
|
|
7
|
-
* module's _start runs once.
|
|
8
|
-
*
|
|
9
|
-
* Incompleteness is decided by `codeop.compile_command`, which is what the real
|
|
10
|
-
* Python REPL uses — it returns None for source that is syntactically fine so
|
|
11
|
-
* far but unfinished (an open bracket, a `def` with no body yet), raises
|
|
12
|
-
* SyntaxError for source that can never complete, and otherwise hands back a
|
|
13
|
-
* code object. That distinction is not something to re-derive from error
|
|
14
|
-
* strings; the previous Pyodide implementation asked PyodideConsole for it,
|
|
15
|
-
* which is the same idea reached through a Pyodide-only object.
|
|
16
|
-
*
|
|
17
|
-
* Compiling in 'single' mode also gets the echo right for free: an expression
|
|
18
|
-
* statement goes through sys.displayhook exactly as it does at a real prompt,
|
|
19
|
-
* so `1 + 1` prints `2` and `x = 1` prints nothing, with no wrapper of ours
|
|
20
|
-
* deciding what counts as a result.
|
|
21
|
-
*/
|
|
1
|
+
import { IsolatePool } from '@nimbus-sh/fabric/isolate-pool.js';
|
|
2
|
+
import { manifestVfs } from '@nimbus-sh/core/runtime/vfs-manifest.js';
|
|
3
|
+
import { z } from 'zod/v4';
|
|
22
4
|
import { ReplSession } from './repl-session.js';
|
|
23
5
|
import { sessionUsesSciVariant } from '@nimbus-sh/core/runtime/python-pip.js';
|
|
24
6
|
import { buildCPythonPreamble } from '@nimbus-sh/core/runtime/cpython-runner.js';
|
|
@@ -35,6 +17,8 @@ const INCOMPLETE_MARKER = '__NIMBUS_PY_INCOMPLETE__';
|
|
|
35
17
|
* ordinary output and never leaves.
|
|
36
18
|
*/
|
|
37
19
|
const EXIT_MARKER = '__NIMBUS_PY_EXIT__';
|
|
20
|
+
const PythonFacetResult = z.object({ stdout: z.string(), stderr: z.string(), exitCode: z.number().int(), error: z.string().optional() });
|
|
21
|
+
const PythonFacetFailure = z.object({ __nimbusFacetError: z.string() });
|
|
38
22
|
/** Where cpython-runner's catalog spec stages the interpreter. */
|
|
39
23
|
const CPYTHON_WASM_REL = 'share/cpython/python.wasm';
|
|
40
24
|
const CPYTHON_SCI_WASM_REL = 'share/cpython/python-sci.wasm';
|
|
@@ -102,13 +86,25 @@ class PythonReplAdapter {
|
|
|
102
86
|
return ('Python 3.13.14 (CPython, wasm32-wasi, Nimbus runtime)\r\n' +
|
|
103
87
|
'Type "exit()" or press Ctrl-D to exit.\r\n');
|
|
104
88
|
}
|
|
105
|
-
|
|
89
|
+
push(source) {
|
|
90
|
+
const controller = new AbortController();
|
|
91
|
+
const done = this.evaluate(source, controller.signal);
|
|
92
|
+
const active = { controller, done };
|
|
93
|
+
this.active = active;
|
|
94
|
+
const clear = () => { if (this.active === active)
|
|
95
|
+
this.active = null; };
|
|
96
|
+
void done.then(clear, clear);
|
|
97
|
+
return done;
|
|
98
|
+
}
|
|
99
|
+
async evaluate(source, signal) {
|
|
106
100
|
const trimmed = source.trim();
|
|
107
101
|
if (trimmed === 'exit' || trimmed === 'quit') {
|
|
108
102
|
return { kind: 'output', stdout: '', stderr: 'Use exit() or Ctrl-D to exit\n' };
|
|
109
103
|
}
|
|
110
104
|
try {
|
|
105
|
+
signal.throwIfAborted();
|
|
111
106
|
await this.ensurePool();
|
|
107
|
+
signal.throwIfAborted();
|
|
112
108
|
}
|
|
113
109
|
catch (e) {
|
|
114
110
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -116,7 +112,7 @@ class PythonReplAdapter {
|
|
|
116
112
|
}
|
|
117
113
|
let result;
|
|
118
114
|
try {
|
|
119
|
-
result = await this.submit(buildReplDriver(source));
|
|
115
|
+
result = await this.submit(buildReplDriver(source), signal);
|
|
120
116
|
}
|
|
121
117
|
catch (e) {
|
|
122
118
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -149,13 +145,22 @@ class PythonReplAdapter {
|
|
|
149
145
|
}
|
|
150
146
|
return { kind: 'output', stdout: result.stdout, stderr: result.stderr };
|
|
151
147
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
148
|
+
close() { return this.interrupt(); }
|
|
149
|
+
resetPool() {
|
|
150
|
+
const pool = this.pool;
|
|
151
|
+
this.pool = null;
|
|
152
|
+
this.wasmBytes = null;
|
|
153
|
+
this.fsSnapshot = null;
|
|
154
|
+
pool?.dispose();
|
|
155
|
+
}
|
|
156
|
+
async interrupt() {
|
|
157
|
+
const active = this.active;
|
|
158
|
+
active?.controller.abort();
|
|
159
|
+
try {
|
|
160
|
+
await active?.done;
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
this.resetPool();
|
|
159
164
|
}
|
|
160
165
|
}
|
|
161
166
|
async ensurePool() {
|
|
@@ -166,11 +171,7 @@ class PythonReplAdapter {
|
|
|
166
171
|
// interpreter that does not have it. Dropping the pool rebuilds on the next
|
|
167
172
|
// statement, which is the facet restart EXTENSIONS.md says this costs.
|
|
168
173
|
if (this.pool && this.poolUsesSci !== wantsSci) {
|
|
169
|
-
|
|
170
|
-
this.pool.dispose?.();
|
|
171
|
-
}
|
|
172
|
-
catch { /* fail-soft: it is being replaced */ }
|
|
173
|
-
this.pool = null;
|
|
174
|
+
this.resetPool();
|
|
174
175
|
}
|
|
175
176
|
if (this.pool)
|
|
176
177
|
return;
|
|
@@ -186,7 +187,6 @@ class PythonReplAdapter {
|
|
|
186
187
|
throw new Error(`python313.zip missing at ${stdlibPath} (run 'nimbus install python')`);
|
|
187
188
|
}
|
|
188
189
|
this.wasmBytes = toArrayBuffer(vfs.readFile(wasmPath));
|
|
189
|
-
const { manifestVfs } = await import('@nimbus-sh/core/runtime/vfs-manifest.js');
|
|
190
190
|
// The install root is the Python prefix, so the manifest covers lib/ and
|
|
191
191
|
// etc/ as they are — nothing is aliased into a path the supervisor could
|
|
192
192
|
// not serve.
|
|
@@ -207,7 +207,6 @@ class PythonReplAdapter {
|
|
|
207
207
|
snapshot.files[stdlibPath.replace(/^\/+/, '')] = btoa(bin);
|
|
208
208
|
this.fsSnapshot = snapshot;
|
|
209
209
|
this.pythonHome = `/${installRoot.replace(/^\/+/, '')}`;
|
|
210
|
-
const { IsolatePool } = await import('@nimbus-sh/fabric/isolate-pool.js');
|
|
211
210
|
const host = getFacetManagerLoaderHost(facetMgr);
|
|
212
211
|
// A prompt where `open(path, "w")` silently does nothing is worse than one
|
|
213
212
|
// that refuses to start, so the pid decides which pool this is. Written as
|
|
@@ -219,43 +218,65 @@ class PythonReplAdapter {
|
|
|
219
218
|
// Distinct from cpython-runner's tag: a REPL facet holds a live
|
|
220
219
|
// interpreter and must never be handed a one-shot invocation.
|
|
221
220
|
tag: wantsSci ? 'python-repl:sci' : 'python-repl',
|
|
221
|
+
scope: crypto.randomUUID(),
|
|
222
222
|
concurrency: 1,
|
|
223
223
|
preamble: buildCPythonPreamble(),
|
|
224
224
|
wasmModules: { 'python.wasm': this.wasmBytes },
|
|
225
225
|
};
|
|
226
226
|
const pid = this.deps.pid;
|
|
227
|
-
this.pool =
|
|
227
|
+
this.pool = typeof pid === 'number' && pid > 0
|
|
228
228
|
? new IsolatePool(host.env, host.ctx, { ...base, supervisorPid: pid })
|
|
229
229
|
// The install-time warm-up has no invoking process. It boots the
|
|
230
230
|
// interpreter and never touches a file, so it asks for no supervisor
|
|
231
231
|
// rather than binding one it cannot authenticate to.
|
|
232
|
-
: new IsolatePool(host.env, host.ctx, { ...base, omitSupervisor: true })
|
|
232
|
+
: new IsolatePool(host.env, host.ctx, { ...base, omitSupervisor: true });
|
|
233
233
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
234
|
+
active = null;
|
|
235
|
+
async submit(userCode, signal) {
|
|
236
|
+
const pool = this.pool;
|
|
237
|
+
if (!pool || !this.fsSnapshot)
|
|
238
|
+
throw new Error('Python REPL is not initialized');
|
|
239
|
+
const response = await pool.submitRequest(pythonReplStepRequestFn, new Request('https://facet.internal/python-repl-step', {
|
|
240
|
+
method: 'POST',
|
|
241
|
+
body: JSON.stringify({
|
|
242
|
+
userCode,
|
|
243
|
+
pythonHome: this.pythonHome,
|
|
244
|
+
pyArgv: ['python'],
|
|
245
|
+
userEnv: { HOME: '/home/user', PYTHONUNBUFFERED: '1' },
|
|
246
|
+
progName: 'python',
|
|
247
|
+
cwd: '/home/user',
|
|
248
|
+
fsSnapshot: this.fsSnapshot,
|
|
249
|
+
}),
|
|
250
|
+
signal,
|
|
251
|
+
}), { timeoutMs: 60_000 });
|
|
252
|
+
if (!response.ok) {
|
|
253
|
+
const failure = PythonFacetFailure.parse(await response.json());
|
|
254
|
+
throw new Error(failure.__nimbusFacetError);
|
|
255
|
+
}
|
|
256
|
+
return PythonFacetResult.parse(await response.json());
|
|
245
257
|
}
|
|
246
258
|
}
|
|
247
259
|
/**
|
|
248
|
-
* Facet-side
|
|
249
|
-
*
|
|
250
|
-
*
|
|
260
|
+
* Facet-side, request-shaped: serialized with fn.toString() into the
|
|
261
|
+
* pool's fetch entrypoint, so it captures nothing and names no import —
|
|
262
|
+
* __cpythonReplRun is put on globalThis by the preamble, and unlike
|
|
263
|
+
* __cpythonRun it keeps its interpreter between calls. The request body
|
|
264
|
+
* is the step payload the adapter JSON-encodes; the response is the
|
|
265
|
+
* step result. Request transport because it is the pool's only
|
|
266
|
+
* cancellable dispatch: Ctrl-C aborts the request, workerd stops the
|
|
267
|
+
* interpreter at its suspension point.
|
|
251
268
|
*/
|
|
252
|
-
async function
|
|
269
|
+
async function pythonReplStepRequestFn(request, facetEnv) {
|
|
270
|
+
const args = await request.json();
|
|
271
|
+
if (typeof args !== 'object' || args === null || !('userCode' in args) || typeof args.userCode !== 'string') {
|
|
272
|
+
throw new Error('Python REPL request must contain userCode');
|
|
273
|
+
}
|
|
253
274
|
const run = Reflect.get(globalThis, '__cpythonReplRun');
|
|
254
275
|
if (typeof run !== 'function') {
|
|
255
|
-
return {
|
|
276
|
+
return Response.json({
|
|
256
277
|
stdout: '', stderr: '', exitCode: 127,
|
|
257
278
|
error: 'cpython preamble missing: __cpythonReplRun not in scope',
|
|
258
|
-
};
|
|
279
|
+
});
|
|
259
280
|
}
|
|
260
281
|
const adopt = Reflect.get(globalThis, '__wasiAdoptSupervisor');
|
|
261
282
|
const drain = Reflect.get(globalThis, '__wasiDrainPersist');
|
|
@@ -266,13 +287,15 @@ async function pythonReplStepFacetFn(args, facetEnv) {
|
|
|
266
287
|
// filesystem it could read.
|
|
267
288
|
if (supervisor)
|
|
268
289
|
Reflect.set(globalThis, '__nimbusPySupervisor', supervisor);
|
|
269
|
-
adopt
|
|
290
|
+
if (typeof adopt === 'function')
|
|
291
|
+
Reflect.apply(adopt, undefined, [supervisor ?? null]);
|
|
270
292
|
try {
|
|
271
|
-
return await run(args);
|
|
293
|
+
return Response.json(await run(args));
|
|
272
294
|
}
|
|
273
295
|
finally {
|
|
274
296
|
// A line that wrote a file and then raised still wrote the file.
|
|
275
|
-
|
|
297
|
+
if (typeof drain === 'function')
|
|
298
|
+
await drain();
|
|
276
299
|
}
|
|
277
300
|
}
|
|
278
301
|
export async function runPythonRepl(deps) {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* interface declared below.
|
|
13
13
|
*/
|
|
14
14
|
import type { WebSocketTerminal } from '../facets/ws-terminal.js';
|
|
15
|
+
import type { Shell } from '@nimbus-sh/core/substrate/lifo/shell/Shell.js';
|
|
15
16
|
/**
|
|
16
17
|
* Per-runtime adapter contract. The shell-side ReplSession orchestrates
|
|
17
18
|
* input handling; the adapter wraps the actual runtime invocation.
|
|
@@ -30,6 +31,8 @@ export interface ReplAdapter {
|
|
|
30
31
|
/** Called once on session close (exit() / Ctrl-D / shell teardown).
|
|
31
32
|
* Should free any cached pool / isolate. Idempotent. */
|
|
32
33
|
close(): Promise<void>;
|
|
34
|
+
/** Abort and settle the active push, resetting its interpreter before resolving. */
|
|
35
|
+
interrupt?(): void | Promise<void>;
|
|
33
36
|
/** Primary prompt (typically '>>> '). */
|
|
34
37
|
ps1: string;
|
|
35
38
|
/** Continuation prompt (typically '... '). */
|
|
@@ -50,45 +53,10 @@ export type ReplPushResult = {
|
|
|
50
53
|
kind: 'error';
|
|
51
54
|
stderr: string;
|
|
52
55
|
};
|
|
53
|
-
/**
|
|
54
|
-
* Manages an interactive REPL session: stdin buffering with minimal
|
|
55
|
-
* readline UX (line-mode), output routing to the WS terminal, prompt
|
|
56
|
-
* rendering, and adapter dispatch.
|
|
57
|
-
*
|
|
58
|
-
* The shell creates a ReplSession when a runtime's `startRepl` hook
|
|
59
|
-
* fires; the session installs a `replCallback` on the WebSocketTerminal
|
|
60
|
-
* (via attachRepl()) and runs until the adapter signals 'exit' or the
|
|
61
|
-
* user presses Ctrl-D on an empty line.
|
|
62
|
-
*
|
|
63
|
-
* No setTimeout in the read loop — the session is driven entirely by
|
|
64
|
-
* keystroke arrival on the WS, with awaits gating the adapter's push().
|
|
65
|
-
*/
|
|
66
56
|
export declare class ReplSession {
|
|
67
57
|
private adapter;
|
|
58
|
+
private detachRepl;
|
|
68
59
|
private terminal;
|
|
69
|
-
private detachReplCb;
|
|
70
|
-
/**
|
|
71
|
-
* REPL-R7-1 (2026-05-12): optional reference to the Nimbus shell.
|
|
72
|
-
*
|
|
73
|
-
* Required when the REPL is launched from a multi-line WS frame
|
|
74
|
-
* (e.g. user pastes `python\nexit(7)`). The shell input handler
|
|
75
|
-
* splits the frame on \r\n and pushes lines AFTER
|
|
76
|
-
* the first into `shell.pasteQueue`, which is drained ONLY when
|
|
77
|
-
* the shell becomes idle (after executeLine returns). While our
|
|
78
|
-
* REPL is running, those pasteQueue lines sit there waiting and
|
|
79
|
-
* the REPL itself receives no input → user sees a hung `>>> `
|
|
80
|
-
* prompt that never responds.
|
|
81
|
-
*
|
|
82
|
-
* If `shell` is provided, ReplSession will, immediately after
|
|
83
|
-
* attaching its replCallback, drain shell.pasteQueue and feed the
|
|
84
|
-
* lines into the callback (suffixed with \r each — matches what
|
|
85
|
-
* the WS frame originally would have looked like). This makes the
|
|
86
|
-
* paste path work transparently for REPL launches.
|
|
87
|
-
*
|
|
88
|
-
* The shell reference is optional so existing adapters (bun, node,
|
|
89
|
-
* ruby) that haven't been updated keep working with their
|
|
90
|
-
* pre-fix behavior.
|
|
91
|
-
*/
|
|
92
60
|
private shellRef;
|
|
93
61
|
/** Current line buffer (chars typed since the last enter). */
|
|
94
62
|
private lineBuf;
|
|
@@ -101,9 +69,11 @@ export declare class ReplSession {
|
|
|
101
69
|
/** Per-session history ring (most recent first). Capped at 100. */
|
|
102
70
|
private history;
|
|
103
71
|
private historyIdx;
|
|
104
|
-
/** Resolves when close() has been called and the session ended. */
|
|
105
72
|
private closedResolve;
|
|
106
73
|
private closedPromise;
|
|
74
|
+
private pendingInterrupt;
|
|
75
|
+
private activePush;
|
|
76
|
+
private ending;
|
|
107
77
|
/** Exit code captured from adapter's last 'exit' return. */
|
|
108
78
|
private exitCode;
|
|
109
79
|
/**
|
|
@@ -124,23 +94,16 @@ export declare class ReplSession {
|
|
|
124
94
|
*/
|
|
125
95
|
private inputQueue;
|
|
126
96
|
private draining;
|
|
127
|
-
constructor(adapter: ReplAdapter, terminal: WebSocketTerminal, shell?:
|
|
97
|
+
constructor(adapter: ReplAdapter, terminal: WebSocketTerminal, shell?: Pick<Shell, 'takeQueuedInput'>);
|
|
128
98
|
/** Run the session: prints banner, installs the input hook, returns
|
|
129
99
|
* a promise that resolves with the exit code when the session ends. */
|
|
130
100
|
run(): Promise<number>;
|
|
131
|
-
/**
|
|
132
|
-
* REPL-A1b: drain the input queue serially. Pulls data off
|
|
133
|
-
* inputQueue, runs handleInput, and reads any data that arrived
|
|
134
|
-
* during the await. Exits when queue is empty. Only ONE drainInput
|
|
135
|
-
* runs at a time (guarded by draining flag set in attachRepl
|
|
136
|
-
* callback).
|
|
137
|
-
*/
|
|
138
101
|
private drainInput;
|
|
139
102
|
/** Process an input chunk. May contain multiple characters (paste
|
|
140
103
|
* or rapid typing) — we iterate char-by-char to handle each
|
|
141
104
|
* control byte individually. */
|
|
142
105
|
private handleInput;
|
|
143
|
-
|
|
106
|
+
private interruptBusy;
|
|
144
107
|
private submitLine;
|
|
145
108
|
/** Map up-arrow → previous history entry. */
|
|
146
109
|
private historyUp;
|
|
@@ -148,7 +111,6 @@ export declare class ReplSession {
|
|
|
148
111
|
private historyDown;
|
|
149
112
|
/** Erase the current displayed line and replace with `text`. */
|
|
150
113
|
private replaceCurrentLine;
|
|
151
|
-
/** Close the session: detach input hook, free adapter, resolve. */
|
|
152
114
|
private endSession;
|
|
153
115
|
}
|
|
154
116
|
//# sourceMappingURL=repl-session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repl-session.d.ts","sourceRoot":"","sources":["../../src/runtime/repl-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"repl-session.d.ts","sourceRoot":"","sources":["../../src/runtime/repl-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,+CAA+C,CAAC;AAI3E;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;mCAC+B;IAC/B,MAAM,IAAI,MAAM,CAAC;IACjB;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC5C;6DACyD;IACzD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,oFAAoF;IACpF,SAAS,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAiBtC,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,QAAQ,CAA+C;IAE/D,8DAA8D;IAC9D,OAAO,CAAC,OAAO,CAAc;IAC7B,sDAAsD;IACtD,OAAO,CAAC,SAAS,CAAa;IAC9B,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAgB;IAChC,8EAA8E;IAC9E,OAAO,CAAC,IAAI,CAAkB;IAC9B,mEAAmE;IACnE,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,gBAAgB,CAA0C;IAClE,OAAO,CAAC,UAAU,CAAwC;IAC1D,OAAO,CAAC,MAAM,CAA8B;IAE5C,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAa;IAC7B;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,QAAQ,CAAkB;gBAEtB,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAUrG;4EACwE;IAClE,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;YAuCd,UAAU;IAiBxB;;qCAEiC;YACnB,WAAW;IA0EzB,OAAO,CAAC,aAAa;YAiBP,UAAU;IA0FxB,6CAA6C;IAC7C,OAAO,CAAC,SAAS;IAMjB,mDAAmD;IACnD,OAAO,CAAC,WAAW;IAUnB,gEAAgE;IAChE,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,UAAU;CAwBnB"}
|