@nimbus-sh/core 0.3.0 → 0.4.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.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +112 -0
  3. package/dist/_shared/tarball-stream.d.ts +93 -0
  4. package/dist/_shared/tarball-stream.d.ts.map +1 -0
  5. package/dist/_shared/tarball-stream.js +235 -0
  6. package/dist/_shared/tarball.d.ts +17 -0
  7. package/dist/_shared/tarball.d.ts.map +1 -0
  8. package/dist/_shared/tarball.js +39 -0
  9. package/dist/runtime/clang-runner.d.ts +38 -0
  10. package/dist/runtime/clang-runner.d.ts.map +1 -0
  11. package/dist/runtime/clang-runner.js +866 -0
  12. package/dist/runtime/facet-host.d.ts +12 -0
  13. package/dist/runtime/facet-host.d.ts.map +1 -1
  14. package/dist/runtime/local-facet-host.d.ts.map +1 -1
  15. package/dist/runtime/local-facet-host.js +29 -9
  16. package/dist/runtime/ruby-gems.d.ts +30 -0
  17. package/dist/runtime/ruby-gems.d.ts.map +1 -0
  18. package/dist/runtime/ruby-gems.js +636 -0
  19. package/dist/runtime/ruby-runner.d.ts +127 -0
  20. package/dist/runtime/ruby-runner.d.ts.map +1 -0
  21. package/dist/runtime/ruby-runner.js +1357 -0
  22. package/dist/runtime/session-process-supervisor.d.ts +15 -0
  23. package/dist/runtime/session-process-supervisor.d.ts.map +1 -1
  24. package/dist/runtime/session-process-supervisor.js +30 -0
  25. package/dist/workspace/nimbus-workspace.d.ts.map +1 -1
  26. package/dist/workspace/nimbus-workspace.js +9 -2
  27. package/package.json +4 -2
  28. package/src/_shared/tarball-stream.ts +263 -0
  29. package/src/_shared/tarball.ts +46 -0
  30. package/src/runtime/clang-runner.ts +924 -0
  31. package/src/runtime/facet-host.ts +12 -0
  32. package/src/runtime/local-facet-host.ts +28 -8
  33. package/src/runtime/ruby-gems.ts +682 -0
  34. package/src/runtime/ruby-runner.ts +1484 -0
  35. package/src/runtime/session-process-supervisor.ts +27 -0
  36. package/src/workspace/nimbus-workspace.ts +10 -1
@@ -67,6 +67,8 @@ export class SessionProcessSupervisor {
67
67
  private terminators = new Map<number, () => void>();
68
68
  /** Fires after every appendOutput/markExit once log persistence is wired. */
69
69
  private logActivity: (() => void) | null = null;
70
+ /** Fires once per pid on its first terminal transition; see setOnTerminal. */
71
+ private onTerminalCb: ((pid: number) => void) | null = null;
70
72
 
71
73
  // ── Lifecycle / PID authority ─────────────────────────────────────────
72
74
 
@@ -130,10 +132,33 @@ export class SessionProcessSupervisor {
130
132
  return this.table.setUmask(pid, umask);
131
133
  }
132
134
 
135
+ /**
136
+ * Observe every pid's FIRST transition out of `running`, whichever door it
137
+ * leaves by — exit(), kill(), a facet's self-reported exit, a timeout abort:
138
+ * all of them end here, which is what makes this one callback a complete
139
+ * seam for per-pid durable state (the resident-launch journal) that must be
140
+ * released exactly when the process ends and never before.
141
+ *
142
+ * One slot, owned by the FacetManager. A second subscriber would mean two
143
+ * owners of process-end policy; grow this into a list only when a second
144
+ * genuine owner exists.
145
+ */
146
+ setOnTerminal(cb: (pid: number) => void): void {
147
+ this.onTerminalCb = cb;
148
+ }
149
+
150
+ private fireTerminal(pid: number, wasRunning: boolean): void {
151
+ if (!wasRunning || !this.onTerminalCb) return;
152
+ if (this.table.get(pid)?.state === 'running') return;
153
+ try { this.onTerminalCb(pid); } catch { /* the process is gone regardless */ }
154
+ }
155
+
133
156
  /** Mark a process as exited. First terminal state wins. */
134
157
  exit(pid: number, exitCode: number): void {
158
+ const wasRunning = this.table.get(pid)?.state === 'running';
135
159
  this.table.exit(pid, exitCode);
136
160
  this.terminators.delete(pid);
161
+ this.fireTerminal(pid, wasRunning);
137
162
  }
138
163
 
139
164
  /**
@@ -141,9 +166,11 @@ export class SessionProcessSupervisor {
141
166
  * stdin can't outlive the process.
142
167
  */
143
168
  kill(pid: number): boolean {
169
+ const wasRunning = this.table.get(pid)?.state === 'running';
144
170
  const killed = this.table.kill(pid);
145
171
  this.terminate(pid);
146
172
  this.input.close(pid);
173
+ this.fireTerminal(pid, wasRunning);
147
174
  return killed;
148
175
  }
149
176
 
@@ -352,11 +352,15 @@ async function registerWasmRuntimes(deps: {
352
352
  const [
353
353
  { makeBashRunnerFactory },
354
354
  { makeCPythonRunnerFactory },
355
+ { makeRubyRunnerFactory },
356
+ { makeClangRunnerFactory },
355
357
  { wasmRunnerSpec },
356
358
  { buildRuntimeHandler },
357
359
  ] = await Promise.all([
358
360
  import('../runtime/bash-runner.js'),
359
361
  import('../runtime/cpython-runner.js'),
362
+ import('../runtime/ruby-runner.js'),
363
+ import('../runtime/clang-runner.js'),
360
364
  import('../runtime/wasm-runner.js'),
361
365
  import('../runtime/runtime-registry.js'),
362
366
  ]);
@@ -391,8 +395,13 @@ async function registerWasmRuntimes(deps: {
391
395
  'bash-runner': makeBashRunnerFactory({ facets: deps.facets, vfs: deps.vfs }),
392
396
  // No `startResident`: a workspace owns no actor that could outlive the
393
397
  // call, so a program that keeps serving is refused by name rather than
394
- // run as a one-shot that dies with it.
398
+ // run as a one-shot that dies with it. Same for ruby, where a script is
399
+ // the shape that may bind a port.
395
400
  'cpython-runner': makeCPythonRunnerFactory({ facets: deps.facets, vfs: deps.vfs }),
401
+ 'ruby-runner': makeRubyRunnerFactory({
402
+ facets: deps.facets, vfs: deps.vfs, registry: deps.registry,
403
+ }),
404
+ 'clang-runner': makeClangRunnerFactory({ facets: deps.facets, vfs: deps.vfs }),
396
405
  };
397
406
  rehydrateInstalledRuntimesView(
398
407
  deps.vfs.as(CRED_KERNEL),