Repository navigation
Drop Windows PowerShell's echo of the lines the client sends (v1.64.1) - #142
Merged
Merged
Conversation
Windows PowerShell reading its commands from a pipe writes each line back to stdout, so every command showed up with its marker tail above its output. The client now filters the exact echo of each line it sent (EchoFilter, PowerShell dialect only), recognises it across chunks, and switches itself off for a PowerShell that does not echo. Client-side: works with nodes of any version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…esume, encodings and over the Hub Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- An echo may follow PowerShell's prompt (`PS …> ` until the init line runs, `>> ` on continuation); any pending line can match, and a match forgets the earlier pending ones whose echo was missed. - No permanent switch-off: a shell that did not echo the last command only stops holding partial lines; whole lines are still checked, and an echo turns holding back on. - Resume path: commandCompleted() runs before the cwd-fetch marker is sent, so that line is not mistaken for the completed command's. - Scan chunks in place (sublistView); copy only when bytes are held. - A program's own `> ` prompt is never held. - Dialect resolved once for the filter; stale "never echoed" docs fixed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…Windows) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…script
CI recorded what both PowerShell editions write over the pipe: a prompt
before every line read (`PS <location>> `, then `PS>` once the prompt
function returns ''), then the line echoed, `\n`-terminated. The filter
missed the `PS>` form and passed the prompt that arrives before the next
line is sent ("PS>hello-omny" on Windows CI).
- A line start that is or may become a prompt is held until its line
completes, kept across command boundaries; echoes after any prompt form
are dropped with it.
- powershell_pipe_test now asserts that transcript per edition; unit and
controller tests replay it exactly.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review: the filter guessed at prompt shapes (PS>, PS <loc>> , >> ) because the empty prompt function makes PowerShell print its PS> fallback, and it matched echoes against a queue of sent lines. That held a nested pwsh's prompt or a REPL's '>' forever, showed typed-ahead/continuation echoes, lost echoes of lines sent before the first prompt, and could attribute held bytes to a finished agent run. The init line now sets the prompt to CwdMarker.promptSentinel (written in halves, so its own echo never contains it). Every line PowerShell reads comes back as one line starting with that exact string, which is dropped whole; only the init echo after the default prompt is matched by text. No queue, no heuristics; chunks without a prompt pass through uncopied. Docs no longer claim the empty prompt hides the prompt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ust handle (Windows) Both editions, through the controller: no-newline output, large chunked output, errors (and their display), non-ASCII and very long command lines, cd, AI agent runs (output, exit 0/1/native), Read-Host input, and typed-ahead lines. Each asserts that no sentinel, echo or marker reaches the user. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The new real-PowerShell session tests showed 5.1 quoting the failing line
in every error, marker code included ("+ Get-Item … ; $__omnyLc=…"), and
for agent runs the exit-code prefix too. The marker must stay on the
command's line, so 256 blanks now separate the command from what the
client adds around it; the ~80-character quote holds only the command.
Tests: the agent failed-cmdlet case checks for protocol text, not the
error itself; input typed into a running command uses a stdin reader
(Read-Host does not read the pipe with stdin redirected).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It linked the throwaway pub cache's hosted/git folders to the real cache. On Windows those are junctions, and the recursive delete of the throwaway cache went through them: the runner's real cache lost packages and the AI tests then failed to load package:http/testing.dart. Windows now gets no links (the throwaway cache downloads what it needs); elsewhere links are removed by type without following them, and the temp directory is kept if any link survives. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.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
In a PowerShell session on a Windows node, every command showed up echoed above its output, marker tail included:
The node runs 1.63.3; the client is 1.64.0.
Cause
Windows PowerShell reads these sessions' commands from a pipe, and in that mode it writes each line it reads back to stdout. The init line (
function prompt { '' }) hides thePS …>prompt but not the echo. The client assumed a piped PowerShell doesn't echo (PowerShellDialect.wrapCommand: "no echo control needed over a pipe"). Earlier client versions showed fragments of the echo (='Continue',;$o.Flush(), as in the git-missing report). The longer markers since 1.63.4 make whole lines show.Fix (client-side, works with any node version)
EchoFilter. It queues each line the client sends, and drops the exact echo of the next queued line, with its CRLF or LF, where it starts an output line. Everything else passes through. Bytes that could still be an echo are held until they can be told apart, so an echo split across chunks is recognised; held bytes are released when the command completes.ShellDialect.echoesInputis true for PowerShell only;InteractiveShellControllerfilters stdout before the marker scan, and registers each line it sends.Tests
echo_filter_test.dart(12 tests): CRLF and LF, order, split chunks, near-misses, line-start only, only once, held bytes released, turning itself off.list_shortcut_test.dart(taggedwindows): realpowershell.exeandpwsh.exesessions through the controller. They assert that neither the commands nor the markers reach the output, for both a ping-marker and a full-marker command. This is what confirms the diagnosis on CI's Windows runner, since 5.1 can't be run on macOS.Release
pubspec.yaml,lib/src/version.dart), with a CHANGELOG entry.🤖 Generated with Claude Code