Skip to content

fix: read replay stdin asynchronously so pipes work - #33

Merged
EauDoon merged 1 commit into
mainfrom
fix/replay-stdin-pipe
Sep 6, 2026
Merged

fix: read replay stdin asynchronously so pipes work#33
EauDoon merged 1 commit into
mainfrom
fix/replay-stdin-pipe

Conversation

@EauDoon

@EauDoon EauDoon commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Defect

The documented aas export <run-id> | aas replay - pipeline was broken:
readFileSync(0) raised EAGAIN: resource temporarily unavailable, read
instead of consuming piped bundle JSON. Reproduced live before the fix;
the file-input path was unaffected.

Fix

Read piped stdin asynchronously in chunks. The size cap, empty-document
rejection, and TTY usage error are unchanged. Verified live: piped
export-to-replay of a rail-review run now verifies end to end, exit 0.

Tests

  • New stdin tests: piped simulate-mode bundle reports unavailable (exit
    1. without touching the filesystem, TTY stdin is a usage error
      (exit 2), and oversized piped input fails closed against the byte
      limit.
  • npm test: 73/73.

Devin Review

`aas export <id> | aas replay -` failed with EAGAIN: readFileSync(0)
does not reliably drain a pipe on all platforms. Read piped stdin
asynchronously in chunks with the existing size cap and empty-document
rejection preserved. TTY use still fails closed with the usage hint.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

Devin Review

Comment thread bin/aas.mjs
chunks.push(typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk);
}
const text = Buffer.concat(chunks).toString("utf8");
if (text.length > CHILD_JSON_LIMIT) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Multibyte bundles bypass byte limit

Valid JSON with multibyte text can exceed CHILD_JSON_LIMIT bytes while passing the character-count check. Replay then accepts an oversized bundle.

Suggested change
if (text.length > CHILD_JSON_LIMIT) {
if (Buffer.byteLength(text, "utf8") > CHILD_JSON_LIMIT) {
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread bin/aas.mjs
Comment on lines +1447 to +1452
const chunks = [];
for await (const chunk of stdin) {
chunks.push(typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk);
}
const text = Buffer.concat(chunks).toString("utf8");
if (text.length > CHILD_JSON_LIMIT) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟨 Unbounded stdin can exhaust memory

readReplayInput retains all piped input before enforcing its limit. A large or endless producer can exhaust the replay process's memory.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@EauDoon
EauDoon merged commit ae58eac into main Sep 6, 2026
9 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