Repository navigation
fix(core): reuse recent Console config checks for rejected inference - #57465
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
The change looks sound. I ran the updated explanation test against the base, where it fails (Expected: 1, Received: 2) because every rejected response triggers its own config fetch. With this PR the full provider-opencode suite passes (40/40), and typecheck in packages/core passes. The age check runs inside the loading semaphore, so concurrent rejections share the load already in progress. Because checked is set when a load starts, failed loads also hold back retries for the window.
The public API is unchanged: check is internal to the plugin.
No blocking concerns.
12 tasks
5 tasks
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.
Problem
The OpenCode Console provider plugin (
packages/core/src/plugin/provider/opencode.ts) registers anhttp.responsesession hook (explain) for the opencode provider and every Console-configured provider. On every inference response with status 401 or 403 it calledcheck(), which re-fetchedGET <server>/api/v2/configto learn why the request was rejected. A client whose inference keeps getting rejected (out of credits, blocked account, SSO required, revoked key) and keeps retrying therefore sent one config request per failed inference request. Concurrent failures also each queued their own load behind the semaphore.Production evidence (Cloudflare analytics, 2026-10-19):
GET /console/api/v2/configper minuteopencode/latest/2.0.32/cli/console/api/v2/configis ~408k requests per 12 hours, the Console API's largest endpoint by farFix
checknow takes an optionalmaxAge.load()records when it started (viaClock), andexplaincallscheck(Duration.seconds(30)). If any config load (startup, the 1-minute poll, a credential-switch refresh, or an earlier explanation) started within the last 30 seconds, the hook reuses the last reported connection status instead of fetching again. The age check runs inside the existingloadingsemaphore, so concurrent failing responses wait for the load already in flight and then reuse its result.Rejected responses are still replaced with the same actionable message (reconnect / sign in with SSO again), based on the Console's last reported status. The trade-off: a status change in the Console shows up in explanations up to 30 seconds late. The 1-minute poll is unchanged.
I also checked the rest of the file for other ways to loop:
applyre-registering hooks,Credential.Event.Switched→refresh, and snapshot equality. None of them fetch config. Token refresh publishesCredential.Event.Updated, notSwitched. Connection status updates publishIntegration.Event.Updated, which the plugin does not subscribe to. The poll usesonlyIfMissing, so it never stacks timers.Tests
The existing explanation test in
packages/core/test/plugin/provider-opencode.test.tsis now anit.effecttest onTestClock, and it counts config requests. After startup it sends 1 rejected response, then 10 concurrent and 20 sequential SSO-rejected responses within the 30-second window, plus responses for the opencode provider and an unrelated provider. It checks that every Console-provider response is still explained and that only one config request is made after startup.--rerun-each 5.Expected: 1, Received: 2on the first rejected response). Instrumented, the same sequence made 33 config requests for 32 rejected responses; with the fix it makes 2 (startup + one check).bun typecheckinpackages/coreand the rootbun run checkboth pass.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