fix(provider-pi): deliver dynamic tool results to Bun-based pi - #3095
Open
fgrehm wants to merge 1 commit into
Open
fix(provider-pi): deliver dynamic tool results to Bun-based pi#3095fgrehm wants to merge 1 commit into
fgrehm wants to merge 1 commit into
Conversation
pi has shipped as a Bun-compiled binary since v0.55.0, and Bun's
net.Socket({ fd }) never attaches a read handle for a borrowed stdio
fd: the fd is validated and dropped, _handle stays null, and no poll
is ever registered (upstream gap, see oven-sh/bun#35341 and #29141,
both open). The pi extension read its result channel with
new net.Socket({ fd: 4 }), so under Bun-based pi nothing was ever
read: the tool promise never settled, pi never emitted
tool_execution_end, and every dynamic tool call (AskUserQuestion,
update_environment_directory, plugin agent tools) hung until
manually stopped.
Read the channel through Bun.file(fd).stream() when running under
Bun; Node keeps the existing net.Socket path. Teach fake-pi to load
extensions without module.registerHooks so the new regression test
can run the fake pi under Bun: it times out on main at the exact
production symptom and passes with this change.
Review follow-ups applied: stage fake-pi extension copies under the
package's gitignored node_modules; gate staging on the Bun runtime;
single-message fd-4 coverage and a CI bun leg are tracked as
follow-ups.
fgrehm
force-pushed
the
fix/pi-bridge-bun-stdio-channel
branch
from
September 5, 2026 03:05
cee4ebc to
6fabae5
Compare
fgrehm
marked this pull request as ready for review
September 6, 2026 15:31
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Human comments
This is something that almost made me give up on bb but my clanker got through and was able to diagnose the problem. TBH, not sure how this hasn't been reported before, I got it to do some searching on the repo issues / PRs / discussions but it did not find anything related.
Anyways, I hope this is the right way to fix the problem but if not, happy to provide more info about my environment as a separate ticket for discussion and investigation.
I'm about to rebuild my container with this patch + another one I got in the works and will report back if it goes sideways before marking the PR as ready for review.
What was wrong
The pi provider's dynamic tools (
AskUserQuestion,update_environment_directory, plugin agent tools) hang forever under the shipped pi. pi has been distributed as a Bun-compiled binary since v0.55.0 (release assets, built viabun build --compilein earendil-works/pi scripts/build-binaries.sh#L205), and pi 0.85.0's binary embeds Bun 1.3.14.Bun's
net.Socket({ fd })validates the fd and attaches no handle (_handle === null, no poll registered — see bun-v1.3.14 net.ts#L684 and the open upstream fix PRs oven-sh/bun#35341, #29141). The bridge→extension channel read (bb-pi-extension.ts#L177) relied on a Node-only behavior, so under the compiled pi every dynamic tool result was written but never read: the extension's tool promise never settled, pi never emittedtool_execution_end, and turns hung until manually stopped.This is not a Bun regression (read adoption has never shipped) and cannot be worked around by pinning Bun because pi embeds its runtime. The existing suite missed it because the fake pi loads extensions under Node, where the fd semantics work.
What changed
plugins/provider-pi/src/bridge/bb-pi-extension.ts— the bridge→extension channel reader branches on the runtime: under Bun it reads fd 4 throughBun.file(fd).stream()(same newline framing andStringDecoderhandling); under Node the existingnet.Socketpath is unchanged, with its non-blocking comment moved onto that branch. No message formats, wire content, or fd assignments changed — server↔daemon payloads are untouched, soHOST_DAEMON_PROTOCOL_VERSIONis not bumped.plugins/provider-pi/src/bridge/fake-pi-rpc.mjs— test fake: under runtimes withoutmodule.registerHooks(Bun) it stages the extension copy beside the package's gitignorednode_modulesso the extension's bare imports resolve natively; Node keeps the resolve-hook path. Header docs updated.plugins/provider-pi/src/bridge/bridge.bun-runtime.test.ts(new) — regression test running the fake pi under Bun and driving a dynamic tool round trip end to end. Known limitation, called out: it skips when Bun is absent fromPATH(it.skipIf(bunBinary() === null)), and no CI leg installs Bun today, so this guard does not run in CI yet (follow-up issue; without it, CI cannot detect a revert of the Bun branch).node_modules(not the source tree), the Bun branch is gated on the runtime rather than onregisterHooksavailability, and the single-message fd-4 coverage plus a bridge→extension liveness handshake are tracked as follow-ups rather than shipped here.How you verified
plugins/provider-pi/src/bridge/bridge.bun-runtime.test.ts: red onmainattimed out waiting for the tool result to reach pi under Bun(the exact production symptom), green with this change.pnpm exec vitest run --config vitest.config.ts src/bridge/bridge.bun-runtime.test.ts src/bridge/bridge.round2.test.ts src/bridge/bridge.framing.test.ts— 13/13 pass (Bun on PATH).pnpm exec turbo run typecheck --filter=bb-plugin-provider-pi— clean.BB_PROVIDER_BRIDGE_RECORD_DIR): recorded lanes show the full request→response chain through the bridge's fd-4 write with no error anywhere, matching the failure mode; pi's own session file shows it only ever received the abort-path tool result.Generated with "Omen Alpha" (Opencode Go) via BB / Pi