@vzn/vx 0.0.60 → 0.0.61

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vzn/vx",
3
- "version": "0.0.60",
3
+ "version": "0.0.61",
4
4
  "description": "An open, extensible monorepo task runner.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -17,10 +17,10 @@
17
17
  "node": ">=18"
18
18
  },
19
19
  "optionalDependencies": {
20
- "@vzn/vx-linux-x64": "0.0.60",
21
- "@vzn/vx-linux-arm64": "0.0.60",
22
- "@vzn/vx-darwin-x64": "0.0.60",
23
- "@vzn/vx-darwin-arm64": "0.0.60"
20
+ "@vzn/vx-linux-x64": "0.0.61",
21
+ "@vzn/vx-linux-arm64": "0.0.61",
22
+ "@vzn/vx-darwin-x64": "0.0.61",
23
+ "@vzn/vx-darwin-arm64": "0.0.61"
24
24
  },
25
25
  "dependencies": {
26
26
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
@@ -386,6 +386,9 @@ async function runRuntimeCommand(
386
386
  stdin: 'ignore',
387
387
  stdout: 'pipe',
388
388
  stderr: 'pipe',
389
+ // Its own group, so the probe's whole tree can be taken down with vx
390
+ // (`killProbesOnExit`).
391
+ detached: true,
389
392
  })
390
393
  } catch (err) {
391
394
  // The probe runs through `sh -c` like a task: a box without sh names
@@ -397,11 +400,18 @@ async function runRuntimeCommand(
397
400
  }
398
401
  throw new UserError(`cache.inputs runtime command failed to spawn: ${command} (cwd: ${cwd})`)
399
402
  }
400
- const [stdout, stderr, exitCode] = await Promise.all([
401
- new Response(proc.stdout).text(),
402
- new Response(proc.stderr).text(),
403
- proc.exited,
404
- ])
403
+ liveProbes.add(proc)
404
+ killProbesOnExit()
405
+ let stdout, stderr, exitCode
406
+ try {
407
+ ;[stdout, stderr, exitCode] = await Promise.all([
408
+ new Response(proc.stdout).text(),
409
+ new Response(proc.stderr).text(),
410
+ proc.exited,
411
+ ])
412
+ } finally {
413
+ liveProbes.delete(proc)
414
+ }
405
415
  const output = `${stdout}${stderr}`.trim()
406
416
  if (exitCode !== 0) {
407
417
  throw new UserError(
@@ -412,6 +422,31 @@ async function runRuntimeCommand(
412
422
  return output
413
423
  }
414
424
 
425
+ /**
426
+ * Runtime probes still running. A probe that outlives its answer's need — a
427
+ * run stopped by Ctrl-C, or ended by a refusal, while `node -e …` or a hung
428
+ * `git` still ran — was left behind: vx exited and the probe's shell and
429
+ * what it started ran on under init (A-9). Every probe is its own group, and
430
+ * the ones still listed when vx exits are SIGKILLed with their trees. A
431
+ * `kill -9` of vx runs no exit hook; that residual is the task groups' guard's
432
+ * (exec/kill-tree.ts), which probes are not on.
433
+ */
434
+ const liveProbes = new Set<ReturnType<typeof Bun.spawn>>()
435
+ let probeExitHooked = false
436
+ function killProbesOnExit(): void {
437
+ if (probeExitHooked) return
438
+ probeExitHooked = true
439
+ process.on('exit', () => {
440
+ for (const p of liveProbes) {
441
+ try {
442
+ process.kill(-p.pid, 'SIGKILL')
443
+ } catch {
444
+ // the group is gone
445
+ }
446
+ }
447
+ })
448
+ }
449
+
415
450
  /**
416
451
  * Resolve a list of runtime-input commands to sorted [command, output]
417
452
  * pairs. Dedups via the shared `memo` (Promise per key): the first