feat(auth): add model-level rate limit locking for multi-bucket providers (#120)

Providers like Antigravity maintain separate quota buckets per model family
(e.g. Claude vs Gemini). A 429 on claude-opus previously locked the entire
account, preventing gemini-pro requests even though its quota was full.

This adds in-memory per-model locking so that only the specific model is
skipped during account selection while other models remain accessible.

Changes:
- Add model-aware lock tracking in auth.js (Map<connectionId:model, expiry>)
- Pass model context from chat handler to auth service
- Multi-bucket behavior gated to known providers (MULTI_BUCKET_PROVIDERS set)
- No database schema changes — locks are in-memory and clear on restart

Closes #110
This commit is contained in:
Nick Roth authored and GitHub committed 2026-02-15 11:35:13 +07:00
1 parent 69131295db
commit 202fee714b
2 files changed
+90 -8

No files matched your search

+2 -2
View File
@@ -120,7 +120,7 @@ async function handleSingleModelChat(body, modelStr, clientRawRequest = null, re
let lastStatus = null;
while (true) {
const credentials = await getProviderCredentials(provider, excludeConnectionId);
const credentials = await getProviderCredentials(provider, excludeConnectionId, model);
// All accounts unavailable
if (!credentials || credentials.allRateLimited) {
@@ -170,7 +170,7 @@ async function handleSingleModelChat(body, modelStr, clientRawRequest = null, re
if (result.success) return result.response;
// Mark account unavailable (auto-calculates cooldown with exponential backoff)
const { shouldFallback } = await markAccountUnavailable(credentials.connectionId, result.status, result.error, provider);
const { shouldFallback } = await markAccountUnavailable(credentials.connectionId, result.status, result.error, provider, model);
if (shouldFallback) {
log.warn("AUTH", `Account ${accountId}... unavailable (${result.status}), trying fallback`);