- consolidate 'pro'/'ultra' into single 'paid' tier (no distinction needed)
- update mapTierString() and inferTierFromModels() in quota-fetcher.ts
- fix tier_priority default from ['ultra','pro'] to ['paid']
- add missing quota_management to mergeWithDefaults() in config-loader
- update UI tier badge styling for 'paid' tier
- update api-client.ts tier type definition
Tier detection now uses paidTier/currentTier from loadCodeAssist API
response instead of inferring from model names. This is the correct
approach - all Antigravity accounts have access to same models
regardless of tier.
- Add TierInfo interface and tier fields to LoadCodeAssistResponse
- Add mapTierString() helper for API → AccountTier conversion
- Update getProjectId() to extract and return tier
- Update fetchAccountQuota() to use API tier
- Remove flawed detectTier() function
2.5-pro is a standard pro-tier model, not ultra. This caused all accounts
with gemini-2.5-pro access to incorrectly display ULTRA badge.
Tier will be re-detected on next quota fetch for existing accounts.
- Trim nickname in API route for consistency with CLI
- Block URL-unsafe chars (%, /, &, ?, #) in nickname
- Block reserved patterns (kiro-N, ghcp-N) used by auto-discovery
- Add reload-merge pattern in discovery to reduce race condition
- add pause/resume dropdown menu option in account item
- display tier badges (ultra/pro/free) with color coding
- show paused badge when account is paused
- wire onPauseToggle through component tree
Refs #282
Previously touchAccount was only called when switching accounts or auto-
switching due to quota exhaustion. Now lastUsedAt is updated for every
OAuth provider execution, ensuring dashboard shows accurate timestamps.
- add paused state and tier field to OAuthAccount
- create quota-manager.ts for central quota/tier logic
- add tier detection and 30s cache to quota-fetcher
- add quota_management schema to unified config
Refs #282
Kiro/GHCP OAuth tokens have empty email field, causing all accounts to
use accountId='default' and overwrite each other. This fix:
- Add PROVIDERS_WITHOUT_EMAIL constant for kiro/ghcp identification
- Require nickname for kiro/ghcp during registration (CLI + web UI)
- Use nickname as accountId instead of email for these providers
- Enforce nickname uniqueness to prevent collisions
- Update discoverExistingAccounts() to generate unique IDs (kiro-1, etc.)
Closes#258, #267
- Clear stdinKeepalive interval on SIGINT/SIGTERM signal handlers
- Add cancelProjectSelection() to timeout/exit/error handlers
- Close server on error path in testLocalhostBinding to prevent fd leak
- Add TTL-based cleanup for stale auth sessions (10 min expiry)
- Use DEVICE_CODE_TIMEOUT_MS constant instead of hardcoded value (DRY)
CLIProxyAPIPlus has a 15-second timer that prompts for manual URL paste.
If user completes browser auth after this timer fires but before the
non-blocking check, the prompt blocks forever on stdin since CCS pipes
stdin but doesn't write to it.
Workaround: Send newline every 16s for authorization code flows to skip
the manual prompt and continue polling for callback.
Port cleanup before OAuth was skipped for providers whose ports were
only in comments. This caused hanging when stale processes blocked
the callback port from previous auth attempts.
Changes:
- auth-types.ts: Add codex (1455), agy (51121), iflow (11451) to map
- oauth-port-diagnostics.ts: Update iflow from device_code to auth_code flow
- Add Claude (54545) to doc comments for future reference
- Replace 4-button row with 3 icon buttons (restart, stop, settings)
- Add tooltips to all icon buttons via TooltipProvider
- Move version display to header next to title
- Implement collapsed/expanded two-state design
- Remove manual version input field (use dropdown only)
- Add clickable update/downgrade badge showing target version
- Add "Version Management" section header in expanded view
- Increase control sizes (h-8) for better touch targets
- Settings icon toggles to X when expanded
- Fix formatQuotaBar crash on percentage > 100 or < 0 (clamp to 0-100)
- Fix shared project accounts excluded from failover (same GCP project = pooled quota)
- Fix division by zero in avgQuota when models array empty
- Fix null account label fallback to 'Unknown Account'
The button was incorrectly calling handleRestart (pure restart) instead
of triggering version install. Now correctly installs latestVersion for
updates or maxStableVersion for downgrades.
Implements comprehensive version management for CLIProxyAPI Plus:
Backend APIs:
- GET /versions: fetch available versions from GitHub releases
- POST /install: install specific version with force flag for unstable
- POST /restart: restart proxy without version change
Frontend:
- 4-button layout: Restart, Update/Downgrade, Stop, Settings gear
- Collapsible version picker with dropdown + manual input
- Confirmation dialog for unstable versions (>6.6.80)
- Progressive disclosure (version picker hidden by default)
Ref: plans/260105-1250-cliproxy-version-management/
- Show amber warning indicator when installed version is unstable (v81+)
- Version display now shows "(unstable)" suffix with amber styling
- "Downgrade" button replaces "Update" when version is unstable
- Tooltip explains restart will downgrade to stable version
Fixes#273
The websearch-transformer hook used hardcoded 'which' command which doesn't
exist on Windows. Now uses process.platform detection to choose 'where' on
Windows and 'which' on Unix systems.
Add version stability warnings to Dashboard API and UI:
- Extend /api/cliproxy/update-check with isStable, maxStableVersion, stabilityMessage
- Health check shows warning status for v81+ installations
- UI header displays version badge with amber warning for unstable
Closes: relates to #269