Retry session_busy prompt rejections once the agent goes idle - #3004
Open
bradhallett wants to merge 5 commits into
Open
Retry session_busy prompt rejections once the agent goes idle#3004bradhallett wants to merge 5 commits into
bradhallett wants to merge 5 commits into
Conversation
… goes idle Branch only on ACP -32003 with data.reason "session_busy": queue the prompt instead of failing the turn, resend it exactly once on the next end-of-turn session update, and fall back to the original error on a second busy rejection or after a 10-minute wait (overridable via BB_ACP_SESSION_BUSY_RETRY_TIMEOUT_MS for tests).
… the idle update The busy wait is armed a microtask after the -32003 response lands, so a session_info_update dispatched in the same stdout chunk was consumed before the wait existed and the prompt stalled until the timeout. Count session_info_update notifications unconditionally and treat one observed after the prompt request as idle. The fake agent gains FAKE_ACP_SESSION_BUSY_SAME_CHUNK to reproduce the coalesced delivery, and the retry test now pins the input.accepted delta count.
Contributor
Author
|
Upstream report for the omp-side half (typed |
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
What was wrong
When omp is streaming without an ACP-owned turn in flight — the completion-instant race (a steer lands in a turn's final second, bb closes its turn bookkeeping while omp is still finishing) or deferred agent-initiated continuations (#2122, #2461) — omp's ACP layer lets
session/promptfall through to a bareAgentSession.prompt(), which throwsAgentBusyError; since omp#9825 that rejection is typed on the wire as-32003withdata.reason: "session_busy". The bridge had no path for that typed rejection, so it fell into the generic error path: the turn failed and dispatch re-sent into the still-busy session, producing rejection storms (evidence: +3 ms rejection afterturn/input/accepted, retry turn 23 ms later, worst storm 8 rejections over 105 s until the ~8-minute client timeout; one thread terminally stuck inerror). Full diagnosis and event-log evidence in #3009.What changed
packages/provider-bridge-acp/src/bridge/agent-connection.ts—AcpAgentResponseErrornow carries the JSON-RPC errordata(optional constructor arg), so the typed reason is inspectable. No wire changes.packages/provider-bridge-acp/src/bridge/bridge.ts—-32003anddata.reason === "session_busy"; any other shape falls through to the existing error path unchanged.session_info_updatenotification (ACP v1 has no idle status variant; omp emits this last at end of turn).session/updatenotifications are counted unconditionally inhandleAgentNotification, so the coalesced-chunk case — busy error and idle update arriving in one stdout chunk, before the wait is armed — is detected via a pre-request snapshot and retries immediately.BB_ACP_SESSION_BUSY_RETRY_TIMEOUT_MS), surfaces the original busy error through the existing failure path.acceptTurnInput, so no duplicateinput.accepteddelta is emitted for the resent prompt; each new prompt gets a fresh retry budget; outstanding waits are settled onfinishTurn/stopSession/removeSessionso nothing dangles.packages/provider-bridge-acp/src/bridge/fake-acp-agent.mjs—FAKE_ACP_SESSION_BUSY_{PROMPTS,SKIP,REASON,SAME_CHUNK,IDLE_DELAY_MS}knobs reproducing omp's exact wire shape (code, message,data { reason, hint }, end-of-turnusage_update→session_info_updateordering, single-chunk coalescing).packages/plugin-sdk+packages/domain/src/plugin-sdk-version.ts— version bumped 0.4.40 → 0.4.41 (the bridge output is part of the published SDK artifact; the repo's version-bump check requires it).How you verified
reasonfails immediately (no retry consumed); no idle before the retry timeout fails with the original error (BB_ACP_SESSION_BUSY_RETRY_TIMEOUT_MSinjectable); busy error + idle update coalesced into one chunk retries immediately; each new prompt gets a fresh retry budget.mainatdebb58d10(merge commit05b300885):pnpm exec turbo run test --filter=@bb/provider-bridge-acp— 318/318 passed;pnpm exec turbo run typecheck lintfor@bb/provider-bridge-acp,@bb/domain,@get-bb/plugin-sdk— 6/6 green;pnpm exec oxfmt --checkclean on all five touched files. Mutation re-check: inverting thedata.reason === "session_busy"gate fails 4 of the 5 busy-matched tests; restoring it returns them to green.Fixes #3009