@nimbus-sh/worker 0.2.0 → 0.2.2

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.
Files changed (83) hide show
  1. package/dist/facets/manager.d.ts +47 -2
  2. package/dist/facets/manager.d.ts.map +1 -1
  3. package/dist/facets/manager.js +139 -15
  4. package/dist/loaders/generated-workers.d.ts +2 -2
  5. package/dist/loaders/generated-workers.d.ts.map +1 -1
  6. package/dist/loaders/generated-workers.js +3 -3
  7. package/dist/runtime/bash-repl.d.ts +1 -1
  8. package/dist/runtime/bash-repl.d.ts.map +1 -1
  9. package/dist/runtime/bash-repl.js +3 -2
  10. package/dist/runtime/cpython-resident.d.ts +27 -0
  11. package/dist/runtime/cpython-resident.d.ts.map +1 -0
  12. package/dist/runtime/cpython-resident.js +133 -0
  13. package/dist/runtime/facet-loader-host.d.ts +16 -1
  14. package/dist/runtime/facet-loader-host.d.ts.map +1 -1
  15. package/dist/runtime/facet-loader-host.js +42 -0
  16. package/dist/runtime/package-manager.d.ts +3 -58
  17. package/dist/runtime/package-manager.d.ts.map +1 -1
  18. package/dist/runtime/package-manager.js +6 -143
  19. package/dist/runtime/python-repl.d.ts +1 -1
  20. package/dist/runtime/python-repl.d.ts.map +1 -1
  21. package/dist/runtime/python-repl.js +2 -2
  22. package/dist/runtime/ruby-repl.js +1 -1
  23. package/dist/runtime/ruby-resident.d.ts +20 -0
  24. package/dist/runtime/ruby-resident.d.ts.map +1 -0
  25. package/dist/runtime/ruby-resident.js +278 -0
  26. package/dist/runtime/runtime-catalog.d.ts +4 -80
  27. package/dist/runtime/runtime-catalog.d.ts.map +1 -1
  28. package/dist/runtime/runtime-catalog.js +4 -67
  29. package/dist/session/init.d.ts +16 -7
  30. package/dist/session/init.d.ts.map +1 -1
  31. package/dist/session/init.js +210 -249
  32. package/dist/session/keys.d.ts +13 -0
  33. package/dist/session/keys.d.ts.map +1 -1
  34. package/dist/session/keys.js +13 -0
  35. package/dist/session/nimbus-session.d.ts +30 -2
  36. package/dist/session/nimbus-session.d.ts.map +1 -1
  37. package/dist/session/nimbus-session.js +49 -58
  38. package/dist/session/programmatic.d.ts +3 -3
  39. package/dist/session/programmatic.d.ts.map +1 -1
  40. package/dist/session/programmatic.js +3 -2
  41. package/dist/session/routes.js +1 -1
  42. package/dist/session/supervisor-rpc.d.ts +6 -13
  43. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  44. package/dist/session/supervisor-rpc.js +7 -17
  45. package/package.json +2 -2
  46. package/scripts/bundle-facet-workers.mjs +9 -8
  47. package/scripts/bundle-runtime.mjs +276 -44
  48. package/dist/npm/tarball-stream.d.ts +0 -93
  49. package/dist/npm/tarball-stream.d.ts.map +0 -1
  50. package/dist/npm/tarball-stream.js +0 -235
  51. package/dist/npm/tarball.d.ts +0 -34
  52. package/dist/npm/tarball.d.ts.map +0 -1
  53. package/dist/npm/tarball.js +0 -97
  54. package/dist/runtime/bash-runner.d.ts +0 -63
  55. package/dist/runtime/bash-runner.d.ts.map +0 -1
  56. package/dist/runtime/bash-runner.generated.d.ts +0 -14
  57. package/dist/runtime/bash-runner.generated.d.ts.map +0 -1
  58. package/dist/runtime/bash-runner.generated.js +0 -13
  59. package/dist/runtime/bash-runner.js +0 -291
  60. package/dist/runtime/clang-runner.d.ts +0 -37
  61. package/dist/runtime/clang-runner.d.ts.map +0 -1
  62. package/dist/runtime/clang-runner.js +0 -865
  63. package/dist/runtime/cpython-runner.d.ts +0 -71
  64. package/dist/runtime/cpython-runner.d.ts.map +0 -1
  65. package/dist/runtime/cpython-runner.js +0 -535
  66. package/dist/runtime/python-pip.d.ts +0 -38
  67. package/dist/runtime/python-pip.d.ts.map +0 -1
  68. package/dist/runtime/python-pip.js +0 -1063
  69. package/dist/runtime/ruby-gems.d.ts +0 -30
  70. package/dist/runtime/ruby-gems.d.ts.map +0 -1
  71. package/dist/runtime/ruby-gems.js +0 -636
  72. package/dist/runtime/ruby-runner.d.ts +0 -75
  73. package/dist/runtime/ruby-runner.d.ts.map +0 -1
  74. package/dist/runtime/ruby-runner.js +0 -1577
  75. package/dist/runtime/runtime-registry.d.ts +0 -162
  76. package/dist/runtime/runtime-registry.d.ts.map +0 -1
  77. package/dist/runtime/runtime-registry.js +0 -364
  78. package/dist/runtime/virtual-socket-kernel.generated.d.ts +0 -14
  79. package/dist/runtime/virtual-socket-kernel.generated.d.ts.map +0 -1
  80. package/dist/runtime/virtual-socket-kernel.generated.js +0 -13
  81. package/dist/runtime/wasm-runner.d.ts +0 -70
  82. package/dist/runtime/wasm-runner.d.ts.map +0 -1
  83. package/dist/runtime/wasm-runner.js +0 -664
