@nimbus-sh/worker 0.1.4 → 0.1.6

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 (141) hide show
  1. package/README.md +37 -0
  2. package/dist/_shared/crypto.d.ts +15 -0
  3. package/dist/_shared/crypto.d.ts.map +1 -0
  4. package/dist/_shared/crypto.js +122 -0
  5. package/dist/facets/manager.d.ts +24 -0
  6. package/dist/facets/manager.d.ts.map +1 -1
  7. package/dist/facets/manager.js +279 -70
  8. package/dist/facets/process.d.ts +11 -2
  9. package/dist/facets/process.d.ts.map +1 -1
  10. package/dist/facets/process.js +187 -21
  11. package/dist/facets/vite-dev-server.d.ts +2 -0
  12. package/dist/facets/vite-dev-server.d.ts.map +1 -1
  13. package/dist/facets/vite-dev-server.js +39 -12
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -0
  17. package/dist/loaders/child-process/spawn-facet.d.ts +1 -3
  18. package/dist/loaders/child-process/spawn-facet.d.ts.map +1 -1
  19. package/dist/loaders/child-process/spawn-facet.js +1 -12
  20. package/dist/loaders/child-process/spawn-pool.d.ts +1 -1
  21. package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
  22. package/dist/loaders/child-process/spawn-pool.js +1 -6
  23. package/dist/loaders/loader-pool.d.ts +7 -0
  24. package/dist/loaders/loader-pool.d.ts.map +1 -1
  25. package/dist/loaders/loader-pool.js +3 -1
  26. package/dist/npm/installer.d.ts.map +1 -1
  27. package/dist/npm/installer.js +47 -27
  28. package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
  29. package/dist/npm/pre-bundle-facet.js +2 -1
  30. package/dist/npm/resolve-one-facet.d.ts.map +1 -1
  31. package/dist/npm/resolve-one-facet.js +41 -13
  32. package/dist/npm/resolver.d.ts.map +1 -1
  33. package/dist/npm/resolver.js +70 -35
  34. package/dist/router/index.d.ts.map +1 -1
  35. package/dist/router/index.js +45 -21
  36. package/dist/router/remote-api.d.ts.map +1 -1
  37. package/dist/router/remote-api.js +29 -8
  38. package/dist/runtime/barrel-synthesizer.d.ts +7 -0
  39. package/dist/runtime/barrel-synthesizer.d.ts.map +1 -1
  40. package/dist/runtime/barrel-synthesizer.js +11 -0
  41. package/dist/runtime/clang-runner.d.ts +2 -2
  42. package/dist/runtime/clang-runner.d.ts.map +1 -1
  43. package/dist/runtime/clang-runner.js +64 -47
  44. package/dist/runtime/esbuild-service.d.ts +12 -5
  45. package/dist/runtime/esbuild-service.d.ts.map +1 -1
  46. package/dist/runtime/esbuild-service.js +28 -14
  47. package/dist/runtime/node-runner.d.ts +2 -0
  48. package/dist/runtime/node-runner.d.ts.map +1 -1
  49. package/dist/runtime/node-shims.d.ts +4 -2
  50. package/dist/runtime/node-shims.d.ts.map +1 -1
  51. package/dist/runtime/node-shims.js +404 -55
  52. package/dist/runtime/os-contracts.d.ts +128 -0
  53. package/dist/runtime/os-contracts.d.ts.map +1 -0
  54. package/dist/runtime/os-contracts.js +1 -0
  55. package/dist/runtime/package-manager.d.ts +31 -0
  56. package/dist/runtime/package-manager.d.ts.map +1 -1
  57. package/dist/runtime/package-manager.js +162 -15
  58. package/dist/runtime/port-registry.d.ts +5 -0
  59. package/dist/runtime/port-registry.d.ts.map +1 -1
  60. package/dist/runtime/port-registry.js +22 -1
  61. package/dist/runtime/pyodide-runtime-assets.d.ts +19 -0
  62. package/dist/runtime/pyodide-runtime-assets.d.ts.map +1 -0
  63. package/dist/runtime/pyodide-runtime-assets.js +44 -0
  64. package/dist/runtime/python-repl.d.ts +3 -0
  65. package/dist/runtime/python-repl.d.ts.map +1 -1
  66. package/dist/runtime/python-repl.js +18 -32
  67. package/dist/runtime/python-runner.d.ts +8 -9
  68. package/dist/runtime/python-runner.d.ts.map +1 -1
  69. package/dist/runtime/python-runner.js +958 -118
  70. package/dist/runtime/python-socket-shim.d.ts +11 -0
  71. package/dist/runtime/python-socket-shim.d.ts.map +1 -0
  72. package/dist/runtime/python-socket-shim.js +526 -0
  73. package/dist/runtime/require-resolver.d.ts.map +1 -1
  74. package/dist/runtime/require-resolver.js +2 -11
  75. package/dist/runtime/ruby-gems.d.ts +25 -0
  76. package/dist/runtime/ruby-gems.d.ts.map +1 -0
  77. package/dist/runtime/ruby-gems.js +582 -0
  78. package/dist/runtime/ruby-runner.d.ts +2 -4
  79. package/dist/runtime/ruby-runner.d.ts.map +1 -1
  80. package/dist/runtime/ruby-runner.js +335 -34
  81. package/dist/runtime/runtime-catalog.d.ts +16 -4
  82. package/dist/runtime/runtime-catalog.d.ts.map +1 -1
  83. package/dist/runtime/runtime-catalog.js +21 -10
  84. package/dist/runtime/runtime-registry.d.ts +3 -0
  85. package/dist/runtime/runtime-registry.d.ts.map +1 -1
  86. package/dist/runtime/runtime-registry.js +4 -0
  87. package/dist/runtime/sqlite-runtime-fs-bridge.d.ts +43 -0
  88. package/dist/runtime/sqlite-runtime-fs-bridge.d.ts.map +1 -0
  89. package/dist/runtime/sqlite-runtime-fs-bridge.js +224 -0
  90. package/dist/runtime/static-server.d.ts +3 -0
  91. package/dist/runtime/static-server.d.ts.map +1 -0
  92. package/dist/runtime/static-server.js +121 -0
  93. package/dist/runtime/vfs-snapshot.d.ts +57 -0
  94. package/dist/runtime/vfs-snapshot.d.ts.map +1 -0
  95. package/dist/runtime/vfs-snapshot.js +141 -0
  96. package/dist/runtime/virtual-socket-kernel.d.ts +16 -0
  97. package/dist/runtime/virtual-socket-kernel.d.ts.map +1 -0
  98. package/dist/runtime/virtual-socket-kernel.js +360 -0
  99. package/dist/runtime/wasi-instance.d.ts +6 -3
  100. package/dist/runtime/wasi-instance.d.ts.map +1 -1
  101. package/dist/runtime/wasm-runner.d.ts +1 -25
  102. package/dist/runtime/wasm-runner.d.ts.map +1 -1
  103. package/dist/runtime/wasm-runner.js +1 -160
  104. package/dist/session/agent.d.ts +43 -0
  105. package/dist/session/agent.d.ts.map +1 -0
  106. package/dist/session/agent.js +1252 -0
  107. package/dist/session/init.d.ts.map +1 -1
  108. package/dist/session/init.js +64 -19
  109. package/dist/session/nimbus-session.d.ts +14 -2
  110. package/dist/session/nimbus-session.d.ts.map +1 -1
  111. package/dist/session/nimbus-session.js +104 -30
  112. package/dist/session/programmatic.d.ts +10 -0
  113. package/dist/session/programmatic.d.ts.map +1 -1
  114. package/dist/session/programmatic.js +121 -0
  115. package/dist/session/routes.d.ts.map +1 -1
  116. package/dist/session/routes.js +19 -1
  117. package/dist/session/rpc.d.ts +11 -0
  118. package/dist/session/rpc.d.ts.map +1 -1
  119. package/dist/session/rpc.js +56 -43
  120. package/dist/session/supervisor-rpc.d.ts +15 -0
  121. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  122. package/dist/session/supervisor-rpc.js +32 -0
  123. package/dist/session/ws.d.ts +4 -3
  124. package/dist/session/ws.d.ts.map +1 -1
  125. package/dist/session/ws.js +11 -1
  126. package/dist/shell/unix-commands.d.ts.map +1 -1
  127. package/dist/shell/unix-commands.js +52 -51
  128. package/dist/vfs/path.d.ts +8 -4
  129. package/dist/vfs/path.d.ts.map +1 -1
  130. package/dist/vfs/path.js +16 -4
  131. package/dist/vfs/sqlite-vfs.d.ts +2 -0
  132. package/dist/vfs/sqlite-vfs.d.ts.map +1 -1
  133. package/dist/vfs/sqlite-vfs.js +11 -0
  134. package/dist/vfs/symlink-registry.d.ts +7 -1
  135. package/dist/vfs/symlink-registry.d.ts.map +1 -1
  136. package/dist/vfs/symlink-registry.js +16 -11
  137. package/package.json +4 -1
  138. package/public/index.html +240 -0
  139. package/public/s/index.html +1316 -128
  140. package/runtime-contracts/pyodide-workerd-adapter.json +18 -0
  141. package/scripts/bundle-runtime.mjs +99 -24
