- 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
When all accounts fail with HTTP 500/503 errors (e.g., Google API returning
'Unknown Error' for Claude models on large conversations), the proxy now
attempts to use a fallback model if --fallback is enabled.
This enables graceful degradation when:
- All accounts are exhausted due to 5xx errors (not just rate limits)
- Claude models fail on very large conversations
- The API has temporary issues with specific models
The fallback uses the existing MODEL_FALLBACK_MAP configuration:
- claude-opus-4-5-thinking -> gemini-3-pro-high
- claude-sonnet-4-5-thinking -> gemini-3-flash
Relates to #88
- 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 test-schema-sanitizer.cjs to run-all.cjs test runner
- Add test:sanitizer npm script for running it individually
- Update test to use renamed cleanSchema function
- Fix interleaved thinking test to not require thinking blocks after
tool result (model decides when to use visible thinking)
Co-Authored-By: Claude <noreply@anthropic.com>
The /compact command was failing with 'Proto field is not repeating,
cannot start list' error for Claude models because tool schemas were
sent with lowercase JSON Schema types (array, object, string) but
Google's Cloud Code API expects uppercase protobuf types (ARRAY,
OBJECT, STRING).
Changes:
- Add toGoogleType() function to convert JSON Schema types to Google format
- Add Phase 5 to cleanSchemaForGemini() for type conversion
- Apply cleanSchemaForGemini() for ALL models (not just Gemini) since
all requests go through Cloud Code API which validates schema format
- Add comprehensive test suite with 10 tests covering nested arrays,
complex schemas, and real-world Claude Code tool scenarios
Fixes#82
- 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 [ignore] tags around system instruction to prevent model from
identifying as "Antigravity" when asked "Who are you?"
- Replace full system instruction with minimal version used by
CLIProxyAPI/gcli2api to reduce token usage and improve response quality
Fixes#76
Co-Authored-By: Claude <noreply@anthropic.com>
Adopts issue template pattern from opencode-antigravity-auth:
- Bug report template with [BUG] prefix and 6-item checklist
- Feature request template with [FEATURE] prefix
- Config disables blank issues, adds links to Google Cloud Support, TOS, and Discussions
Co-Authored-By: Claude <noreply@anthropic.com>
- 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
Fixes issue #71 - 'No accounts available' error when API returns 429
The Google Cloud Code API can return 429 RESOURCE_EXHAUSTED errors even
when accounts have quota available due to:
- Temporary API load/throttling
- Per-minute request limits (not per-day quota)
- Transient backend issues
This fix adds:
1. A 500ms buffer after waiting for rate limits to expire
2. Optimistic rate limit reset when all accounts appear stuck
3. Retry logic that clears rate limits and tries again
The fix works in conjunction with the server-level optimistic reset
that already exists, providing multiple layers of protection against
false 'No accounts available' errors.
Co-Authored-By: Claude <noreply@anthropic.com>
- Add test:emptyretry script and include in test suite
- Fix test-interleaved-thinking: use complex prompt to force thinking
- Fix test-multiturn-thinking-tools: make Turn 2 lenient (thinking optional)
- Fix test-multiturn-thinking-tools-streaming: same lenient approach
- Use TEST_MODELS helper instead of hardcoded model ID
Models may skip thinking on obvious next steps - this is valid behavior.
Tests now only require thinking on first turn to verify signatures work.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Dashboard Enhancements
- Add Request Volume trend chart with Chart.js line graph
- Support Family/Model display modes for aggregation levels
- Show Total/Today/1H usage statistics
- Hierarchical filter dropdown with Smart select (Top 5 by 24h usage)
- Persist chart preferences to localStorage
- Improve account health detection logic
- Core models (sonnet/opus/pro/flash) require >5% quota to be healthy
- Dynamic quota ring chart supporting any model family
- Unify table styles with standard-table class
## Global Style Refactoring
- Add CSS variable system for theming
- Space color scale (950/900/850/800/border)
- Neon accent colors (purple/green/cyan/yellow/red)
- Text hierarchy (main/dim/muted/bright)
- Chart palette (16 colors)
- Add unified component classes
- .view-container for consistent page layouts
- .section-header/.section-title/.section-desc
- .standard-table for table styling
- Update scrollbar, nav-item, progress-bar to use theme variables
## Settings Module Extensions
- Add model mapping column in Models tab
- Enhance model selectors with family color indicators
- Support horizontal scroll for tabs on narrow screens
- Add defaultCooldownMs and maxWaitBeforeErrorMs config options
## New Module
- Add src/modules/usage-stats.js for request tracking
- Track /v1/messages and /v1/chat/completions endpoints
- Hierarchical storage: { hour: { family: { model: count } } }
- Auto-save every minute, 30-day retention
- GET /api/stats/history endpoint for dashboard chart
## Backend Changes
- Add direct account manipulation helpers (bypass AccountManager)
- Add POST /api/config/password endpoint for WebUI password change
- Auto-reload AccountManager after account operations
- Use CSS variables in OAuth callback pages
## Other
- Update .gitignore for runtime data directory
- Add i18n keys for new UI elements (EN/zh_CN)
Co-Authored-By: Claude <noreply@anthropic.com>
Adds comprehensive test for the empty response retry mechanism:
- Verifies EmptyResponseError class exists and works correctly
- Tests basic requests still work (no regression)
- Validates error class behavior and detection
All tests pass successfully.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Issues found by Claude Opus 4.5 + Gemini 3 Pro:
HIGH PRIORITY FIXES:
- Mark account rate-limited when 429 occurs during retry (was losing resetMs)
- Add exponential backoff between retries (500ms, 1000ms, 2000ms)
- Fix 5xx handling: don't pass error response to streamer, refetch instead
- Use recognizable error messages (429/401) for isRateLimitError/isAuthError
MEDIUM PRIORITY FIXES:
- Refactor while loop to for loop for clearer retry semantics
- Simplify logic flow with early returns
Code review by: Claude Opus 4.5 + Gemini 3 Pro Preview
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move MAX_EMPTY_RESPONSE_RETRIES to constants.js for consistency
- Handle 429/401/5xx errors properly during retry fetch
- Use proper message ID format (crypto.randomBytes) instead of Date.now()
- Add crypto import for UUID generation
Code review by: Gemini 3 Pro Preview + Claude Opus 4.5
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When Claude Code sends requests with large thinking_budget values,
the model may spend all tokens on "thinking" and return empty responses,
causing Claude Code to stop mid-conversation.
This commit adds a retry mechanism that:
- Throws EmptyResponseError instead of emitting fake message on empty response
- Retries up to 2 times before giving up
- Emits fallback message only after all retries are exhausted
Changes:
- src/errors.js: Added EmptyResponseError class and isEmptyResponseError()
- src/cloudcode/sse-streamer.js: Throw error instead of yielding fake message
- src/cloudcode/streaming-handler.js: Added retry loop with fallback
Tested for 6+ hours with 1,884 API requests and 88% recovery rate
on empty responses.
Fixes#61🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>