@@ -1,291 +0,0 @@
1
- import { z } from 'zod';
2
- import { BASH_RUNNER_BODY_SRC } from './bash-runner.generated.js';
3
- import { flushVfsDiff, snapshotVfs } from '@nimbus-sh/core/runtime/vfs-snapshot.js';
4
- import { requireVfsCred } from '@nimbus-sh/core/runtime/os-contracts.js';
5
- import { resolveVfsPath } from '@nimbus-sh/core/vfs/path.js';
6
- import { getFacetManagerLoaderHost } from './facet-loader-host.js';
7
- const BashSliceSchema = z.object({
8
- state: z.enum(['need-input', 'exited', 'error']),
9
- exitCode: z.number().optional(),
10
- stdout: z.string().optional(),
11
- stderr: z.string().optional(),
12
- error: z.string().optional(),
13
- fsDiff: z.custom().optional(),
14
- stats: z.record(z.string(), z.unknown()).optional(),
15
- }).passthrough();
16
- function normalizeSlice(raw) {
17
- const parsed = BashSliceSchema.safeParse(raw);
18
- if (!parsed.success)
19
- return null;
20
- return {
21
- state: parsed.data.state,
22
- exitCode: Number(parsed.data.exitCode ?? 0),
23
- stdout: parsed.data.stdout || '',
24
- stderr: parsed.data.stderr || '',
25
- error: parsed.data.error,
26
- fsDiff: parsed.data.fsDiff,
27
- stats: parsed.data.stats,
28
- };
29
- }
30
- function toArrayBuffer(bytes) {
31
- const out = new ArrayBuffer(bytes.byteLength);
32
- new Uint8Array(out).set(bytes);
33
- return out;
34
- }
35
- function errorMessage(error) {
36
- if (error instanceof Error)
37
- return error.message;
38
- return String(error);
39
- }
40
- async function bashFacetStep(args) {
41
- const boot = Reflect.get(globalThis, '__bashBoot');
42
- const feed = Reflect.get(globalThis, '__bashFeed');
43
- if (typeof boot !== 'function' || typeof feed !== 'function') {
44
- return {
45
- state: 'error',
46
- exitCode: 127,
47
- stdout: '',
48
- stderr: '',
49
- error: 'bash-runner preamble missing (__bashBoot/__bashFeed not in scope)',
50
- };
51
- }
52
- return args.op === 'boot' ? boot(args) : feed(args);
53
- }
54
- export async function createBashFacetSession(deps) {
55
- const findFile = (relativePath) => {
56
- const entry = deps.manifest.files.find((file) => file.path === relativePath);
57
- return entry ? `${deps.installRoot}/${entry.path}` : null;
58
- };
59
- const bashWasmPath = findFile('share/bash/bash.async.wasm');
60
- if (!bashWasmPath || !deps.vfs.exists(bashWasmPath)) {
61
- throw new Error("bash.async.wasm missing (re-run 'nimbus install bash')");
62
- }
63
- const userEnv = { ...deps.env };
64
- userEnv.HOME ||= '/home/user';
65
- userEnv.PATH ||= '/bin:/usr/bin';
66
- userEnv.TERM ||= 'dumb';
67
- userEnv.NIMBUS_PWD = deps.cwd;
68
- userEnv.BASH_ENV ||= '/etc/nimbus.bashrc';
69
- userEnv.PWD = deps.cwd;
70
- const extraRoots = [...(deps.extraRoots ?? [])];
71
- if (userEnv.HOME !== '/home/user')
72
- extraRoots.push(userEnv.HOME);
73
- const fsSnapshot = snapshotVfs(deps.vfs, deps.cwd, { extraRoots });
74
- if ('error' in fsSnapshot)
75
- throw new Error(fsSnapshot.error);
76
- const wasmModules = {
77
- 'bash.async.wasm': toArrayBuffer(deps.vfs.readFile(bashWasmPath)),
78
- };
79
- for (const file of deps.manifest.files) {
80
- const prefix = 'share/bash/coreutils/';
81
- if (!file.path.startsWith(prefix) || !file.path.endsWith('.wasm'))
82
- continue;
83
- const name = file.path.slice(prefix.length, -'.wasm'.length);
84
- const vfsPath = `${deps.installRoot}/${file.path}`;
85
- if (deps.vfs.exists(vfsPath)) {
86
- wasmModules[`cu_${name}.wasm`] = toArrayBuffer(deps.vfs.readFile(vfsPath));
87
- }
88
- }
89
- const appletsPath = findFile('share/bash/coreutils/busybox.applets');
90
- const busyboxApplets = appletsPath && deps.vfs.exists(appletsPath)
91
- ? new TextDecoder().decode(deps.vfs.readFile(appletsPath))
92
- .split('\n')
93
- .map((line) => line.trim())
94
- .filter(Boolean)
95
- : [];
96
- const { NimbusLoaderPool } = await import('../loaders/loader-pool.js');
97
- const { env, ctx } = getFacetManagerLoaderHost(deps.facetMgr);
98
- const pool = new NimbusLoaderPool(env, ctx, {
99
- tag: 'bash-runner',
100
- concurrency: 1,
101
- omitSupervisor: true,
102
- preamble: BASH_RUNNER_PREAMBLE,
103
- wasmModules,
104
- });
105
- let active = true;
106
- let closed = false;
107
- const submit = async (args) => {
108
- const slice = normalizeSlice(await pool.submit(bashFacetStep, args, { timeoutMs: 300_000 }));
109
- if (!slice)
110
- throw new Error('facet returned an invalid payload');
111
- if (slice.state === 'exited') {
112
- if (slice.fsDiff)
113
- flushVfsDiff(deps.vfs, slice.fsDiff);
114
- active = false;
115
- }
116
- else if (slice.state === 'error') {
117
- active = false;
118
- }
119
- return slice;
120
- };
121
- try {
122
- const initial = await submit({
123
- op: 'boot',
124
- argv: deps.argv,
125
- environ: Object.entries(userEnv).map(([key, value]) => `${key}=${value}`),
126
- cwd: deps.cwd,
127
- fsSnapshot: fsSnapshot.snapshot,
128
- stdinData: deps.stdinData ?? '',
129
- stdinClosed: deps.stdinClosed,
130
- stdinTty: deps.stdinTty,
131
- busyboxApplets,
132
- });
133
- return {
134
- initial,
135
- push(data, eof = false) {
136
- if (closed)
137
- throw new Error('bash facet session is closed');
138
- return submit({ op: 'feed', data, eof });
139
- },
140
- async close() {
141
- if (closed)
142
- return;
143
- try {
144
- if (active)
145
- await submit({ op: 'feed', data: '', eof: true });
146
- }
147
- catch {
148
- // Session teardown is best-effort; the owning command already
149
- // reports dispatch failures from boot/push.
150
- }
151
- finally {
152
- closed = true;
153
- pool.dispose();
154
- }
155
- },
156
- };
157
- }
158
- catch (error) {
159
- pool.dispose();
160
- throw error;
161
- }
162
- }
163
- /** bash flags that consume the following argv element. */
164
- const BASH_OPT_WITH_ARG = new Set(['-c', '-o', '+o', '--rcfile', '--init-file']);
165
- /**
166
- * Locate the script-path argv element (first non-flag arg when -c is
167
- * absent) so the handler can resolve it against the session cwd —
168
- * bash's own cwd inside the facet starts at '/' until the BASH_ENV
169
- * chdir runs, so relative script paths must be made absolute host-side.
170
- * Returns the argv index or -1 (interactive / -c / stdin modes).
171
- */
172
- function findScriptArgIndex(argv) {
173
- for (let i = 0; i < argv.length; i++) {
174
- const a = argv[i];
175
- if (a === '--')
176
- return i + 1 < argv.length ? i + 1 : -1;
177
- if (a === '-')
178
- return -1; // read from stdin
179
- if (a.startsWith('-') || a.startsWith('+')) {
180
- if (BASH_OPT_WITH_ARG.has(a)) {
181
- if (a === '-c')
182
- return -1; // command string mode
183
- i++; // skip the option's argument
184
- }
185
- continue;
186
- }
187
- return i;
188
- }
189
- return -1;
190
- }
191
- export function makeBashRunnerFactory(deps) {
192
- return function bashRunnerFactory(manifest, installRoot, binName, _binKind) {
193
- return async function bashBinHandler(ctx) {
194
- // All VFS access (runtime wasm reads, script probes, snapshot,
195
- // fsDiff writeback) runs as the INVOKING process credential —
196
- // S2a enforcement applies to bash exactly as to ruby/python.
197
- const cred = requireVfsCred('cred' in ctx ? ctx.cred : undefined, binName);
198
- const vfs = deps.vfs.as(cred);
199
- const argv = [...(ctx.args ?? [])];
200
- const cwd = ctx.cwd || '/home/user';
201
- // Resolve a relative script path against the session cwd.
202
- const scriptIdx = findScriptArgIndex(argv);
203
- const extraRoots = [];
204
- if (scriptIdx >= 0) {
205
- const abs = resolveVfsPath(argv[scriptIdx], cwd);
206
- if (!vfs.exists(abs)) {
207
- ctx.stderr.write(`${binName}: ${argv[scriptIdx]}: No such file or directory\n`);
208
- return 127;
209
- }
210
- // Pass bash an ABSOLUTE path: the facet chdir's to the session
211
- // cwd via BASH_ENV before opening the script, so a relative arg
212
- // would resolve against cwd twice. resolveVfsPath returns a
213
- // slash-less canonical key; re-anchor it at root.
214
- argv[scriptIdx] = '/' + abs;
215
- const dir = abs.replace(/\/[^/]*$/, '');
216
- if (dir)
217
- extraRoots.push(dir);
218
- }
219
- // stdin plumbing. A terminal-backed fd 0 feeds incrementally
220
- // (interactive bash, `read` builtins); a piped stdin is drained
221
- // upfront and closed so the scheduler never parks on it.
222
- const stdinIsTty = typeof ctx.isFdTerminal === 'function' ? ctx.isFdTerminal(0) : !ctx.stdin;
223
- const feedStream = ctx.terminalStdin ?? ctx.stdin;
224
- let stdinData = '';
225
- let stdinClosed = true;
226
- if (stdinIsTty && feedStream) {
227
- stdinClosed = false;
228
- }
229
- else if (ctx.stdin) {
230
- stdinData = await ctx.stdin.readAll();
231
- }
232
- let session = null;
233
- try {
234
- session = await createBashFacetSession({
235
- facetMgr: deps.facetMgr,
236
- vfs,
237
- manifest,
238
- installRoot,
239
- argv: [binName, ...argv],
240
- env: ctx.env || {},
241
- cwd,
242
- stdinData,
243
- stdinClosed,
244
- stdinTty: stdinIsTty,
245
- extraRoots,
246
- });
247
- let slice = session.initial;
248
- for (;;) {
249
- if (slice.stdout)
250
- ctx.stdout.write(slice.stdout);
251
- if (slice.stderr)
252
- ctx.stderr.write(slice.stderr);
253
- if (slice.state === 'exited') {
254
- return slice.exitCode;
255
- }
256
- if (slice.state === 'error') {
257
- ctx.stderr.write(`${binName}: ${slice.error || 'bash facet error'}\n`);
258
- return slice.exitCode || 1;
259
- }
260
- // need-input: pull the next chunk from the terminal.
261
- let data = '';
262
- let eof = true;
263
- if (!ctx.signal.aborted && feedStream) {
264
- const chunk = await feedStream.read();
265
- if (!ctx.signal.aborted) {
266
- data = chunk === null ? '' : chunk.replace(/\r\n?/g, '\n');
267
- eof = chunk === null;
268
- }
269
- }
270
- slice = await session.push(data, eof);
271
- }
272
- }
273
- catch (e) {
274
- ctx.stderr.write(`${binName}: dispatch failed: ${errorMessage(e)}\n`);
275
- return 1;
276
- }
277
- finally {
278
- await session?.close();
279
- }
280
- };
281
- };
282
- }
283
- /**
284
- * Source string injected as the loader-pool `preamble`. The facet's module init
285
- * evaluates it verbatim so `__bashBoot` / `__bashFeed` are in scope when the
286
- * user fn runs. Self-contained — no closure captures, no imports.
287
- *
288
- * The scheduler itself lives in `bash/preamble.ts` as real TypeScript; the build
289
- * bundles it into `bash-runner.generated.ts`.
290
- */
291
- export const BASH_RUNNER_PREAMBLE = BASH_RUNNER_BODY_SRC;
@@ -1,37 +0,0 @@
1
- /**
2
- * clang-runner.ts — compile, link, and execute C programs for Nimbus WASI.
3
- *
4
- * Architecture (compile-link-run, two facet calls):
5
- *
6
- * compile : clang.wasm + sysroot subset for C includes + user .c
7
- * → produces .o bytes (returned to supervisor).
8
- * link : lld.wasm + sysroot subset for link (crt1.o + libc.a)
9
- * + .o from compile → produces .wasm executable.
10
- * write : final .wasm flushed to user VFS at the requested path.
11
- *
12
- * The filesystem both halves see is the one WASI layer every other
13
- * non-node runtime uses (wasi-instance.ts), seeded and sealed.
14
- *
15
- * Splitting compile and link into separate LOADER calls keeps each
16
- * call under the empirical loader payload ceiling. Each ships:
17
- *
18
- * - compile: 31 MiB clang.wasm + ~1.3 MiB sysroot subset (C includes).
19
- * - link : 19 MiB lld.wasm + ~0.75 MiB libs + tiny .o.
20
- *
21
- * Sysroot subset extraction happens supervisor-side via a small ustar
22
- * parser. The full sysroot.tar is parsed once when the clang runtime
23
- * warms for a session; compile/link calls reuse the filtered subsets.
24
- *
25
- * Dispatch stays direct: no sleeps, no caller-side retries, and no
26
- * catch-and-continue around loader failures.
27
- */
28
- import type { RuntimeManifest } from './runtime-catalog.js';
29
- import type { SqliteVFS } from '@nimbus-sh/core/vfs/sqlite-vfs.js';
30
- import type { FacetManager } from '../facets/manager.js';
31
- /** Build the runner factory. Closes over facetMgr + vfs. */
32
- export declare function makeClangRunnerFactory(deps: {
33
- facetMgr: FacetManager;
34
- vfs: SqliteVFS;
35
- }): (manifest: RuntimeManifest, installRoot: string, binName: string, binKind: string | undefined) => (ctx: any) => Promise<number>;
36
- export declare const CLANG_RUNNER_PREAMBLE: string;
37
- //# sourceMappingURL=clang-runner.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"clang-runner.d.ts","sourceRoot":"","sources":["../../src/runtime/clang-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAmB,SAAS,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AASzD,4DAA4D;AAC5D,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,QAAQ,EAAE,YAAY,CAAC;IACvB,GAAG,EAAE,SAAS,CAAC;CAChB,GAAG,CAAC,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,KAC7F,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,MAAM,CAAC,CAkThC;AAyjBD,eAAO,MAAM,qBAAqB,QAAiE,CAAC"}