@@ -0,0 +1,128 @@
1
+ import type { VfsEvent } from '../vfs/events.js';
2
+ export type RuntimeFileType = 'file' | 'directory' | 'symlink';
3
+ export interface RuntimeVfsStat {
4
+ type: RuntimeFileType;
5
+ size: number;
6
+ ctime: number;
7
+ mtime: number;
8
+ mode: number;
9
+ revision: number;
10
+ }
11
+ export interface RuntimeVfsDirEntry {
12
+ name: string;
13
+ type: RuntimeFileType;
14
+ }
15
+ export interface RuntimeOpenFlags {
16
+ read?: boolean;
17
+ write?: boolean;
18
+ append?: boolean;
19
+ create?: boolean;
20
+ truncate?: boolean;
21
+ followSymlinks?: boolean;
22
+ expectedRevision?: number;
23
+ }
24
+ export interface RuntimeFileHandle {
25
+ id: number;
26
+ path: string;
27
+ flags: Required<Omit<RuntimeOpenFlags, 'expectedRevision'>> & {
28
+ expectedRevision?: number;
29
+ };
30
+ position: number;
31
+ baseRevision: number;
32
+ closed: boolean;
33
+ }
34
+ export interface RuntimeFsBridge {
35
+ stat(path: string, options?: {
36
+ followSymlinks?: boolean;
37
+ }): Promise<RuntimeVfsStat | null>;
38
+ readFile(path: string, options?: {
39
+ followSymlinks?: boolean;
40
+ }): Promise<Uint8Array | null>;
41
+ writeFile(path: string, bytes: string | Uint8Array, options?: {
42
+ createParents?: boolean;
43
+ expectedRevision?: number;
44
+ }): Promise<void>;
45
+ open(path: string, flags: RuntimeOpenFlags): Promise<RuntimeFileHandle>;
46
+ read(handleId: number, offset: number | null, length: number): Promise<Uint8Array>;
47
+ write(handleId: number, offset: number | null, bytes: Uint8Array): Promise<number>;
48
+ close(handleId: number): Promise<void>;
49
+ readdir(path: string, options?: {
50
+ followSymlinks?: boolean;
51
+ }): Promise<RuntimeVfsDirEntry[]>;
52
+ mkdir(path: string, options?: {
53
+ recursive?: boolean;
54
+ mode?: number;
55
+ }): Promise<void>;
56
+ unlink(path: string): Promise<void>;
57
+ rmdir(path: string): Promise<void>;
58
+ rename(from: string, to: string): Promise<void>;
59
+ readlink(path: string): Promise<string | null>;
60
+ symlink(target: string, path: string): Promise<void>;
61
+ fsync(handleId?: number): Promise<void>;
62
+ revision(path?: string): Promise<number>;
63
+ subscribe?(path: string, listener: (event: VfsEvent) => void): () => void;
64
+ }
65
+ export interface RuntimeProcessBridge {
66
+ spawn(command: string, args: string[], options?: {
67
+ cwd?: string;
68
+ env?: Record<string, string>;
69
+ tty?: RuntimeTtyOptions;
70
+ }): Promise<{
71
+ pid: number;
72
+ }>;
73
+ writeStdin(pid: number, bytes: string | Uint8Array): Promise<void>;
74
+ endStdin(pid: number): Promise<void>;
75
+ kill(pid: number, signal?: string): Promise<void>;
76
+ wait(pid: number, timeoutMs?: number): Promise<{
77
+ exitCode: number | null;
78
+ }>;
79
+ }
80
+ export interface RuntimeTtyOptions {
81
+ stdinIsTTY?: boolean;
82
+ stdoutIsTTY?: boolean;
83
+ stderrIsTTY?: boolean;
84
+ columns?: number;
85
+ rows?: number;
86
+ raw?: boolean;
87
+ }
88
+ export interface RuntimePortBridge {
89
+ register(port: number, processId: number, handler: (request: Request) => Promise<Response>): Promise<void>;
90
+ unregister(port: number, processId?: number): Promise<void>;
91
+ list(): Promise<Array<{
92
+ port: number;
93
+ processId: number;
94
+ registeredAt: number;
95
+ }>>;
96
+ }
97
+ export type RuntimePackageAbi = 'javascript' | 'wasm32-wasi-nimbus' | 'pyodide' | 'ruby-wasm' | 'native-unsupported';
98
+ export interface RuntimeCommandProvider {
99
+ runtimeName: string;
100
+ version: string;
101
+ abi: RuntimePackageAbi;
102
+ commands: string[];
103
+ packageManagers?: string[];
104
+ libraries?: string[];
105
+ }
106
+ export type RuntimeDiagnosticEvent = {
107
+ type: 'fs-cache';
108
+ hit: boolean;
109
+ path: string;
110
+ bytes?: number;
111
+ revision?: number;
112
+ } | {
113
+ type: 'fs-flush';
114
+ path?: string;
115
+ bytes: number;
116
+ durationMs: number;
117
+ } | {
118
+ type: 'fs-invalidation';
119
+ path: string;
120
+ revision: number;
121
+ lagMs?: number;
122
+ } | {
123
+ type: 'unsupported-abi';
124
+ packageName?: string;
125
+ abi: string;
126
+ message: string;
127
+ };
128
+ //# sourceMappingURL=os-contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"os-contracts.d.ts","sourceRoot":"","sources":["../../src/runtime/os-contracts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -27,12 +27,31 @@
27
27
  */
