feat(opencode): killswitch — block requests when quota drops below threshold#35
Open
iceteaSA wants to merge 6 commits into
Open
feat(opencode): killswitch — block requests when quota drops below threshold#35iceteaSA wants to merge 6 commits into
iceteaSA wants to merge 6 commits into
Conversation
This was referenced May 21, 2026
There was a problem hiding this comment.
2 issues found across 10 files
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
Fix all with cubic | Re-trigger cubic
d89dd9d to
f667649
Compare
0054553 to
d125adb
Compare
9092526 to
37961f1
Compare
|
Want your agent to iterate on Greptile's feedback? Try greploops. |
56730ff to
20f6330
Compare
…reshold Self-review fixes folded in: - Token-aware fail-closed read: const mainQuota = quotaManager.getMain(auth.access) so a previous main account's cached quota can't satisfy the fail-closed check or feed the killswitch eval after a main-account switch. - Removed a stray inner 'let sessionRequestCount = 0' + unconditional increment that shadowed the process-scoped counter, which had left the active-route fallback every-N refresh reading a never-incremented counter.
Contributor
Author
…nged The callback fires on any persisted fallback storage change (token refresh, quota update, or error recording), not only quota fetches. Rename per review feedback for an accurate API name.
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.
Per-account request blocking when remaining quota drops below configurable thresholds. Returns a synthetic 429 only when the request genuinely cannot be routed anywhere.
Features:
killswitchblock.null).killswitchPassesPolicyevaluates all present quota windows — a present below-threshold window still blocks even when the other window is missing (failClosed=false).Retry-Aftercomputation read the fresh, token-aware QuotaManager cache, never the stale request-start storage snapshot.Retry-Afterheader set to the earliest quota reset across the unroutable accounts./claude-killswitchslash command (on/off/set/status) for runtime management.Files:
packages/core/src/killswitch.ts— newpackages/core/src/accounts.ts— killswitch types and policy functions (sharedDEFAULT_KILLSWITCH_THRESHOLDS)packages/opencode/src/index.ts— killswitch fetch-gate + command registrationpackages/opencode/src/tests/killswitch.test.ts+index.test.tsfetch-gate testsREADME.md+packages/opencode/README.md— killswitch documentationSummary by cubic
Adds a per-account killswitch and a unified quota cache in
@cortexkit/anthropic-auth-coreso OpenCode blocks low‑quota requests and returns 429 with Retry‑After when unroutable or when the quota API is backed off. Adds/claude-killswitch, enforces the killswitch across all routing paths, and keeps the sidebar accurate on background fallback storage updates and after async main refreshes.New Features
getRoutableFallbackAccounts; token‑aware reads for main and fallbacks;failClosedOnUnknownQuotarespected when main quota is unknown;/claude-killswitchto view/toggle/set, persisted to the sidecarkillswitchblock; optionalquota.refreshEveryNRequests.onFallbackStorageChanged(token refresh, quota update, or error) and preserve the active fallback after async main quota refreshes; refresh can happen without a request.Bug Fixes
Written for commit 8c44a67. Summary will update on new commits.
Greptile Summary
This PR introduces a per-account killswitch that hard-blocks requests when remaining quota drops below configurable thresholds, returning a synthetic 429 with
Retry-Afteronly when main is killed and no routable fallbacks remain (or the request body is non-replayable). It also fixes a sidebar clobber race where an async main-quota refresh could overwrite the active fallback account, and addsonFallbackStorageChangedso the sidebar refreshes on background quota updates.packages/opencode/src/index.ts): eager quota refresh before evaluation, post-refresh re-read ofmainQuota, unifiedgetRoutableFallbackAccountsusinggetFallbackQuotafor consistent token-aware quota reads across all routing paths, and a fail-closed/backoff 429 guard before the killswitch evaluation.packages/core/src/accounts.ts):killswitchPassesPolicyiterates all windows withcontinueon missing entries so a present below-threshold window blocks even when the partner window is absent;killswitchRetryAfterSecondsreturns the earliest reset time across all accounts + 60 s buffer./claude-killswitchcommand (packages/core/src/killswitch.ts):on/off/set/statuswith per-account overrides andset allshorthand, persisted to the sidecar config.Confidence Score: 5/5
Safe to merge — the four issues flagged in earlier review rounds are all addressed in the current diff.
All four previously identified routing bugs — stale mainQuota bypassing first-request evaluation, killswitchPassesPolicy early-returning on the first missing window, inconsistent quota sources between allFallbacksKilled and survivingFallbacks, and the reactive fallback filter using stale a.quota — are fixed in this diff. Test coverage is comprehensive across unit and integration scenarios.
No files require special attention.
Important Files Changed
Comments Outside Diff (1)
packages/core/src/killswitch.ts, line 340-355 (link)thresholdsobject reference whenset allis usedWhen
entry.account === 'all', the samethresholdsobject is assigned toupdated.mainand to every entry inaccounts[id]. All these properties point to the same object in memory. Callers that receiveupdatedConfigand subsequently mutate threshold values (e.g., patching a single window in-place) would silently affect every account and the main entry simultaneously. Constructing a fresh object for each assignment ({ ...thresholds }) avoids the aliasing.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Reviews (12): Last reviewed commit: "Merge branch 'fix/sidebar-fallback-quota..." | Re-trigger Greptile