Stability fixes for the Gemini provider — no new features:
- Map SAFETY/RECITATION/BLOCKLIST finish reasons (gemini-to-openai → content_filter)
- Add 15s per-page timeout on models sync pagination to prevent indefinite hangs
- Fix mime_type → mimeType in inlineData to match Gemini v1beta API (camelCase)
- Fix include_thoughts → includeThoughts to match Gemini API (camelCase)
- Add inlineData/mime_type fallback in gemini-to-openai request translator
Google AI Studio defaults to 50 models per page. Set pageSize=1000
to maximize per-page results and follow nextPageToken to fetch all
available models across pages. Also fixes query param separator when
base URL already contains query string.
Replace inline `provider === "gemini"` checks in chatCore.ts and auth.ts
with shared hasPerModelQuota() and lockModelIfPerModelQuota() from
accountFallback.ts. Also adds max-cooldown preservation to lockModel()
to prevent race conditions from overwriting longer lockouts.
isModelLocked() was called to lock models on 429 but never checked
when selecting connections. Requests to a locked model would still
route to it, causing unnecessary repeated 429s.
Gemini AI Studio enforces per-model quotas. Previously a 429 on
gemini-2.5-pro would mark the entire connection as credits_exhausted,
blocking all models on that API key.
Three-layer fix:
- chatCore: lock model only (not connection) for RATE_LIMITED and
QUOTA_EXHAUSTED errors from Gemini
- auth: early-return with model-only lockout before terminal status
check, so credits_exhausted is never set on the connection
- rateLimitManager: use model-scoped limiter keys for Gemini so the
Bottleneck queue pauses only the affected model, not the connection
- chat: skip markAccountExhaustedFrom429 for Gemini (per-model quotas)
Gemini AI Studio has per-model quota limits. When one model hits its
quota (429), other models on the same API key may still be available.
- Use lockModel() for 429s on Gemini (model-only lockout, connection
stays active for other models)
- Skip markAccountExhaustedFrom429 for Gemini (prevents deprioritizing
the entire connection in credential selection)
- Apply model-only 404 lockout for Gemini too (deprecated/unavailable
models shouldn't disable the provider)
Match reset() behavior — clear lastFailureTime when recovering from
OPEN state to avoid stale timestamps in persisted state.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Show import progress dialog when adding Gemini API key with model
list, completion status, and Close button
- Remove hardcoded Gemini model registry — models come exclusively
from Google API sync per API key
- Hide "Import from /models" button for Gemini (sync handles it)
- Remove server-side fire-and-forget auto-sync (client handles it)
- Categorize synced Gemini models by endpoint type in catalog:
embedding, image, and audio (transcription + speech)
- Add modelsImported and close i18n keys to all 33 languages
Combo handlers call _onSuccess()/_onFailure() directly instead of
execute(), bypassing the OPEN→HALF_OPEN→CLOSED transition. After
resetTimeout elapses, canExecute() returns true and requests flow
through, but _onSuccess() only reset failureCount without changing
state — leaving the breaker permanently OPEN with 0 failures.
Handle OPEN state in both methods: _onSuccess() now transitions
OPEN→CLOSED, _onFailure() skips redundant re-transition.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Auto-sync is fire-and-forget on the server, so the dashboard needs to
poll for model updates after saving a Gemini key (3s delay). On delete,
refresh models immediately since DB cleanup is synchronous.
Removed hardcoded registry fallback for Gemini in dashboard, catalog,
and v1beta endpoints. Without synced models (no API keys), Gemini shows
nothing. Hardcoded entries are always removed from v1beta regardless
of sync result.
Store synced models keyed by providerId:connectionId so each API key's
models are tracked separately. On read, union across all connections.
On connection delete, remove only that key's models. Models with no
remaining connections are automatically excluded.