feat(terminals): kill process without discarding the session, and clear stopped sessions#119
Merged
Conversation
…ar stopped sessions The UI only ever called the remove RPC, so killing a terminal always discarded it along with its scrollback. Wire up the existing terminate RPC (stop the process, keep the session) and distinguish it from remove in the toolbar: running sessions get a Kill action, stopped ones get Remove. Add a clear-exited RPC (TerminalManager.clearExited) plus a nav-level Clear exited sweep to drop every stopped owned session at once.
✅ Deploy Preview for devfra ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Killing a process (terminate) or removing a still-running session now opens a confirmation modal, since a live process is being terminated. This applies to both interactive and readonly sessions. Already-stopped sessions are removed immediately without a prompt. The modal is dismissible via backdrop click or Escape and confirmable via Enter.
Readonly sessions aggregated from other devframes via the hub stream their raw output straight to the client, so bare LF line endings never get the server-side CRLF normalization that own pipe sessions receive — xterm then left the cursor column untouched on each newline and rendered a staircase. Enable xterm's convertEol for readonly sessions so a lone LF is treated as CRLF (a no-op when CRLF already arrived); interactive PTY sessions keep it off so full-screen TUIs retain exact cursor control.
Aggregated (read-only) sessions surfaced from other devframes via the hub were rendered without any controls. They can now be force-killed while running and removed once stopped, routed through new hub built-in RPCs (hub:terminals:terminate/restart/remove) — the same seam TerminalView already uses for write/resize. The plugin UI shows Kill/Remove for external sessions too, not just its own. startChildProcess (and startPtySession) now accept restartable on the session descriptor. When false, the terminals UI hides the restart control and hub:terminals:restart rejects the call (DF8205) — for sessions whose lifecycle is owned elsewhere. code-server sets restartable:false so restarting the editor goes through its own start flow (fresh port + secret) rather than re-spawning the raw process.
# Conflicts: # plugins/terminals/src/client/App.svelte # plugins/terminals/src/client/design.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The terminals UI only ever called the
removeRPC, so "killing" a terminal always discarded it along with its scrollback. There was no way to stop a process yet keep its output, nor to tidy up sessions that had already exited.This wires up the two missing capabilities:
terminateRPC — the process stops but the session and its scrollback stay in the list, marked stopped. Restart remains available.remove). A new nav-level Clear exited button sweeps away every stopped owned session at once, backed by a newdevframes:plugin:terminals:clear-exitedRPC andTerminalManager.clearExited().Hub-aggregated (external, read-only) sessions are excluded from all these controls, as before.
Notes
remove()was refactored to share a privatedisposeSession()teardown helper withclearExited(), which publishes once for the whole sweep.vitest(17 passed),tsc --noEmit,eslint, and the full plugin build (tsdown + client + SPA) all clean.This PR was created with the help of an agent.