Standardize filter bar layout across admin pages to place search/filters
on left and action buttons on right within the same row, improving
visual consistency and space utilization.
Upstream accounts now use the standard APIKey type instead of a dedicated
upstream type. GetBaseURL() and new GetGeminiBaseURL() automatically append
/antigravity for Antigravity platform APIKey accounts, eliminating the need
for separate upstream forwarding methods.
- Remove ForwardUpstream, ForwardUpstreamGemini, testUpstreamConnection
- Remove upstream branch guards in Forward/ForwardGemini/TestConnection
- Add migration 052 to convert existing upstream accounts to apikey
- Update frontend CreateAccountModal to create apikey type
- Add unit tests for GetBaseURL and GetGeminiBaseURL
- EditAccountModal: add Base URL / API Key fields for upstream type
- EditAccountModal: initialize editBaseUrl from credentials on upstream account open
- EditAccountModal: save upstream credentials (base_url, api_key) on submit
- CreateAccountModal: pass mixed_scheduling extra when creating upstream account
1. Frontend: replace hardcoded antigravityDefaultMappings with async
fetch from GET /admin/accounts/antigravity/default-model-mapping,
eliminating the duplicate data source that caused frontend/backend
mapping inconsistency.
2. Backend: convert handleSmartRetry and antigravityRetryLoop from
standalone functions to AntigravityGatewayService methods, enabling
Redis cache sync (updateAccountModelRateLimitInCache) after both
rate-limit write paths — long-delay branch and retry-exhausted branch.
Change formatTime() to include seconds (HH:MM:SS) instead of only
hours and minutes (HH:MM). This gives users more precise information
about when rate limits will reset.
This feature allows API Keys to have their own quota limits and expiration
times, independent of the user's balance.
Backend:
- Add quota, quota_used, expires_at fields to api_key schema
- Implement IsExpired() and IsQuotaExhausted() checks in middleware
- Add ResetQuota and ClearExpiration API endpoints
- Integrate quota billing in gateway handlers (OpenAI, Anthropic, Gemini)
- Include quota/expiration fields in auth cache for performance
- Expiration check returns 403, quota exhausted returns 429
Frontend:
- Add quota and expiration inputs to key create/edit dialog
- Add quick-select buttons for expiration (+7, +30, +90 days)
- Add reset quota confirmation dialog
- Add expires_at column to keys list
- Add i18n translations for new features (en/zh)
Migration:
- Add 045_add_api_key_quota.sql for new columns
- Add new API endpoint GET /admin/users/:id/balance-history with pagination and type filter
- Add SumPositiveBalanceByUser for calculating total recharged amount
- Create UserBalanceHistoryModal component with:
- User info header (email, username, created_at, current balance, notes, total recharged)
- Type filter dropdown (all/balance/admin_balance/concurrency/admin_concurrency/subscription)
- Quick deposit/withdraw buttons
- Paginated history list with icons and colored values
- Add instant tooltip on balance column for better UX
- Add z-index prop to BaseDialog for modal stacking control
- Update i18n translations (zh/en)