Skip to content

fix(acp): a blank line from an ACP agent no longer ends the session - #28851

Open
only21mil wants to merge 1 commit into
pingdotgg:mainfrom
only21mil:fix/audit-m085
Open

only21mil wants to merge 1 commit into
pingdotgg:mainfrom
only21mil:fix/audit-m085

Conversation

@only21mil

Copy link
Copy Markdown
Contributor

Problem

If an ACP agent writes an empty or whitespace-only line to stdout, T3 Code ends the whole session with AcpProtocolParseError. The strict ACP frame parser hands every line to JSON.parse, and JSON.parse("") throws. A stray \n after a message, or a blank \r\n line, is enough to kill a running turn.

The official ACP SDKs ignore these lines: the TypeScript SDK's ndJsonStream and the Python SDK's stdio transport both trim each line and skip it if nothing is left. T3 Code's own Codex app-server parser also skips blank lines (effect-codex-app-server/src/protocol.ts).

Change

makeStrictNdJsonRpcParser now skips lines that are empty after trim(). Every other line still goes through the strict JSON-RPC codec, so a malformed nonblank frame still ends the session, as before.

Scope and approval

This is a very small fix for an obvious bug, so it needs no prior issue: one condition in the frame loop, plus one test. It does not touch the stricter rule this parser exists for, which ends the session on malformed agent output. A line with no content is not a message, and the ACP reference SDKs ignore it. Please confirm that skipping whitespace-only lines, as those SDKs do, is the tolerance you want.

Verification

  • New test skips blank lines between agent messages in packages/effect-acp/src/protocol.test.ts. It sends \n, \r\n and \t\n before a session/update in one stdout chunk.
    • Before the fix: fails, expected 'AcpProtocolParseError' to equal 'SessionUpdate'.
    • After the fix: passes.
  • vp test run src/protocol.test.ts in packages/effect-acp: 23/23 pass, including the existing malformed-frame tests (logs decode failures without copying the cause or wire payload, does not emit a second process-exit error after a decode failure). Those tests show that a nonblank non-JSON line still ends the session.
  • Runtime check against a real child process: the repo's mock ACP peer, started with ACP_MOCK_STDOUT_PREFIX set to blank lines, then initialize and an x/echo request.
    • Before the fix: initialize fails with AcpProtocolParseError (Unexpected end of JSON input).
    • After the fix: initialize returns protocol version 2 and x/echo echoes its params.
  • vp run check:changed against the base commit: format, lint, knip, typecheck (14 packages) and the tests beside the changes all pass.
  • In the app, with a Local ACP provider that runs the repo's mock agent and writes an extra blank line after each line it prints. Each client talked to a server built from the base commit for "before" and from this branch for "after"; the client code is the same in both. Web, Android and iOS used one dev server. The desktop app (Linux, vp run dev:desktop) runs its own server, built the same way. The machine name under the mobile thread titles is masked. Before the fix, every turn fails to open a provider session, and the server log shows AcpProtocolParseError caused by Unexpected end of JSON input. After the fix, each turn gets the agent's reply.

Web before: the blank-line agent fails to open a session.

Web before

Web after: the agent replies “hello from mock”.

Web after

Desktop before: the turn fails with “Failed to open acpRegistry provider session”.

Desktop before

Desktop after: the agent replies “hello from mock”.

Desktop after

Android before: the turn shows “Provider session failed to open”.

Android before

Android after: the agent replies “hello from mock”.

Android after

iOS before: the turn shows “Provider session failed to open”.

iOS before

iOS after: the agent replies “hello from mock”.

iOS after

Not checked:

  • No real third-party agent known to emit blank lines was run.
  • Full CI suites.

Prior PRs

Generated with Claude Opus 5.5 and GPT-6.1 Terra and GPT-6.1 Sol in T3 Code Nightly

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XS 0-9 changed lines (additions + deletions). labels Nov 1, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at a51c31b

Macroscope's review found this PR approvable — Blank or whitespace-only ACP output lines are now ignored instead of ending the session. Nonblank messages retain strict decoding, keeping the change narrowly limited to transport tolerance.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 57d764e and a51c31b.

Files selected for processing: 2
  • packages/effect-acp/src/protocol.test.ts
  • packages/effect-acp/src/protocol.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.

Walkthrough

The strict NDJSON parser now skips whitespace-only complete lines. Nonblank lines still go through the strict codec. A test checks a valid session/update message surrounded by blank lines.

Changes: NDJSON Parser

Layer / File(s) Summary
Blank-line handling and validation
packages/effect-acp/src/protocol.ts, packages/effect-acp/src/protocol.test.ts
The parser skips whitespace-only complete lines and uses the strict codec for nonblank lines. The test places blank lines around a valid session/update message and expects a SessionUpdate event.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Possibly related PRs

Suggested labels: bugfix, size:S

Suggested reviewers: juliusmarminge

Merge Risk: Minimal · up to a51c3

No concrete current-head defect or unresolved merge risk was identified.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title names the main change: a blank line from an ACP agent no longer ends the session. The raw summary and objectives confirm the parser now skips whitespace-only lines in makeStrictNdJsonRpcPars…
Description check Passed The description follows the template. It has Problem, Change, Scope and approval, and Verification sections, and each is filled in with specifics. The Problem section gives the expected behavior and r…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the main change: a blank line from an ACP agent no longer ends the session. The raw summary and objectives confirm the parser now skips whitespace-only lines in makeStrictNdJsonRpcParser, and the title is specific, follows conventional commit form, and is not misleading.

Full details: Description check

Explanation

The description follows the template. It has Problem, Change, Scope and approval, and Verification sections, and each is filled in with specifics. The Problem section gives the expected behavior and reproduction steps. The Change section explains the one-condition fix and why the strict codec still applies to nonblank lines. Scope explains why no prior issue is needed for a very small obvious bug. Verification lists the focused test, before and after results, a runtime check, and app checks with screenshots, and it states what was not checked. The template's closing line asks for the model and harness used. The description gives the model and harness in its last line, so that item is covered.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XS 0-9 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant