fix: narrow rate-limit provider config

Narrow RateLimitService provider config wiring so OpenCode Go receives provider-specific config while Gemini keeps its OAuth-enabled setting through a separate resolver.\n\nValidated locally with the full src/main/rate-limits test suite and typecheck.
This commit is contained in:
Siddiqui Qamar 2026-06-20 19:28:12 -03:00 committed by GitHub
parent e981b477d2
commit 8c6ce31036
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 43 additions and 28 deletions

View File

@ -1328,7 +1328,14 @@ app.whenReady().then(async () => {
rateLimits.setClaudeAuthPreparationResolver((target) =>
claudeRuntimeAuth!.prepareForRateLimitFetch(target)
)
rateLimits.setSettingsResolver(() => store!.getSettings())
rateLimits.setOpenCodeGoConfigResolver(() => {
const settings = store!.getSettings()
return {
sessionCookie: settings.opencodeSessionCookie,
workspaceIdOverride: settings.opencodeWorkspaceId
}
})
rateLimits.setGeminiCliOAuthEnabledResolver(() => store!.getSettings().geminiCliOAuthEnabled)
keybindings = new KeybindingService({
homePath: app.getPath('home'),
getLegacyOverrides: () => store!.getSettings().keybindings

View File

@ -335,10 +335,11 @@ describe('RateLimitService', () => {
it('fetches Gemini and OpenCode Go alongside Claude and Codex', async () => {
const service = new RateLimitService()
service.setSettingsResolver(() => ({
opencodeSessionCookie: 'session=abc123',
opencodeWorkspaceId: ''
service.setOpenCodeGoConfigResolver(() => ({
sessionCookie: 'session=abc123',
workspaceIdOverride: ''
}))
service.setGeminiCliOAuthEnabledResolver(() => true)
vi.mocked(fetchClaudeRateLimits).mockResolvedValueOnce(okProvider('claude', 10, Date.now()))
vi.mocked(fetchCodexRateLimits).mockResolvedValueOnce(okProvider('codex', 20, Date.now()))
@ -356,6 +357,7 @@ describe('RateLimitService', () => {
})
expect(fetchCodexRateLimits).toHaveBeenCalledTimes(1)
expect(fetchGeminiRateLimits).toHaveBeenCalledTimes(1)
expect(fetchGeminiRateLimits).toHaveBeenCalledWith(true)
expect(fetchOpenCodeGoRateLimits).toHaveBeenCalledTimes(1)
expect(fetchOpenCodeGoRateLimits).toHaveBeenCalledWith('session=abc123', undefined)
@ -678,7 +680,10 @@ describe('RateLimitService', () => {
it('isolates provider failures so one error does not block others', async () => {
const service = new RateLimitService()
service.setSettingsResolver(() => ({ opencodeSessionCookie: '', opencodeWorkspaceId: '' }))
service.setOpenCodeGoConfigResolver(() => ({
sessionCookie: '',
workspaceIdOverride: ''
}))
vi.mocked(fetchClaudeRateLimits).mockRejectedValueOnce(new Error('claude down'))
vi.mocked(fetchCodexRateLimits).mockResolvedValueOnce(okProvider('codex', 20, Date.now()))
@ -701,7 +706,10 @@ describe('RateLimitService', () => {
it('discards stale data when a provider becomes unavailable', async () => {
const service = new RateLimitService()
let cookie = 'session=valid'
service.setSettingsResolver(() => ({ opencodeSessionCookie: cookie, opencodeWorkspaceId: '' }))
service.setOpenCodeGoConfigResolver(() => ({
sessionCookie: cookie,
workspaceIdOverride: ''
}))
// 1. Success fetch
vi.mocked(fetchClaudeRateLimits).mockResolvedValue(okProvider('claude', 10, Date.now()))
@ -736,9 +744,9 @@ describe('RateLimitService', () => {
it('discards stale data when Workspace ID override is changed', async () => {
const service = new RateLimitService()
let workspaceId = 'wrk_A'
service.setSettingsResolver(() => ({
opencodeSessionCookie: 'session=valid',
opencodeWorkspaceId: workspaceId
service.setOpenCodeGoConfigResolver(() => ({
sessionCookie: 'session=valid',
workspaceIdOverride: workspaceId
}))
// 1. Success fetch for Workspace A

View File

@ -37,6 +37,13 @@ type ClaudeAuthPreparationResolver = (
target?: ClaudeAccountSelectionTarget
) => Promise<ClaudeRuntimeAuthPreparation>
type OpenCodeGoRateLimitConfig = {
sessionCookie: string
workspaceIdOverride: string
}
type GeminiCliOAuthEnabledResolver = () => boolean
// Why: Claude's subscription usage endpoint has a tight request budget. Quota
// state is informational, so prefer keeping a recent snapshot over polling it
// into 429s during long focused Orca sessions.
@ -98,13 +105,8 @@ export class RateLimitService {
runtime: 'host',
wslDistro: null
}
private settingsResolver:
| (() => {
opencodeSessionCookie: string
opencodeWorkspaceId: string
geminiCliOAuthEnabled?: boolean
})
| null = null
private openCodeGoConfigResolver: (() => OpenCodeGoRateLimitConfig) | null = null
private geminiCliOAuthEnabledResolver: GeminiCliOAuthEnabledResolver | null = null
private inactiveClaudeAccountsResolver: (() => InactiveClaudeAccountInfo[]) | null = null
private inactiveCodexAccountsResolver: (() => InactiveCodexAccountInfo[]) | null = null
private inactiveClaudeCache = new Map<string, ProviderRateLimits>()
@ -142,14 +144,12 @@ export class RateLimitService {
this.claudeFetchTarget = normalizeClaudeAccountSelectionTarget(target)
}
setSettingsResolver(
resolver: () => {
opencodeSessionCookie: string
opencodeWorkspaceId: string
geminiCliOAuthEnabled?: boolean
}
): void {
this.settingsResolver = resolver
setOpenCodeGoConfigResolver(resolver: () => OpenCodeGoRateLimitConfig): void {
this.openCodeGoConfigResolver = resolver
}
setGeminiCliOAuthEnabledResolver(resolver: GeminiCliOAuthEnabledResolver): void {
this.geminiCliOAuthEnabledResolver = resolver
}
setInactiveClaudeAccountsResolver(resolver: () => InactiveClaudeAccountInfo[]): void {
@ -819,10 +819,10 @@ export class RateLimitService {
const codexProvenance = this.getCodexProvenance(codexTarget, codexHomePath)
const codexGeneration = this.codexFetchGeneration
const previousState = this.state
const settings = this.settingsResolver?.()
const cookie = settings?.opencodeSessionCookie ?? ''
const workspaceIdOverride = settings?.opencodeWorkspaceId ?? ''
const geminiCliOAuthEnabled = settings?.geminiCliOAuthEnabled ?? false
const openCodeGoConfig = this.openCodeGoConfigResolver?.()
const cookie = openCodeGoConfig?.sessionCookie ?? ''
const workspaceIdOverride = openCodeGoConfig?.workspaceIdOverride ?? ''
const geminiCliOAuthEnabled = this.geminiCliOAuthEnabledResolver?.() ?? false
// Detect if configuration changed — if it did, we must discard any stale
// data because it belongs to a different session/workspace.