28
28
  import { type RuntimeCatalogEnv, type RuntimeManifest } from './runtime-catalog.js';
29
29
  import type { SqliteVFS } from '../vfs/sqlite-vfs.js';
30
+ /** Minimal shell ctx shape we depend on (matches existing handlers). */
31
+ export interface ShellCtx {
32
+ args: string[];
33
+ env: Record<string, string>;
34
+ cwd: string;
35
+ stdout: {
36
+ write(s: string): void;
37
+ };
38
+ stderr: {
39
+ write(s: string): void;
40
+ };
41
+ }
30
42
  /** Minimal shell-registry shape we depend on. */
31
43
  export interface MinShellRegistry {
32
44
  register(name: string, handler: (ctx: any) => Promise<number>): void;
33
45
  unregister?(name: string): void;
34
46
  resolve?(name: string): any;
35
47
  }
48
+ export interface RuntimeWarmTarget {
49
+ name: string;
50
+ version: string;
51
+ root: string;
52
+ manifest: RuntimeManifest;
53
+ }
54
+ export type RuntimeWarmHook = (target: RuntimeWarmTarget, ctx: ShellCtx) => Promise<void>;
36
55
  /** Runner-factory contract. Each registered runner produces a shell-
37
56
  * command handler given the manifest + the installed root dir. The
38
57
  * package manager invokes the factory at install-time + at boot-time
@@ -54,6 +73,17 @@ export interface RuntimeSummary {
54
73
  sizeBytes: number;
55
74
  license: string;
56
75
  }
76
+ export interface RuntimeInstallTarget {
77
+ runtimeName: string;
78
+ versionOverride: string | null;
79
+ requestedName: string;
80
+ }
81
+ export interface RuntimeCommandHint {
82
+ command: string;
83
+ runtimeName: string;
84
+ installSpec: string;
85
+ }
86
+ export declare function createRuntimeCommandHintResolver(env: RuntimeCatalogEnv): (command: string) => Promise<RuntimeCommandHint | null>;
57
87
  /** Compute the per-user install root for (name, version). Uses
58
88
  * `process.env.HOME` if present; falls back to `/home/user`. */
