- Update data-store.js to filter out disabled accounts in computeQuotaRows()
- Update data-store.js to filter out disabled accounts in getUnfilteredQuotaData()
- Ensures Global Quota average and Account Distribution only reflect active accounts
Co-Authored-By: Claude <noreply@anthropic.com>
This commit addresses "Max retries exceeded" errors during stress testing where
all accounts would become exhausted simultaneously due to short per-second rate
limits triggering cascading failures.
## Rate Limit Parser (`rate-limit-parser.js`)
- Remove 2s buffer enforcement that caused cascading failures when API returned
short reset times (200-600ms). Now adds 200ms buffer for sub-500ms resets
- Add `parseRateLimitReason()` for smart backoff based on error type:
QUOTA_EXHAUSTED, RATE_LIMIT_EXCEEDED, MODEL_CAPACITY_EXHAUSTED, SERVER_ERROR
## Message/Streaming Handlers
- Add per-account+model rate limit state tracking with exponential backoff
- For short rate limits (< 1 second), wait and retry on same account instead
of switching - prevents thundering herd when all accounts hit per-second limits
- Add throttle wait support for fallback modes (emergency/lastResort)
- Add `calculateSmartBackoff()` with progressive tiers by error type
## HybridStrategy (`hybrid-strategy.js`)
- Refactor `#getCandidates()` to return 4 fallback levels:
- `normal`: All filters pass (health, tokens, quota)
- `quota`: Bypass critical quota check
- `emergency`: Bypass health check when ALL accounts unhealthy
- `lastResort`: Bypass BOTH health AND token bucket checks
- Add throttle wait times: 500ms for lastResort, 250ms for emergency
- Fix LRU calculation to use seconds (matches opencode-antigravity-auth)
## Health Tracker
- Increase `recoveryPerHour` from 2 to 10 for faster recovery (1 hour vs 5 hours)
## Account Manager
- Add consecutive failure tracking: `getConsecutiveFailures()`,
`incrementConsecutiveFailures()`, `resetConsecutiveFailures()`
- Add cooldown mechanism separate from rate limits with `CooldownReason`
- Reset consecutive failures on successful request
## Base Strategy
- Add `isAccountCoolingDown()` check in `isAccountUsable()`
## Constants
- Replace fixed `CAPACITY_RETRY_DELAY_MS` with progressive `CAPACITY_BACKOFF_TIERS_MS`
- Add `BACKOFF_BY_ERROR_TYPE` for smart backoff
- Add `QUOTA_EXHAUSTED_BACKOFF_TIERS_MS` for progressive quota backoff
- Add `MIN_BACKOFF_MS` floor to prevent "Available in 0s" loops
- Increase `MAX_CAPACITY_RETRIES` from 3 to 5
- Reduce `RATE_LIMIT_DEDUP_WINDOW_MS` from 5s to 2s
## Frontend
- Remove `capacityRetryDelayMs` config (replaced by progressive tiers)
- Update default `maxCapacityRetries` display from 3 to 5
## Testing
- Add `tests/stress-test.cjs` for concurrent request stress testing
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: add manual OAuth flow support in WebUI
* fix: reset add account modal state on close
* feat: display custom API key in startup banner
* fix: move translations to separate files and optimize import API
* fix: remove orphaned model-manager.js and cleanup callback server on manual auth
---------
Co-authored-by: Badri Narayanan S <59133612+badrisnarayanan@users.noreply.github.com>
The data store's fetchVersion() was never called, so maxAccounts stayed
at the default value of 10. Consolidated into the global store's
fetchVersion() which is called on init.
Co-Authored-By: Claude <noreply@anthropic.com>
Adds `maxAccounts` configuration parameter to control the maximum number of Google accounts.
**Changes:**
- New config field `maxAccounts` (default: 10, range: 1-100)
- Settings page: slider control for adjusting limit
- Accounts page: counter badge (e.g., "8/10") with visual feedback
- Add button disabled when limit reached
- Server-side validation on account creation
**Breaking Changes:** None
The version was stuck at "1.0.0" because fetchVersion() was only called
when initialLoad was true, but loadFromCache() set initialLoad to false
before fetchData() ran. Now version is fetched unconditionally in the
global store's init().
Fixes#144
Co-Authored-By: Claude <noreply@anthropic.com>
Refactor account selection into a strategy pattern with three options:
- Sticky: cache-optimized, stays on same account until rate-limited
- Round-robin: load-balanced, rotates every request
- Hybrid (default): smart distribution using health scores, token buckets, and LRU
The hybrid strategy uses multiple signals for optimal account selection:
health tracking for reliability, client-side token buckets for rate limiting,
and LRU freshness to prefer rested accounts.
Includes WebUI settings for strategy selection and unit tests.
Co-Authored-By: Claude <noreply@anthropic.com>
- Add pt.js translation file with complete PT-BR translations
- Add Portuguese option to language selector in settings
- Load pt.js translation file in index.html
Based on PR #108
Co-authored-by: Pedro Farias <feliperodriguesf62@gmail.com>
Co-authored-by: Wha1eChai <whaleora@gmail.com>
* feat: add i18n support with separate translation files
- Extract translations from store.js to separate files for easier management
- Add translation files for English (en.js), Indonesian (id.js), Turkish (tr.js), and Chinese (zh.js)
- Load translations via window.translations object before Alpine store initialization
- Add Bahasa Indonesia option to language selector
* feat: translate remaining hardcoded UI strings
- Update index.html to use t() for Menu and GitHub labels
- Update views to translate Tier, Quota, Live, tier badges, and close button
- Update components to use translated error messages and confirmation dialogs
- Update utils to use translated validation and error messages
- Update app-init.js to use translated OAuth success/error messages
Feat(ui): add Turkish language support and UI enhancements
Introduces Turkish language support and several UI/UX improvements to the web management interface.
- Remove nested x-data from save preset modal to fix scope access
- Add newPresetName to parent component state
- Ensure savingPreset state is correctly accessed from the button
- Clear input field on modal open and after successful save
- Cooldown now caps API-provided reset times instead of being a fallback
- Fixed misleading UI descriptions for cooldown settings
- Removed unused cooldownDurationMs from settings object
- Updated default fallback values in frontend to 10s
Co-Authored-By: Claude <noreply@anthropic.com>
- Add backend storage logic in `src/utils/claude-config.js` to save/load/delete presets
- Add API endpoints (`GET`, `POST`, `DELETE`) for presets in `src/webui/index.js`
- Update `public/views/settings.html` with new Presets UI card and modals
- Update `public/js/components/claude-config.js` with auto-load logic and unsaved changes protection
- Add translations (EN/ZH) for new UI elements in `public/js/store.js`
- Add integration tests in `tests/frontend/test-frontend-settings.cjs`
- Update compiled CSS
Co-Authored-By: Claude <noreply@anthropic.com>
Add debouncing to chart updates to prevent rapid flickering, implement checks to avoid redundant history processing and double renders, and disable quota chart animations to fix visual glitches.
Improve robustness of chart updates in dashboard components by adding
force destroy checks across canvas properties, component state, and
Chart.js registry to prevent memory leaks and instance conflicts.
Save new chart instances to both canvas and component for better tracking.
Add a 24-hour time-to-live check to the data cache restoration logic to prevent using stale cached data. This ensures data freshness by expiring and removing outdated cache entries before restoration. Also corrected a minor typo in the validity check comment.
Extract hardcoded priority logic into a DEAD_THRESHOLD constant and MODEL_TIERS array for better maintainability and readability. This refactoring improves code organization without altering functionality.
Switch from substring includes to regex word boundary tests for model names like opus, sonnet, and gemini variants, improving accuracy in the account manager's prioritization logic.
- Implement localStorage-based caching in data-store to restore accounts, models, and usage data on load, improving initial render performance
- Add hash-based routing in global store to sync active tab with URL, enabling browser back/forward navigation and direct linking to tabs
Add sorting functionality to the models table with clickable headers for columns like Stat, Model Identity, Global Quota, Next Reset, and Account Distribution. Includes dynamic sort icons and logic to handle ascending/descending order with appropriate defaults.
Introduce a priority-based system for selecting the main model quota, considering model tiers (e.g., opus, sonnet, pro) and availability status. This enhances accuracy by treating models with less than 1% remaining quota as "dead" for prioritization, ensuring users see the most relevant and active model in the dashboard.
Implement responsive sidebar functionality that auto-opens on desktop (≥1024px) and auto-closes on mobile, with a toggle button for mobile users. Added overlay for mobile sidebar dismissal and CSS for collapsed state on desktop. Minor adjustments to dashboard chart borders and grid layouts.
The WebUI was generating model names like "gemini-3-flash [1m]" with a
space before the suffix, causing 404 errors when Claude Code used
sub-agents. Changed to "gemini-3-flash[1m]" (no space).
Fixes#97
Co-Authored-By: Claude <noreply@anthropic.com>
Ensure the visibility change event listener for health checks is set up only once
and properly removed on destroy to avoid memory leaks and duplicate handlers.
Implement periodic health checks every 15 seconds to monitor connection status,
pausing when the tab is hidden and resuming on visibility. Update UI bindings
to use data store for connection status instead of global store. Add destroy
method to clean up timers on component teardown.
- Replace Tailwind CDN with local build (PostCSS + autoprefixer + daisyui)
- Add CSS build scripts with automatic prepare hook on npm install
- Create account-actions.js service layer with unified response format
- Extend ErrorHandler.withLoading() for automatic loading state management
- Add skeleton screens for initial load, silent refresh for subsequent updates
- Implement loading animations for async operations (buttons, modals)
- Improve empty states and add ARIA labels for accessibility
- Abstract component styles using @apply (buttons, badges, inputs)
- Add JSDoc documentation for Dashboard modules
- Update README and CLAUDE.md with development guidelines
- Update CLAUDE.md with comprehensive WebUI architecture and API documentation
- Improve settings UI with searchable model dropdowns and visual family indicators
- Migrate usage statistics persistence to user config directory with auto-migration
- Refactor server request handling and fix model suffix logic
- Add time range selector (1H/6H/24H/7D/All) with preference persistence
- Implement smart X-axis label formatting for multi-day usage data
- Standardize global component spacing and fix CSS @apply limitations
- Add elegant empty state UI for charts when filtered data is absent
- Update i18n translations for all new dashboard features
- Add ENABLE_EXPERIMENTAL_MCP_CLI toggle in Claude CLI settings (default: true)
- Add Gemini 1M Context Mode toggle for [1m] suffix (default: true)
- Auto-apply [1m] suffix to existing Gemini model configurations
- Add i18n translations for both features (English and Chinese)
- Add standalone Models tab with real-time quota/status display
- Move model identity table from Dashboard to Models tab
- Slim down Dashboard to KPI cards and charts only
- Dashboard charts now use unfiltered data (independent of Models filters)
Settings > Models improvements:
- Remove redundant Alias column (only Mapping is functional)
- Fix column misalignment bug (empty td)
- Add column widths and hidden row opacity styling
- Single row edit constraint (only one Mapping editable at a time)
- showHiddenModels toggle now only affects Settings (not Models tab)
- Update description text to match current functionality
i18n:
- Add 'models' and 'modelsPageDesc' keys (EN/ZH)
- Add 'modelMappingHint' for Claude CLI guidance
- Update 'modelsDesc' to reflect new functionality