Skip to content

Rework AI terminal commands with VS Code-style shell integration#330

Merged
hendrikmennen merged 9 commits into
mainfrom
fix/ai-terminal-concurrency
Jul 24, 2026
Merged

Rework AI terminal commands with VS Code-style shell integration#330
hendrikmennen merged 9 commits into
mainfrom
fix/ai-terminal-concurrency

Conversation

@hendrikmennen

@hendrikmennen hendrikmennen commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #322. Full rework of how AI terminal commands are tracked, replacing the out-of-band completion channel with VS Code-style shell integration.

Terminal command tracking (OSC 633 shell integration)

The previous approach typed a visible marker command into the shell, suppressed its echo with cursor-erase hacks, and signalled completion through extra pipes/handles — which sometimes leaked the marker into the user-facing terminal and behaved differently across Unix/Windows.

Now, shell startup files install prompt hooks that emit invisible, in-band OSC 633 sequences (C = command started, D;<exit> = command finished with exit code), exactly like VS Code's shell integration:

  • ShellIntegration.cs — generates integration scripts for bash (--init-file), zsh (ZDOTDIR) and PowerShell, sourcing the user's own startup files first. Scripts are written atomically to a per-user directory (~/.oneware/shell-integration, 0700).
  • ShellIntegrationParser.cs — chunk-safe streaming parser that strips OSC 633 sequences from pty output and raises typed events; all other escape sequences pass through untouched.
  • TerminalManagerViewModel — captures output strictly between the C/D markers (no prompt drawing, no command echo) with a short grace period so multi-line command blocks complete as one execution.
  • Nothing is ever typed into the shell and no extra fds/pipes are inherited; the same mechanism works on Unix and Windows (ConPTY).
  • User input remains possible while a command runs; a best-effort UserInputEchoFilter keeps echoed keystrokes out of the captured/streamed tool output (visible terminal unaffected).

Robustness fixes

  • Shell exit handling: exit/crash of the shell no longer hangs pending executions — pty EOF raises Closed, the real process exit code is captured (waitpid on Unix, Process.ExitCode on Windows) and reported, and the terminal tab closes automatically.
  • forkpty deadlock: pre-fork P/Invoke warm-up fixes a latent hang where the first spawned terminal could deadlock in the child before execve.
  • Timeout/cancel recovery: gentle Ctrl+C first; if the shell stays stuck, the process tree is killed and the automation terminal discarded instead of being reused.

Chat UX

  • Stop button on every running tool call (right of the spinner) — cancels just that invocation via a per-invocation CancellationTokenSource (IAiFunctionProvider.CancelFunction); the model receives a graceful "stopped by user" result instead of the turn failing.
  • Chat abort now also cancels running tool invocations.
  • Queued messages: item template with remove button, plus IChatService queue management (RemoveMostRecentQueuedMessageAsync/ClearQueuedMessagesAsync) wired to the Copilot SDK.
  • Copilot CLI bumped to 1.0.74.

Tests

New/rewritten coverage: parser strip/event/chunk-split tests, spawn-config tests per shell, echo-filter tests, and live-bash integration tests (command lifecycle, failing exit codes, exit 3 closing the session with the real exit code, no marker/control-byte leakage). 22 tests passing.

Net result: −460 lines while covering more edge cases.

Submodule cleanup: hendrikmennen/VtNetCore.Avalonia#2

hendrikmennen and others added 8 commits July 23, 2026 22:48
Keep AI commands in the real interactive terminal while reporting completion and exit status through inherited pipes. Recover the completion handshake after interactive Ctrl+C and remove prompt-marker parsing from chat output.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Initialize a shell completion function before showing Unix terminals and use short per-terminal sequence IDs so hidden completion calls stay on one terminal row.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Using a fixed path under the shared /tmp allowed another local user to
pre-create the directory and tamper with the scripts our shells source
(TOCTOU), and blocked script writes for the second user on multi-user
systems. Scripts now live in ~/.oneware/shell-integration (0700).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@hendrikmennen hendrikmennen changed the title Use out-of-band terminal completion channel Rework AI terminal commands with VS Code-style shell integration Jul 24, 2026
# Conflicts:
#	src/OneWare.Chat/Services/AiFunctionProvider.cs
#	src/OneWare.Essentials/Services/IAiFunctionProvider.cs
@hendrikmennen
hendrikmennen merged commit b6ad8cd into main Jul 24, 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