59
89
  export declare function installRoot(homeDir: string, name: string, version: string): string;
@@ -109,5 +139,6 @@ export declare function makeNimbusVerbHandler(deps: {
109
139
  /** Returns `process.env.HOME` for the session. Computed by the
110
140
  * caller (init.ts) from the shell env. */
111
141
  getHome(): string;
142
+ warmRuntime?: RuntimeWarmHook;
112
143
  }): (ctx: any) => Promise<number>;
113
144
  //# sourceMappingURL=package-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"package-manager.d.ts","sourceRoot":"","sources":["../../src/runtime/package-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"package-manager.d.ts","sourceRoot":"","sources":["../../src/runtime/package-manager.ts"],"names":[],"mappings":"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"}
@@ -34,6 +34,123 @@ export function registerRunnerFactory(key, factory) {
34
34
  export function getRegisteredRunners() {
35
35
  return Object.keys(runnerFactories);
36
36
  }
37
+ const RUNTIME_NAME_ALIASES = {
38
+ python3: 'python',
39
+ pip: 'python',
40
+ pip3: 'python',
41
+ ruby3: 'ruby',
42
+ gem: 'ruby',
43
+ bundle: 'ruby',
44
+ bundler: 'ruby',
45
+ 'wasm-ld': 'clang',
46
+ };
47
+ function runtimeEntrypoints(manifest) {
48
+ const out = [...manifest.entrypoints];
49
+ const seen = new Set(out.map((ep) => ep.binName));
50
+ const add = (binName, runner, kind) => {
51
+ if (seen.has(binName))
52
+ return;
53
+ out.push({ binName, runner, kind, args: [] });
54
+ seen.add(binName);
55
+ };
56
+ if (manifest.name === 'python') {
57
+ add('pip', 'python-runner', 'pip');
58
+ add('pip3', 'python-runner', 'pip');
59
+ }
60
+ if (manifest.name === 'ruby') {
61
+ add('gem', 'ruby-runner', 'gem');
62
+ add('bundle', 'ruby-runner', 'bundle');
63
+ add('bundler', 'ruby-runner', 'bundle');
64
+ }
65
+ return out;
66
+ }
67
+ function splitRuntimeSpec(spec) {
68
+ const atIdx = spec.indexOf('@');
69
+ return {
70
+ name: atIdx >= 0 ? spec.slice(0, atIdx) : spec,
71
+ versionOverride: atIdx >= 0 ? spec.slice(atIdx + 1) : null,
72
+ };
73
+ }
74
+ async function resolveRuntimeInstallTarget(env, catalog, spec) {
75
+ const parsed = splitRuntimeSpec(spec);
76
+ const aliased = RUNTIME_NAME_ALIASES[parsed.name] ?? parsed.name;
77
+ if (catalog.runtimes[aliased]) {
78
+ return {
79
+ runtimeName: aliased,
80
+ versionOverride: parsed.versionOverride,
81
+ requestedName: parsed.name,
82
+ };
83
+ }
84
+ for (const [runtimeName, entry] of Object.entries(catalog.runtimes)) {
85
+ const version = entry.default;
86
+ const versionEntry = entry.versions[version];
87
+ if (!versionEntry)
88
+ continue;
89
+ try {
90
+ const manifest = await fetchManifest(env, versionEntry.manifest);
91
+ if (runtimeEntrypoints(manifest).some((ep) => ep.binName === parsed.name)) {
92
+ return {
93
+ runtimeName,
94
+ versionOverride: parsed.versionOverride,
95
+ requestedName: parsed.name,
96
+ };
97
+ }
98
+ }
99
+ catch {
100
+ // A bad manifest should not prevent canonical catalog names from
101
+ // resolving; it only suppresses bin-name aliasing for that runtime.
102
+ }
103
+ }
104
+ return null;
105
+ }
106
+ export function createRuntimeCommandHintResolver(env) {
107
+ let hintsPromise = null;
108
+ const loadHints = async () => {
109
+ const catalog = await fetchCatalog(env);
110
+ const hints = new Map();
111
+ const add = (command, runtimeName) => {
112
+ if (!command || command.includes('/'))
113
+ return;
114
+ if (!hints.has(command)) {
115
+ hints.set(command, { command, runtimeName, installSpec: command });
116
+ }
117
+ };
118
+ for (const runtimeName of Object.keys(catalog.runtimes)) {
119
+ add(runtimeName, runtimeName);
120
+ }
121
+ for (const [alias, runtimeName] of Object.entries(RUNTIME_NAME_ALIASES)) {
122
+ if (catalog.runtimes[runtimeName])
123
+ add(alias, runtimeName);
124
+ }
125
+ for (const [runtimeName, entry] of Object.entries(catalog.runtimes)) {
126
+ const versionEntry = entry.versions[entry.default];
127
+ if (!versionEntry)
128
+ continue;
129
+ try {
130
+ const manifest = await fetchManifest(env, versionEntry.manifest);
131
+ for (const ep of runtimeEntrypoints(manifest))
132
+ add(ep.binName, runtimeName);
133
+ }
134
+ catch {
135
+ // Hints are best-effort UX. Install itself still surfaces the
136
+ // manifest/catalog error through the normal package-manager path.
137
+ }
138
+ }
139
+ return hints;
140
+ };
141
+ return async (command) => {
142
+ if (!command || command.includes('/'))
143
+ return null;
144
+ if (!hintsPromise) {
145
+ hintsPromise = loadHints().catch((e) => {
146
+ hintsPromise = null;
147
+ throw e;
148
+ });
149
+ }
150
+ const hints = await hintsPromise;
151
+ return hints.get(command) ?? null;
152
+ };
153
+ }
37
154
  /** Compute the per-user install root for (name, version). Uses
38
155
  * `process.env.HOME` if present; falls back to `/home/user`. */
39
156
  export function installRoot(homeDir, name, version) {
@@ -83,7 +200,7 @@ export function listInstalledManifests(vfs, homeDir) {
83
200
  export function rehydrateInstalledRuntimes(vfs, registry, homeDir) {
84
201
  const bins = [];
85
202
  for (const { root, manifest } of listInstalledManifests(vfs, homeDir)) {
86
- for (const ep of manifest.entrypoints) {
203
+ for (const ep of runtimeEntrypoints(manifest)) {
87
204
  const factory = runnerFactories[ep.runner];
88
205
  if (!factory)
89
206
  continue; // runner not registered yet — skip
@@ -99,7 +216,7 @@ export function listInstalledRuntimes(vfs, homeDir) {
99
216
  name: manifest.name,
100
217
  version: manifest.version,
101
218
  root,
102
- bins: manifest.entrypoints.map((e) => e.binName),
219
+ bins: runtimeEntrypoints(manifest).map((e) => e.binName),
103
220
  sizeBytes: manifest.files.reduce((a, f) => a + f.size, 0),
104
221
  license: manifest.license,
105
222
  }));
@@ -151,13 +268,13 @@ export async function ensureRuntimesProgrammatic(deps, specs, opts = {}) {
151
268
  * `nimbus uninstall …`. Registered under the name `nimbus`.
152
269
  */
153
270
  export function makeNimbusVerbHandler(deps) {
154
- const { env, vfs, registry, getHome } = deps;
271
+ const { env, vfs, registry, getHome, warmRuntime } = deps;
155
272
  return async function nimbus(ctx) {
156
273
  const argv = ctx.args || [];
157
274
  const verb = argv[0];
158
275
  const rest = argv.slice(1);
159
276
  if (verb === 'install') {
160
- return runInstall(rest, ctx, { env, vfs, registry, getHome });
277
+ return runInstall(rest, ctx, { env, vfs, registry, getHome, warmRuntime });
161
278
  }
162
279
  if (verb === 'uninstall') {
163
280
  return runUninstall(rest, ctx, { vfs, registry, getHome });
@@ -184,11 +301,7 @@ async function runInstall(args, ctx, deps) {
184
301
  ctx.stderr.write('usage: nimbus install <name>[@<version>]\n');
185
302
  return 2;
186
303
  }
187
- // Parse `<name>` or `<name>@<version>`.
188
304
  const spec = positional[0];
189
- const atIdx = spec.indexOf('@');
190
- const name = atIdx >= 0 ? spec.slice(0, atIdx) : spec;
191
- const versionOverride = atIdx >= 0 ? spec.slice(atIdx + 1) : null;
192
305
  // Fetch catalog.
193
306
  let catalog;
194
307
  try {
@@ -198,13 +311,16 @@ async function runInstall(args, ctx, deps) {
198
311
  ctx.stderr.write(`nimbus install: ${e?.message || e}\n`);
199
312
  return 1;
200
313
  }
201
- const runtimeEntry = catalog.runtimes[name];
202
- if (!runtimeEntry) {
203
- ctx.stderr.write(`nimbus install: '${name}' is not in catalog\n`);
314
+ const target = await resolveRuntimeInstallTarget(deps.env, catalog, spec);
315
+ if (!target) {
316
+ const parsed = splitRuntimeSpec(spec);
317
+ ctx.stderr.write(`nimbus install: '${parsed.name}' is not in catalog\n`);
204
318
  ctx.stderr.write(`nimbus install: try 'nimbus install --available' to see installable runtimes\n`);
205
319
  return 1;
206
320
  }
207
- const version = versionOverride || runtimeEntry.default;
321
+ const name = target.runtimeName;
322
+ const runtimeEntry = catalog.runtimes[name];
323
+ const version = target.versionOverride || runtimeEntry.default;
208
324
  const versionEntry = runtimeEntry.versions[version];
209
325
  if (!versionEntry) {
210
326
  ctx.stderr.write(`nimbus install: '${name}@${version}' not in catalog\n`);
@@ -219,6 +335,21 @@ async function runInstall(args, ctx, deps) {
219
335
  ctx.stdout.write(`[${name}] already installed at ${root} (use --reinstall to refetch)\n`);
220
336
  // Still re-register bins in case the registry lost them — idempotent.
221
337
  rehydrateInstalledRuntimes(deps.vfs, deps.registry, home);
338
+ let manifest = null;
339
+ try {
340
+ manifest = JSON.parse(deps.vfs.readFileString(`${root}/manifest.json`));
341
+ }
342
+ catch {
343
+ manifest = null;
344
+ }
345
+ if (manifest) {
346
+ await warmRuntimeIfConfigured(ctx, deps, {
347
+ name,
348
+ version,
349
+ root,
350
+ manifest,
351
+ });
352
+ }
222
353
  return 0;
223
354
  }
224
355
  // Fetch manifest from R2.
@@ -300,7 +431,7 @@ async function runInstall(args, ctx, deps) {
300
431
  });
301
432
  await Promise.all(workers);
302
433
  // Register entrypoints.
303
- for (const ep of manifest.entrypoints) {
434
+ for (const ep of runtimeEntrypoints(manifest)) {
304
435
  const factory = runnerFactories[ep.runner];
305
436
  if (!factory) {
306
437
  ctx.stderr.write(`[${name}] warning: runner '${ep.runner}' not registered; bin '${ep.binName}' will not be invokable\n`);
@@ -310,8 +441,24 @@ async function runInstall(args, ctx, deps) {
310
441
  deps.registry.register(ep.binName, handler);
311
442
  }
312
443
  ctx.stdout.write(`[${name}] installed at ${root} (${(totalBytes / 1024 / 1024).toFixed(1)} MiB)\n`);
444
+ await warmRuntimeIfConfigured(ctx, deps, {
445
+ name,
446
+ version,
447
+ root,
448
+ manifest,
449
+ });
313
450
  return 0;
314
451
  }
452
+ async function warmRuntimeIfConfigured(ctx, deps, target) {
453
+ if (!deps.warmRuntime)
454
+ return;
455
+ try {
456
+ await deps.warmRuntime(target, ctx);
457
+ }
458
+ catch (e) {
459
+ ctx.stderr.write(`[${target.name}] warning: runtime warm-up failed: ${e?.message || e}\n`);
460
+ }
461
+ }
315
462
  // ── --list ───────────────────────────────────────────────────────────
316
463
  async function runList(ctx, deps) {
317
464
  const home = deps.getHome();
@@ -323,7 +470,7 @@ async function runList(ctx, deps) {
323
470
  ctx.stdout.write(`installed runtimes (${installed.length}):\n`);
324
471
  for (const { root, manifest } of installed) {
325
472
  const totalBytes = manifest.files.reduce((a, f) => a + f.size, 0);
326
- const bins = manifest.entrypoints.map((e) => e.binName).join(', ');
473
+ const bins = runtimeEntrypoints(manifest).map((e) => e.binName).join(', ');
327
474
  ctx.stdout.write(` ${manifest.name}@${manifest.version} ${(totalBytes / 1024 / 1024).toFixed(1)} MiB bins=[${bins}] ${root}\n`);
328
475
  }
329
476
  return 0;
@@ -374,7 +521,7 @@ async function runUninstall(args, ctx, deps) {
374
521
  }
375
522
  for (const m of matches) {
376
523
  // Unregister bins.
377
- for (const ep of m.manifest.entrypoints) {
524
+ for (const ep of runtimeEntrypoints(m.manifest)) {
378
525
  // We don't have a guaranteed `unregister`; bins shadowing is OK
379
526
  // because boot-rehydration only re-registers what's still on disk.
380
527
  if (typeof deps.registry.unregister === 'function') {
@@ -38,6 +38,9 @@ export interface PortEntry {
38
38
  }
39
39
  export declare class PortRegistry {
40
40
  private ports;
41
+ private facetStubsByPid;
42
+ /** Remember the routeable facet stub for a running process. */
43
+ bindFacetStub(pid: number, facetStub: any): void;
41
44
  /** Register a facet as listening on a port. */
42
45
  register(port: number, pid: number, facetStub: any): void;
43
46
  /** Unregister a port. */
@@ -46,6 +49,8 @@ export declare class PortRegistry {
46
49
  unregisterByPid(pid: number): number;
47
50
  /** Look up a port entry. */
48
51
  get(port: number): PortEntry | undefined;
52
+ /** Attach a routeable facet stub to ports previously reserved by a PID. */
53
+ attachFacetStubByPid(pid: number, facetStub: any): number[];
49
54
  /** Check if a port is registered. */
50
55
  has(port: number): boolean;
51
56
  /** Get all registered ports. */
@@ -1 +1 @@
1
- {"version":3,"file":"port-registry.d.ts","sourceRoot":"","sources":["../../src/runtime/port-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,SAAS,EAAE,GAAG,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAgC;IAE7C,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,IAAI;IAIzD,yBAAyB;IACzB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC,oDAAoD;IACpD,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAWpC,4BAA4B;IAC5B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAIxC,qCAAqC;IACrC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,gCAAgC;IAChC,MAAM,IAAI,SAAS,EAAE;IAIrB;;;;;;;;;;;;;;;;;OAiBG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IA8F9F,IAAI,KAAK;;;;;;MAKR;CACF"}
1
+ {"version":3,"file":"port-registry.d.ts","sourceRoot":"","sources":["../../src/runtime/port-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,SAAS,EAAE,GAAG,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,eAAe,CAA0B;IAEjD,+DAA+D;IAC/D,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,IAAI;IAMhD,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,IAAI;IAKzD,yBAAyB;IACzB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC,oDAAoD;IACpD,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAYpC,4BAA4B;IAC5B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAIxC,2EAA2E;IAC3E,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,MAAM,EAAE;IAU3D,qCAAqC;IACrC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,gCAAgC;IAChC,MAAM,IAAI,SAAS,EAAE;IAIrB;;;;;;;;;;;;;;;;;OAiBG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IA8F9F,IAAI,KAAK;;;;;;MAKR;CACF"}
@@ -27,9 +27,18 @@
27
27
  */
28
28
  export class PortRegistry {
29
29
  ports = new Map();
30
+ facetStubsByPid = new Map();
31
+ /** Remember the routeable facet stub for a running process. */
32
+ bindFacetStub(pid, facetStub) {
33
+ if (!facetStub)
34
+ return;
35
+ this.facetStubsByPid.set(pid, facetStub);
36
+ this.attachFacetStubByPid(pid, facetStub);
37
+ }
30
38
  /** Register a facet as listening on a port. */
31
39
  register(port, pid, facetStub) {
32
- this.ports.set(port, { port, pid, facetStub, registeredAt: Date.now() });
40
+ const routeableStub = facetStub || this.facetStubsByPid.get(pid) || null;
41
+ this.ports.set(port, { port, pid, facetStub: routeableStub, registeredAt: Date.now() });
33
42
  }
34
43
  /** Unregister a port. */
35
44
  unregister(port) {
@@ -44,12 +53,24 @@ export class PortRegistry {
44
53
  count++;
45
54
  }
46
55
  }
56
+ this.facetStubsByPid.delete(pid);
47
57
  return count;
48
58
  }
49
59
  /** Look up a port entry. */
50
60
  get(port) {
51
61
  return this.ports.get(port);
52
62
  }
63
+ /** Attach a routeable facet stub to ports previously reserved by a PID. */
64
+ attachFacetStubByPid(pid, facetStub) {
65
+ const ports = [];
66
+ for (const entry of this.ports.values()) {
67
+ if (entry.pid !== pid || entry.facetStub)
68
+ continue;
69
+ entry.facetStub = facetStub;
70
+ ports.push(entry.port);
71
+ }
72
+ return ports;
73
+ }
53
74
  /** Check if a port is registered. */
54
75
  has(port) {
55
76
  return this.ports.has(port);
@@ -0,0 +1,19 @@
1
+ import type { RuntimeManifest } from './runtime-catalog.js';
2
+ import type { SqliteVFS } from '../vfs/sqlite-vfs.js';
3
+ export interface PyodideRuntimeAssetPaths {
4
+ asmWasmVfs: string | null;
5
+ asmJsVfs: string | null;
6
+ stdlibVfs: string | null;
7
+ lockfileVfs: string | null;
8
+ manifest: RuntimeManifest;
9
+ vfs: SqliteVFS;
10
+ }
11
+ export interface PyodideRuntimeFiles {
12
+ asmWasmBytes: Uint8Array;
13
+ asmJsSrc: string;
14
+ stdlibB64: string;
15
+ lockfileText: string;
16
+ }
17
+ export declare function readPyodideRuntimeFiles(args: PyodideRuntimeAssetPaths): PyodideRuntimeFiles;
18
+ export declare function uint8ToBase64(u8: Uint8Array): string;
19
+ //# sourceMappingURL=pyodide-runtime-assets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pyodide-runtime-assets.d.ts","sourceRoot":"","sources":["../../src/runtime/pyodide-runtime-assets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAWtD,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,eAAe,CAAC;IAC1B,GAAG,EAAE,SAAS,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,UAAU,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,wBAAwB,GAAG,mBAAmB,CAoB3F;AA6BD,wBAAgB,aAAa,CAAC,EAAE,EAAE,UAAU,GAAG,MAAM,CAUpD"}
@@ -0,0 +1,44 @@
1
+ import pyodideWorkerdAdapter from '../../runtime-contracts/pyodide-workerd-adapter.json';
2
+ const WORKERD_ADAPTER = pyodideWorkerdAdapter;
3
+ export function readPyodideRuntimeFiles(args) {
4
+ if (!args.asmWasmVfs || !args.asmJsVfs || !args.stdlibVfs) {
5
+ throw new Error('installed Pyodide manifest is missing required files');
6
+ }
7
+ const asmWasmBytes = args.vfs.readFile(args.asmWasmVfs);
8
+ const asmJsSrc = new TextDecoder('utf-8').decode(args.vfs.readFile(args.asmJsVfs));
9
+ const stdlibBytes = args.vfs.readFile(args.stdlibVfs);
10
+ const lockfileText = args.lockfileVfs && args.vfs.exists(args.lockfileVfs)
11
+ ? new TextDecoder('utf-8').decode(args.vfs.readFile(args.lockfileVfs))
12
+ : '{"packages":{}}';
13
+ assertPyodideWorkerdAdapter(args.manifest, asmJsSrc);
14
+ return {
15
+ asmWasmBytes,
16
+ asmJsSrc,
17
+ stdlibB64: uint8ToBase64(stdlibBytes),
18
+ lockfileText,
19
+ };
20
+ }
21
+ function assertPyodideWorkerdAdapter(manifest, asmJsSrc) {
22
+ const metadata = (manifest.runtime_artifacts || []).find((entry) => entry.path === WORKERD_ADAPTER.artifactPath && entry.kind === 'workerd-adapter');
23
+ if (!metadata) {
24
+ throw new Error(`pyodide.asm.js is missing Nimbus workerd adapter metadata (${WORKERD_ADAPTER.id}); ` +
25
+ `sync the python runtime and reinstall it with 'nimbus install python --reinstall'`);
26
+ }
27
+ if (metadata.id !== WORKERD_ADAPTER.id) {
28
+ throw new Error(`pyodide.asm.js adapter mismatch: installed ${metadata.id}, expected ${WORKERD_ADAPTER.id}`);
29
+ }
30
+ if (manifest.version !== WORKERD_ADAPTER.pyodideVersion) {
31
+ throw new Error(`Pyodide version mismatch: installed ${manifest.version}, expected ${WORKERD_ADAPTER.pyodideVersion}`);
32
+ }
33
+ if (!asmJsSrc.startsWith(WORKERD_ADAPTER.sentinel)) {
34
+ throw new Error(`pyodide.asm.js does not contain the Nimbus workerd adapter sentinel (${WORKERD_ADAPTER.id})`);
35
+ }
36
+ }
37
+ export function uint8ToBase64(u8) {
38
+ const chunk = 0x8000;
39
+ let s = '';
40
+ for (let i = 0; i < u8.length; i += chunk) {
41
+ s += String.fromCharCode.apply(null, Array.from(u8.subarray(i, Math.min(i + chunk, u8.length))));
42
+ }
43
+ return btoa(s);
44
+ }
@@ -29,6 +29,7 @@
29
29
  import type { SqliteVFS } from '../vfs/sqlite-vfs.js';
30
30
  import type { FacetManager } from '../facets/manager.js';
31
31
  import type { WebSocketTerminal } from '../facets/ws-terminal.js';
32
+ import type { RuntimeManifest } from './runtime-catalog.js';
32
33
  /** Inputs needed to bootstrap a Pyodide REPL session. */
33
34
  export interface PythonReplDeps {
34
35
  facetMgr: FacetManager;
@@ -36,6 +37,7 @@ export interface PythonReplDeps {
36
37
  terminal: WebSocketTerminal;
37
38
  /** Per-user-VFS install dir, e.g. 'home/user/.nimbus/runtimes/python/0.29.4'. */
38
39
  installRoot: string;
40
+ manifest: RuntimeManifest;
39
41
  /**
40
42
  * REPL-R7-1 (2026-05-12): optional lifo-sh Shell reference.
41
43
  *
@@ -62,4 +64,5 @@ export interface PythonReplDeps {
62
64
  * runs `python` with no args.
63
65
  */
64
66
  export declare function runPythonRepl(deps: PythonReplDeps): Promise<number>;
67
+ export declare function warmPythonRepl(deps: Pick<PythonReplDeps, 'facetMgr' | 'vfs' | 'installRoot' | 'manifest'>): Promise<void>;
65
68
  //# sourceMappingURL=python-repl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"python-repl.d.ts","sourceRoot":"","sources":["../../src/runtime/python-repl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAKlE,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,YAAY,CAAC;IACvB,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAwhBD;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAOzE"}
1
+ {"version":3,"file":"python-repl.d.ts","sourceRoot":"","sources":["../../src/runtime/python-repl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAK5D,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,YAAY,CAAC;IACvB,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,eAAe,CAAC;IAC1B;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AA8fD;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAOzE;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,KAAK,GAAG,aAAa,GAAG,UAAU,CAAC,GAC1E,OAAO,CAAC,IAAI,CAAC,CAIf"}