Force-kill stuck AI terminal commands#316
Merged
Merged
Conversation
When an AI terminal command is cancelled or times out, the shell is first sent Ctrl+C to recover the prompt. If the shell does not return to a usable prompt within the grace period (the process ignores SIGINT or is itself hung), the terminal previously stayed stuck forever and, because the automation terminal is reused, every subsequent command hung too. Now, if the interrupt fails to recover the prompt, the child process tree is forcibly killed and the stuck automation terminal is discarded, so the next command always starts from a fresh, responsive terminal. - PseudoTerminalConnection.KillProcess kills the shell and its children. - TerminalViewModel.KillProcess exposes this to the manager. - TerminalManagerViewModel now kills and discards the terminal when interrupt-based recovery fails. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.
Problem
A
runTerminalCommandcould open a terminal tab, get stuck forever, and be impossible to escape — even the stop button / manual Ctrl+C couldn't recover it. Because the AI reuses the same automation terminal, once it was stuck every subsequent command hung too.Investigation
The keyboard input path is sound (Ctrl+C maps to
\u0003, the terminal control isFocusable), and pressing Ctrl+C in a healthy shell does recover it. The unrecoverable case is when the running process ignores SIGINT or the shell itself is hung — the previous gentle-interrupt recovery had no fallback, so the terminal stayed stuck and poisoned all later commands.Changes
On cancellation/timeout the shell is still sent Ctrl+C first (keeps the terminal reusable for well-behaved commands). If it does not return to a usable prompt within the grace period:
PseudoTerminalConnection.KillProcessforcibly kills the shell and its entire child process tree.TerminalViewModel.KillProcessexposes this to the manager.TerminalManagerViewModelkills the process tree and discards the stuck automation terminal, so the next AI command always starts from a fresh, responsive terminal instead of reusing a hung one.This guarantees a stuck command can always be terminated (via the Copilot stop button, which cancels the tool's
CancellationToken), and that the AI terminal never stays permanently wedged.Testing
dotnet build src/OneWare.TerminalManagersucceeds (only pre-existing warnings).