Skip to content

Make StdioTransport accept Flow<String> + suspend writer#100

Merged
anna239 merged 1 commit into
agentclientprotocol:masterfrom
AlexPl292:master
May 20, 2026
Merged

Make StdioTransport accept Flow<String> + suspend writer#100
anna239 merged 1 commit into
agentclientprotocol:masterfrom
AlexPl292:master

Conversation

@AlexPl292
Copy link
Copy Markdown
Contributor

Promote the Flow-based pair to the primary constructor and keep the existing Source/Sink one as a back-compat secondary, marked @deprecated: the blocking variant pins a dispatcher thread per readLine and would saturate the I/O pool under high agent concurrency.

Fix close() to cancel childScope. Previously close() only closed the channels and invoked closeHandler; the Source/Sink path worked because closing the underlying streams unblocked readLine, but the Flow path has no equivalent unblock — close() would leave the read job parked inside input.collect and the transport stuck in CLOSING. Cancelling childScope cooperatively unwinds the collect, the read job exits, joinAll returns, and the finally block sets state to CLOSED. The Source/Sink path is unaffected (the cancel is a no-op once the job has already exited).

Add StdioTransportFlowTest covering the new primary path: round-trip send/receive, JSON-skip behaviour, input-flow completion, input-flow errors, the output exception contract (IOException = clean, anything else = onError), parent-scope cancellation, and the close-deadlock regression itself.

Promote the Flow-based pair to the primary constructor and keep the
existing Source/Sink one as a back-compat secondary, marked @deprecated:
the blocking variant pins a dispatcher thread per readLine and would
saturate the I/O pool under high agent concurrency.

Fix close() to cancel childScope. Previously close() only closed the
channels and invoked closeHandler; the Source/Sink path worked because
closing the underlying streams unblocked readLine, but the Flow path
has no equivalent unblock — close() would leave the read job parked
inside input.collect and the transport stuck in CLOSING. Cancelling
childScope cooperatively unwinds the collect, the read job exits,
joinAll returns, and the finally block sets state to CLOSED. The
Source/Sink path is unaffected (the cancel is a no-op once the job has
already exited).

Add StdioTransportFlowTest covering the new primary path: round-trip
send/receive, JSON-skip behaviour, input-flow completion, input-flow
errors, the output exception contract (IOException = clean, anything
else = onError), parent-scope cancellation, and the close-deadlock
regression itself.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@anna239 anna239 merged commit 1e395fb into agentclientprotocol:master May 20, 2026
1 check 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.

2 participants