Skip to content

fix(execd): preserve blank lines in command stdout SSE stream#902

Merged
hittyt merged 5 commits into
alibaba:mainfrom
Pangjiping:fix/execd-stdout-preserve-blank-lines
May 19, 2026
Merged

fix(execd): preserve blank lines in command stdout SSE stream#902
hittyt merged 5 commits into
alibaba:mainfrom
Pangjiping:fix/execd-stdout-preserve-blank-lines

Conversation

@Pangjiping
Copy link
Copy Markdown
Collaborator

Summary

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.

Testing

  • Not run (explain why)
  • Unit tests
  • Integration tests
  • e2e / manual verification

Breaking Changes

  • None
  • Yes (describe impact and migration path)

Checklist

  • Linked Issue or clearly described motivation
  • Added/updated docs (if needed)
  • Added/updated tests (if needed)
  • Security impact considered
  • Backward compatibility considered

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>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0168239327

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread components/execd/pkg/runtime/command_common.go Outdated
Pangjiping and others added 2 commits May 17, 2026 15:54
…indows

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>
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>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 37eda911c3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread components/execd/tests/smoke_api.py Outdated
Pangjiping and others added 2 commits May 19, 2026 10:11
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>
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>
Copy link
Copy Markdown
Collaborator

@hittyt hittyt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hittyt hittyt merged commit c1d19b7 into alibaba:main May 19, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working component/execd

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants