Skip to content

feat(hub): expose getResult() on startChildProcess() terminal sessions#90

Merged
antfu merged 2 commits into
mainfrom
feat/hub-terminals-child-process-result
Jul 14, 2026
Merged

feat(hub): expose getResult() on startChildProcess() terminal sessions#90
antfu merged 2 commits into
mainfrom
feat/hub-terminals-child-process-result

Conversation

@antfubot

Copy link
Copy Markdown
Collaborator

Why

Nuxt DevTools is planning to retire its own @xterm-based terminal system in favor of the hub's ctx.terminals (see its plans/vite-devtools-integration/02-terminals-reuse.md / 00-compat-foundation.md). Its current startSubprocess() returns { getProcess (deprecated), getResult, terminate, restart, clear }, where getResult() is a tinyexec Result — awaitable to { stdout, stderr, exitCode }, with live pid/exitCode/killed in the meantime. ctx.terminals.startChildProcess() had no equivalent, so there was no drop-in seam for that migration.

What changed

  • DevframeChildProcessTerminalSession gains a getResult() accessor returning a new DevframeChildProcessResult — a promise-like handle (live pid / exitCode / killed getters + kill()) that resolves to { stdout, stderr, exitCode } once the process exits. Mirrors tinyexec's Result shape closely enough that a tinyexec/execa-based subprocess-runner API can adopt startChildProcess() with little translation.
  • startChildProcess()'s internals now capture stdout/stderr separately, by listening on the raw child process directly instead of consuming tinyexec's own async-iterator/promise. Those both read from the same underlying streams as the merged terminal-display stream, and would otherwise starve each other — this was a real correctness gap, not just a missing feature.
  • getResult() tracks the current run and points at a fresh handle after restart(); it still settles with the real exit code if the session is terminate()d mid-flight.

Testing

  • 4 new tests in packages/hub/src/node/__tests__/host-terminals.test.ts covering: separate stdout/stderr + exit code capture, live accessors before/after exit, a fresh handle after restart(), and settlement after terminate().
  • pnpm lint && pnpm typecheck && pnpm test && pnpm build all pass repo-wide (652 tests).
  • Updated the @devframes/hub tsnapi export snapshots for the two new public types, and added a short note to docs/guide/hub.md / docs/plugins/terminals.md.

Created with the help of an agent.

Add a getResult() accessor to DevframeChildProcessTerminalSession that
mirrors tinyexec's Result contract — a promise-like handle with live
pid/exitCode/killed getters that resolves to { stdout, stderr, exitCode }
once the process exits. stdout and stderr are now captured separately
(alongside the existing merged display stream) by listening on the raw
child process directly, rather than through tinyexec's own async
iterator/promise, which would otherwise starve each other reading the
same underlying streams.

This gives tinyexec/execa-based subprocess-runner APIs (e.g. Nuxt
DevTools' startSubprocess().getResult()) a compatible seam to adopt
ctx.terminals.startChildProcess() directly.

Co-authored-by: opencode <noreply@opencode.ai>
@netlify

netlify Bot commented Jul 14, 2026

Copy link
Copy Markdown

Deploy Preview for devfra ready!

Name Link
🔨 Latest commit 973d4b9
🔍 Latest deploy log https://app.netlify.com/projects/devfra/deploys/6a5606aa24d97600089dd05e
😎 Deploy Preview https://deploy-preview-90--devfra.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@antfu antfu merged commit a8f8c50 into main Jul 14, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants