Skip to content

Fix AI terminal command reliability and cancellation#314

Merged
hendrikmennen merged 1 commit into
mainfrom
fix/ai-terminal-reliability
Jul 15, 2026
Merged

Fix AI terminal command reliability and cancellation#314
hendrikmennen merged 1 commit into
mainfrom
fix/ai-terminal-reliability

Conversation

@hendrikmennen

Copy link
Copy Markdown
Contributor

Problem

AI terminal commands (runTerminalCommand) sometimes got stuck forever for seemingly no reason, even on simple commands. There was also no way to reliably cancel a running command, and the timeout was too short for long-running tasks.

Root cause

UnixPseudoTerminal.WriteAsync ignored the return value of the POSIX write(2) call. write() may perform a partial write or return -1 on EINTR/EAGAIN when the pty input buffer is momentarily full. When that happened, part of the command — often the trailing carriage return — was silently dropped, so the shell never executed the command, never emitted its completion marker, and the call hung until the timeout. Because it depends on buffer timing, it was intermittent and hit even trivial commands.

Changes

  • Reliable command submissionUnixPseudoTerminal.WriteAsync now loops until every byte is written, advancing on partial writes and retrying on transient failures.
  • Long-running task support — the runTerminalCommand timeout is raised from 1 minute to 12 hours so builds/simulations/servers aren't killed prematurely.
  • Stop button cancels the command — the tool handler now takes a CancellationToken (auto-bound by AIFunctionFactory to the token the Copilot SDK cancels on AbortAsync) and threads it into ExecuteInTerminalAsync.
  • Interrupt & recover — on timeout/cancel, the shell is sent Ctrl+C (TerminalViewModel.SendInterrupt) and given a moment to return to a clean prompt, so the reused automation terminal doesn't stay stuck for subsequent commands.

Testing

  • dotnet build succeeds for OneWare.Terminal, OneWare.TerminalManager, and OneWare.Chat (only pre-existing warnings).

Fix intermittent hangs where simple AI terminal commands would get stuck
until the timeout, and make long-running tasks and the stop button behave
correctly.

- UnixPseudoTerminal.WriteAsync now loops until every byte is written,
  handling partial writes and transient EINTR/EAGAIN. Previously the
  return value of write() was ignored, so a dropped trailing carriage
  return left the shell waiting and the command hanging forever.
- Extend the AI runTerminalCommand timeout to 12h so long-running tasks
  (builds, simulations, servers) are not killed prematurely.
- Thread the tool invocation CancellationToken through to
  ExecuteInTerminalAsync so pressing stop in Copilot cancels the running
  command. On timeout/cancel the shell is sent Ctrl+C (SendInterrupt) and
  recovered to a clean prompt so the reused terminal does not stay stuck.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@hendrikmennen
hendrikmennen merged commit f685771 into main Jul 15, 2026
5 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.

1 participant