fix(tui): preserve prior segment output on Ctrl+C interrupt#13596
Conversation
There was a problem hiding this comment.
Pull request overview
Updates Hermes TUI turn interruption handling so a Ctrl+C during a streaming turn preserves already-rendered output in the transcript instead of wiping it when the controller resets to idle.
Changes:
- Flush
segmentMessagesinto the transcript duringinterruptTurn()before callingidle(). - Attach
pendingSegmentToolsto the final interrupted partial assistant message (when a partial exists) rather than losing them during reset.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
0ce1300 to
c10b73b
Compare
There was a problem hiding this comment.
Pull request overview
Preserves already-streamed assistant output (tool trail + commentary segments) in the TUI transcript when the user interrupts a running turn via Ctrl+C, instead of losing it when the turn state is reset.
Changes:
- Update
TurnController.interruptTurnto append accumulated segment messages and include pending tool trail output when rendering the interrupted partial. - Non-functional refactors: import ordering and formatting across TUI libs/components/tests.
- Update Nix
fetchNpmDepshashes forwebandui-tui.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| ui-tui/src/app/turnController.ts | Core behavioral change: preserve segment output and pending tool trails on interrupt. |
| ui-tui/src/lib/terminalSetup.ts | Formatting-only changes in JSON comment stripping and keybinding setup helpers. |
| ui-tui/src/lib/terminalParity.ts | Import formatting and wrapping long conditionals/messages. |
| ui-tui/src/lib/platform.ts | Formatting-only change to isActionMod. |
| ui-tui/src/lib/osc52.ts | Formatting-only change. |
| ui-tui/src/lib/clipboard.ts | Formatting-only changes and function signature wrapping. |
| ui-tui/src/content/hotkeys.ts | Formatting-only change to conditional spread. |
| ui-tui/src/components/textInput.tsx | Formatting-only changes to types/logic layout. |
| ui-tui/src/components/prompts.tsx | Import order + minor JSX formatting for hotkey hint line. |
| ui-tui/src/components/appChrome.tsx | JSX formatting only. |
| ui-tui/src/app/useMainApp.ts | Import ordering only. |
| ui-tui/src/app/useInputHandlers.ts | Remove extra blank line. |
| ui-tui/src/app/useComposerState.ts | Formatting-only refactor (no behavior change intended). |
| ui-tui/src/app/slash/commands/session.ts | Import ordering only. |
| ui-tui/src/app/slash/commands/core.ts | Promise chain formatting; behavior should be unchanged. |
| ui-tui/src/tests/useComposerState.test.ts | Formatting + remove unused vi import. |
| ui-tui/src/tests/terminalSetup.test.ts | Formatting-only changes. |
| ui-tui/src/tests/terminalParity.test.ts | Formatting-only changes. |
| ui-tui/src/tests/platform.test.ts | Formatting-only change. |
| ui-tui/src/tests/osc52.test.ts | Formatting-only change. |
| ui-tui/src/tests/clipboard.test.ts | Formatting-only changes. |
| ui-tui/packages/hermes-ink/src/ink/events/cmd-shortcuts.test.ts | Import ordering + spacing. |
| nix/web.nix | Update fetchNpmDeps hash. |
| nix/tui.nix | Update fetchNpmDeps hash. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cf0cb77 to
ebe9e78
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the TUI turn interruption flow so that cancelling a running interaction (Ctrl+C) preserves already-emitted tool/commentary output in the transcript instead of wiping it, addressing blitz-test feedback about lost partial results.
Changes:
- Update
interruptTurnto preserve and appendsegmentMessages(and any in-flight partial + pending tools) into the transcript before clearing turn state. - Minor refactors/formatting (line wrapping, import ordering, whitespace) across TUI libs/components and related tests.
- Small async flow formatting cleanup in
/terminal-setupcommand handling.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| ui-tui/src/app/turnController.ts | Main behavior change: preserve prior segment output on Ctrl+C and append interrupted marker/partial appropriately. |
| ui-tui/src/app/useInputHandlers.ts | Formatting-only change near imports; interrupt hotkey path unchanged. |
| ui-tui/src/app/useSubmission.ts | No changes. |
| ui-tui/src/app/useComposerState.ts | Formatting/import ordering only; no functional changes intended. |
| ui-tui/src/app/useMainApp.ts | Import ordering only. |
| ui-tui/src/app/slash/commands/core.ts | Reformat promise chain for terminal setup runner; behavior intended to be unchanged. |
| ui-tui/src/app/slash/commands/session.ts | Import ordering only. |
| ui-tui/src/components/appChrome.tsx | JSX formatting only. |
| ui-tui/src/components/prompts.tsx | Import ordering + minor JSX spacing formatting. |
| ui-tui/src/components/textInput.tsx | Type/prop formatting only. |
| ui-tui/src/content/hotkeys.ts | Formatting-only change to conditional spread block. |
| ui-tui/src/lib/terminalSetup.ts | Formatting-only (blank lines / wrapping). |
| ui-tui/src/lib/terminalParity.ts | Import + string wrapping only. |
| ui-tui/src/lib/platform.ts | Formatting-only (remove extra parentheses/indent). |
| ui-tui/src/lib/osc52.ts | Formatting-only (blank line). |
| ui-tui/src/lib/clipboard.ts | Formatting-only (function signature wrapping / blank lines). |
| ui-tui/src/tests/useComposerState.test.ts | Formatting-only (wrapping expectations), remove unused import. |
| ui-tui/src/tests/terminalSetup.test.ts | Formatting-only (wrapping expectations / spacing). |
| ui-tui/src/tests/terminalParity.test.ts | Formatting-only (wrapping objects/arrays). |
| ui-tui/src/tests/platform.test.ts | Formatting-only (blank line). |
| ui-tui/src/tests/osc52.test.ts | Formatting-only (blank line). |
| ui-tui/src/tests/clipboard.test.ts | Formatting-only (wrap long lines / spacing). |
| ui-tui/packages/hermes-ink/src/ink/events/cmd-shortcuts.test.ts | Import ordering/spacing only. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
interruptTurn only flushed the in-flight streaming chunk (bufRef) to the transcript before calling idle(), which wiped segmentMessages and pendingSegmentTools. Every tool call and commentary line the agent had already emitted in the current turn disappeared the moment the user cancelled, even though that output is exactly what they want to keep when they hit Ctrl+C (quote from the blitz feedback: "everything was fine up until the point where you wanted to push to main"). Append each flushed segment message to the transcript first, then render the in-flight partial with the `*[interrupted]*` marker and its pendingSegmentTools. Sys-level "interrupted" note still fires when there is nothing to preserve.
ebe9e78 to
dd5ead1
Compare
…-preserve-segments fix(tui): preserve prior segment output on Ctrl+C interrupt
…-preserve-segments fix(tui): preserve prior segment output on Ctrl+C interrupt
…-preserve-segments fix(tui): preserve prior segment output on Ctrl+C interrupt
…-preserve-segments fix(tui): preserve prior segment output on Ctrl+C interrupt
…-preserve-segments fix(tui): preserve prior segment output on Ctrl+C interrupt
…-preserve-segments fix(tui): preserve prior segment output on Ctrl+C interrupt
From TUI blitz-test feedback: "When cancelling (ctrl + c) a running interaction, whatever was output by the agent to that point gets deleted. … at the moment it just wipes everything back to my last message."
Summary
interruptTurnonly flushed the in-flight streaming chunk (bufRef) to the transcript before callingidle(), which wipedsegmentMessagesandpendingSegmentTools. Every tool call and commentary line the agent had already emitted in the current turn disappeared the moment the user cancelled, even though that output is exactly what they want to keep when they hit Ctrl+C.*[interrupted]*marker and itspendingSegmentTools. Sys-levelinterruptednote still fires when there is nothing to preserve.Test plan
npm run type-checkcleannpm test— 152/152 passinterruptedsys note