Commit Graph

150 Commits

Author SHA1 Message Date
Badri Narayanan S
90b38bbb56 feat: validate model IDs before processing requests
Add model validation cache with 5-minute TTL to reject invalid model IDs
upfront instead of sending them to the API. This provides better error
messages and avoids unnecessary API calls.

- Add MODEL_VALIDATION_CACHE_TTL_MS constant (5 min)
- Add isValidModel() with lazy cache population
- Warm cache when listModels() is called
- Validate model ID in /v1/messages before processing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 19:07:23 +05:30
Badri Narayanan S
2ab0c7943d fix: fail immediately on 400 errors instead of cycling accounts
400 errors (INVALID_ARGUMENT) are client errors that won't be fixed by
switching accounts. Previously the proxy would cycle through all accounts
before returning the error. Now it fails immediately.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 18:36:07 +05:30
jgor20
a43d2332ca feat: per-account quota threshold protection (#212)
feat: per-account quota threshold protection

Resolves #135

- Adds configurable quota protection with three-tier threshold resolution (per-model → per-account → global)
- New global Minimum Quota Level slider in Settings
- Per-account threshold settings via Account Settings modal
- Draggable per-account threshold markers on model quota bars
- Backend: PATCH /api/accounts/:email endpoint, globalQuotaThreshold config
- i18n: quota protection keys for all 5 languages
2026-02-01 17:15:46 +05:30
Badri Narayanan S
33584d31bb fix: suppress count_tokens 501 error logs
Use startsWith() for count_tokens URL check to match requests with
query parameters (e.g., ?beta=true).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 16:55:31 +05:30
Badri Narayanan S
f80e60668c fix: improve mode toggle robustness and add i18n support
- Make mode detection more robust (handle ::1, 0.0.0.0)
- Add getProxyPort() to parse port from ANTHROPIC_BASE_URL dynamically
- Add i18n translation keys for mode toggle in all 5 languages
- Update settings.html to use translation keys and dynamic port

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 16:47:30 +05:30
Badri Narayanan S
02f8e2e323 Merge main into PR #221 to resolve conflicts
Resolved merge conflicts in public/views/settings.html:
- Fixed HTML entity escaping for quote characters in presetHint text
- Fixed HTML entity escaping for pendingPresetName text
2026-02-01 16:20:55 +05:30
Badri Narayanan S
793b20db59 Merge pull request #210 from IrvanFza/feat/version-display
feat: display version prominently in CLI banner and WebUI navbar
2026-02-01 16:14:40 +05:30
Badri Narayanan S
f9bdeddd0d Merge pull request #208 from jgor20/fix/webui-console-errors-and-logging
fix(webui): resolve console errors and misleading server logs
2026-02-01 16:10:42 +05:30
Badri Narayanan S
3c2f324eff fix: honor HOST environment variable for server binding
- Update src/index.js to use HOST environment variable for main server
- Update src/auth/oauth.js to use HOST environment variable for OAuth callback server
- Add diagnostic logging to show actual bound address on startup
- Update startup banner to reflect correct host URL

Co-Authored-By: Claude (gemini-3-flash[1m]) <noreply@anthropic.com>
2026-01-31 00:27:19 +05:30
JEEL TILVA
7985524d49 feat: Implement API and UI for toggling Claude CLI between proxy and paid modes 2026-01-30 13:45:16 +05:30
Badri Narayanan S
ca6783f153 chore: bump user agent version to 1.15.8
Co-Authored-By: Claude (claude-opus-4-5-thinking) <noreply@anthropic.com>
2026-01-29 23:55:15 +05:30
Irvan Fauziansyah
f786e3b3c6 feat: add version display to CLI banner and WebUI
- Add getPackageVersion() utility function in src/utils/helpers.js
- Display version in CLI startup banner (e.g., "v2.4.2")
- Display version in WebUI navbar next to "CLAUDE PROXY SYSTEM"
- Refactor WebUI to use shared getPackageVersion() utility
- Update footer with GitHub icon and link
2026-01-29 16:31:14 +07:00
jgor20
b012fe0245 fix(server): use originalUrl in request logger and suppress .well-known noise
- Changed logging middleware to use req.originalUrl instead of req.path,
  which was mangled by Express wildcard catch-all path stripping
- Suppress Chrome DevTools /.well-known/ requests from logs (debug-only)
2026-01-28 23:02:00 +00:00
Badri Narayanan S
b64809277c chore: update default haiku model to claude-sonnet-4-5 and gemini-3-flash
- Claude preset: gemini-2.5-flash-lite → claude-sonnet-4-5
- Gemini preset: gemini-2.5-flash-lite → gemini-3-flash
- Remove outdated quota warning about haiku model usage

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-26 14:17:11 +05:30
Badri Narayanan S
bc8d428107 Merge pull request #187 from quocthai0404/fix/issue-176-windows-callback-port
fix: Make OAuth callback port configurable for Windows compatibility (#176)
2026-01-26 13:45:13 +05:30
Badri Narayanan S
683ca41480 fix: strip cache_control fields from content blocks (#189)
Claude Code CLI sends cache_control on text, thinking, tool_use, and
tool_result blocks for prompt caching. Cloud Code API rejects these
with "Extra inputs are not permitted".

- Add cleanCacheControl() to proactively strip cache_control at pipeline entry
- Add sanitizeTextBlock() and sanitizeToolUseBlock() for defense-in-depth
- Update reorderAssistantContent() to use block sanitizers
- Add test-cache-control.cjs with multi-model test coverage
- Update frontend dashboard tests to match current UI design
- Update strategy tests to match v2.4.0 fallback behavior
- Update CLAUDE.md and README.md with recent features

Inspired by Antigravity-Manager's clean_cache_control_from_messages() pattern.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-25 03:27:05 +05:30
Badri Narayanan S
5a85f0cfcc feat: comprehensive rate limit handling overhaul (inspired by opencode-antigravity-auth)
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>
2026-01-24 22:43:53 +05:30
quocthai0404
54fc1da829 fix: make OAuth callback port configurable for Windows compatibility (#176)
- Add OAUTH_CALLBACK_PORT environment variable (default: 51121)
- Implement automatic port fallback (51122-51126) on EACCES/EADDRINUSE
- Add Windows-specific troubleshooting in error messages and README
- Document configuration in config.example.json

Closes #176
2026-01-24 14:28:31 +07:00
董飞祥
9992c4ab27 feat: Add manual OAuth authorization mode for WebUI (#131)
* 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>
2026-01-23 18:53:29 +05:30
Badri Narayanan S
0fa945b069 fix: don't count rate limit waits as failed retry attempts
When all accounts are rate-limited or token-exhausted, the retry loop
was incorrectly counting the wait time as a failed attempt. This caused
premature "Max retries exceeded" errors when we were just patiently
waiting for accounts to become available.

- Add attempt-- after sleeping for rate limits or strategy waits
- Add #diagnoseNoCandidates() to hybrid strategy for better logging
- Add getTimeUntilNextToken() and getMinTimeUntilToken() to token tracker
- Return waitMs from hybrid strategy when all accounts are token-blocked

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-23 14:29:24 +05:30
Badri Narayanan S
7aa1508b27 ignore count requests 2026-01-23 14:10:00 +05:30
Wha1eChai
07e413d1ec security: redact sensitive config values and protect update endpoints 2026-01-23 16:12:31 +08:00
Badri Narayanan S
9efe5cd75d fix(webui): add missing config fields to API handler
The POST /api/config endpoint was missing validation for several
Advanced Server Settings fields, causing the sliders to fail silently.
Added support for: rateLimitDedupWindowMs, maxConsecutiveFailures,
extendedCooldownMs, capacityRetryDelayMs, maxCapacityRetries.

Fixes #181

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-23 12:13:03 +05:30
jgor20
7ed9305b5b fix: remove unused weight from quota config
The quota scoring weight is managed in HybridStrategy's DEFAULT_WEIGHTS,
not in the config.quota block. Removed to avoid confusion.
2026-01-21 20:52:14 +00:00
jgor20
2f5babba99 feat(strategy): add quota-awareness to hybrid account selection
The hybrid strategy now considers account quota levels when selecting
accounts, preventing any single account from being drained to 0%.

- Add QuotaTracker class to track per-account quota levels
- Exclude accounts with critical quota (<5%) from selection
- Add quota component to scoring formula (weight: 3)
- Fall back to critical accounts when no alternatives exist
- Add 18 new tests for quota-aware selection

Scoring formula: Health×2 + Tokens×5 + Quota×3 + LRU×0.1

An attempt at resolving  badrisnarayanan/antigravity-claude-proxy#171
2026-01-21 11:15:38 +00:00
jgor20
e51e3ff56a feat(config): add configurable max accounts limit (#156)
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
2026-01-21 04:34:57 +08:00
Badri Narayanan S
11f135ef32 fix: simplify 403/404 endpoint fallback log messages
Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-20 23:41:17 +05:30
Badri Narayanan S
8d8f170f18 fix: add explicit logging for 403/404 endpoint fallback
Adds logging when 403/404 errors trigger endpoint fallback (daily → prod).
The retry behavior was already working but silently - now it's visible.
Matches opencode-antigravity-auth error handling behavior.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-20 23:33:44 +05:30
Badri Narayanan S
c8fbf37be9 fix: replace pickNext() with selectAccount() in /v1/models endpoint
Fixes regression where /v1/models returned 500 error because
pickNext() method was removed in v2.2.x refactor.

Fixes #164

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-20 21:03:03 +05:30
Badri Narayanan S
b0c3a61130 fix: use allowedTiers only for onboarding (not paidTier)
paidTier values like g1-pro-tier and g1-ultra-tier are rejected by
the onboardUser API with 400 INVALID_ARGUMENT. This matches the
opencode-antigravity-auth reference which only uses allowedTiers.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-19 20:19:40 +05:30
Badri Narayanan S
2175118f9f feat: align project discovery with opencode-antigravity-auth reference
- Store project IDs in composite refresh token format (refreshToken|projectId|managedProjectId)
- Add parseRefreshParts() and formatRefreshParts() for token handling
- Extract and persist subscription tier during project discovery
- Fetch subscription in blocking mode when missing from cached accounts
- Fix conditional duetProject setting to match reference implementation
- Export parseTierId() for reuse across modules

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-19 14:21:30 +05:30
Badri Narayanan S
9311c6fdf7 Merge pull request #151 from pedrofariasx/fix/windows-oauth-url
fix: Escape OAuth URL parameters for Windows CLI
2026-01-19 11:43:29 +05:30
Pedro Farias
a8ca1b79f3 fix: escape ampersands in OAuth URL on Windows 2026-01-19 02:26:55 -03:00
Badri Narayanan S
c8c7a5a8aa refactor: move STRATEGY_LABELS to constants.js and make banner dynamic
Consolidate strategy configuration by moving STRATEGY_LABELS from
strategies/index.js to constants.js. Update startup banner to
dynamically display strategy options from SELECTION_STRATEGIES.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-18 12:59:33 +05:30
Badri Narayanan S
5ae19a5b72 feat: add configurable account selection strategies
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>
2026-01-18 03:48:43 +05:30
Badri Narayanan S
973234372b chore: remove unused code and suppress noisy Claude Code logs
- Delete unused files: retry.js, app-init.js, model-manager.js
- Remove duplicate error helpers from helpers.js (exist in errors.js)
- Remove unused exports from signature-cache.js, logger.js
- Remove unused frontend code: ErrorHandler methods, validators, canDelete, destroy
- Make internal functions private in thinking-utils.js
- Remove commented-out code from constants.js
- Remove deprecated .glass-panel CSS class
- Add silent handler for Claude Code event logging (/api/event_logging/batch)
- Suppress logging for /v1/messages/count_tokens (501 responses)
- Fix catch-all to use originalUrl (wildcard strips req.path)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-18 01:36:24 +05:30
Badri Narayanan S
c52d32572a Merge pull request #141 from jgor20/fix/spawn-browser-launch
refactor(cli): use spawn instead of exec for browser launch
2026-01-18 01:01:59 +05:30
Pedro Farias
6a6c4829ca feat: server reliability and observability improvements 2026-01-17 13:21:15 -03:00
jgor20
cbade78e86 Merge branch 'badrisnarayanan:main' into fix/spawn-browser-launch 2026-01-17 13:31:21 +00:00
jgor20
71a808ed31 refactor(cli): use spawn instead of exec for browser launch
Replace shell command execution with spawn for cleaner process handling.

Uses array arguments instead of string interpolation.
2026-01-17 13:13:49 +00:00
Badri Narayanan S
ed68f4b21e fix: enable strict tool parameter validation for Claude models
Set functionCallingConfig.mode = 'VALIDATED' when using Claude models
to ensure strict parameter validation, matching opencode-antigravity-auth.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-17 14:47:48 +05:30
Marvin
480b4a0bc1 fix: preserve whitespace-only chunks in SSE stream (#139)
* fix: preserve whitespace-only chunks in SSE stream

Fixes issue #138 where Claude models would swallow spaces between words because whitespace-only chunks (e.g., " ") were being filtered out as empty.

Changes:
- Modified sse-streamer.js to only skip truly empty strings (""), preserving strings that contain only whitespace.
- Added regression test case in tests/test-streaming-whitespace.cjs to verify whitespace preservation.

* test: add streaming whitespace regression test to main suite

---------

Co-authored-by: walczak <walczak@ial.ruhr>
2026-01-17 12:16:28 +05:30
Badri Narayanan S
2516e90d06 Revert "fix: check allowedTiers when paidTier is free for tier detection"
This reverts commit 11a1879fc7.
2026-01-15 21:26:08 +05:30
Badri Narayanan S
11a1879fc7 fix: check allowedTiers when paidTier is free for tier detection
Some accounts have paidTier.id = "free-tier" but allowedTiers includes
"standard-tier", meaning they can use Pro-level quotas even though their
Google One subscription doesn't grant Antigravity benefits.

New priority:
1. paidTier - if Pro/Ultra, use immediately
2. allowedTiers - if paidTier is free, check for higher tiers
3. currentTier - fallback if still unknown
4. allowedTiers default - final fallback

This fixes accounts that show as "free" but actually have Pro access
through programs other than Google One AI.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-15 21:23:19 +05:30
Badri Narayanan S
9ffb83ab74 fix: improve onboarding flow for non-free tier accounts
- Use raw API tier IDs (e.g., 'free-tier', 'g1-pro-tier') consistently
- Pass DEFAULT_PROJECT_ID for non-free tiers during onboarding
- Fix free tier detection to use .includes('free') instead of exact match
- Upgrade onboarding error logs from debug to warn for visibility
- Add debug logging for onboarding request parameters

Fixes onboarding failures for Pro/Ultra accounts that were previously
failing because the API requires a project ID for paid tier onboarding.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-15 20:25:10 +05:30
Badri Narayanan S
9809337190 fix: improve subscription tier detection with paidTier priority and verbose logging
- Use parseTierId() consistently for all tier sources (paidTier, currentTier, allowedTiers)
- Add tierSource tracking to identify which field tier was detected from
- Add verbose debug logging to show all tier-related fields from loadCodeAssist API
- Fix onboarding to prioritize paidTier > currentTier > allowedTiers (consistent with model-api.js)

This helps diagnose issues where Pro/Ultra accounts are incorrectly detected as free.
Fixes #128

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-15 20:08:30 +05:30
Badri Narayanan S
2a0c110f9b fix: try model fallback before throwing RESOURCE_EXHAUSTED error
When all accounts are rate-limited for > 2 minutes, now attempts
model fallback (if enabled) before throwing the error. This allows
quota-exhausted accounts to gracefully fall back to alternate models.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-15 16:41:02 +05:30
Badri Narayanan S
77363c679e fix: accurate quota reporting with project ID and improved rate limit handling
- Pass project ID to fetchAvailableModels for accurate per-project quota
- Treat missing remainingFraction with resetTime as 0% (exhausted)
- Fix double-escaped regex in rate-limit-parser.js (\\d -> \d)
- Use ANTIGRAVITY_HEADERS for loadCodeAssist consistency
- Store actual reset time from API instead of capping at default
- Add getRateLimitInfo() for detailed rate limit state
- Handle disabled accounts in rate limit checks

Fixes issue where free tier accounts showed 100% quota but were actually exhausted.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-15 16:18:13 +05:30
Badri Narayanan S
a20cba90ee Merge pull request #125 from IrvanFza/feat/webui-notif
docs: update startup message to mention WebUI
2026-01-15 12:46:42 +05:30
Irvan Fauziansyah
915ee88e80 docs: update startup message to mention WebUI
- Changed "Server running at" to "Server and WebUI running at"
- Clarifies that the web interface is available at the same port
2026-01-15 14:10:27 +07:00