You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(execd): preserve blank lines in command stdout SSE stream (#902)
* fix(execd): preserve blank lines in command stdout SSE stream
readFromPos previously skipped consecutive line terminators when the
buffer was empty, dropping standalone newline lines from the SSE output.
Emit "\n" for blank lines while keeping the existing line-content emit
behavior (terminator is still stripped from non-empty lines). \r\n pairs
are coalesced via lastWasCR to avoid duplicate blank emits.
Adds a unit test covering blank lines, leading blank, and CRLF, and an
end-to-end smoke test that runs `printf 'a\n\nb\n\n\nc\n'` and asserts
the stdout event sequence preserves the blanks.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(execd): wait for stdout/stderr tail to flush before complete on Windows
Windows runCommand fired OnExecuteComplete immediately after closing the
done channel, racing the tail goroutines that emit pending stdout/stderr
SSE events. Clients that break on execution_complete then missed final
output, e.g. the blank-line smoke assertion saw an empty sequence while
the server log showed the events were emitted.
Mirror the Linux path: track the tail goroutines with a sync.WaitGroup
and wg.Wait() after close(done) so all buffered output drains before
the completion event is sent. Also covers the cmd.Start failure path.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(execd): persist CRLF state across tail polls
readFromPos previously declared lastWasCR as a per-call local, so the
CRLF coalescing only worked when \r and \n were read in the same
invocation. When tailStdPipe polls a writer that flushes \r before \n
(common on Windows/cmd), the \r and \n can land in separate polls; the
second call starts with lastWasCR=false and emits a spurious "\n" blank
line for the trailing \n. A bare blank \r\n line split across polls
would surface as two blanks.
Hoist the state into tailStdPipe and thread it through readFromPos so
the CR detection survives between polls. Add regression tests covering
split CRLF after content and split blank CRLF.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test(execd): make blank-lines smoke command cross-platform
Replace POSIX printf with single-quoted format string with a python -c
one-liner. cmd /C does not strip single quotes, so the previous command
only worked on Windows runners that happened to have Git for Windows in
PATH (MSYS2 argv pre-processing strips the quotes); on a bare Windows
sandbox the smoke would fail before reaching the filesystem checks.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test(execd): branch blank-lines smoke per platform
The previous python -c attempt produced a SyntaxError on Windows because
Go's syscall.EscapeArg wraps the cmd /C argument in quotes, escaping the
inner quotes as \". cmd /C strips the outer quotes (rule 2 of its parser)
but leaves the literal \" inside, and MSVCRT's argv parser then treats
\" as a literal double-quote character without toggling quote state, so
the first embedded space terminates argv[2] and python sees an
unterminated string literal.
Use a cmd-native echo chain on Windows (no inner quotes, & is sequential)
and keep POSIX printf on Linux/macOS. The execd reader collapses CRLF to
LF, so both platforms yield the same event sequence.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
0 commit comments