- Add showHelp() with usage, options, checks, examples, exit codes
- Update handleDoctorCommand to accept args array instead of boolean
- Update ccs.ts to pass restArgs to doctor command
- Add doctor to CLAUDE.md Help Location Reference table
Previously getReadyProfiles() scanned all *.settings.json files,
including orphan files (ghcp, kiro) not in config.yaml.
Now reads from config.yaml:
- profiles section (excluding 'default')
- cliproxy.providers section
Fixes doctor showing 11 profiles instead of configured 9.
Replace hardcoded ['glm', 'kimi'] list with DelegationValidator.getReadyProfiles()
to detect all configured *.settings.json profiles including mm, or1, g7, etc.
- Set CLIPROXY_MAX_STABLE_VERSION to 9.9.999-0 (effectively no cap)
- v89+ are all stable, no longer show experimental warning
- Only v81-88 remain marked as faulty with known bugs
- Simplified lifecycle.ts to remove redundant experimental warning
- Fix path traversal in trace() via safe dir validation
- Add RFC 7230 hop-by-hop header filtering
- Fix isRecord() to exclude arrays
- Add req.destroy() on oversized body rejection
- Add missing ANTHROPIC_BASE_URL warning for Codex
- Use cwd() fallback when HOME undefined
- Add 4 edge case unit tests
* fix(ci): add persistent logging and remove turn/diff limits for AI review (#298)
- Remove --max-turns limit (unlimited exploration)
- Remove head -8000 diff limit (full diff)
- Add persistent logging to /opt/actions-runner/logs/ai-review/
- Save prompt, stdout, stderr, timing, metadata as separate files
- Add structured metadata.json with run details
- Separate stdout/stderr capture for better debugging
- Include debug info in failure comments (exit code, duration, log path)
- Retry without tool restrictions if first attempt fails
* fix(cliproxy): correct faulty version range to v81-85 and set v89 as stable (#302)
PR #289 incorrectly marked all v81+ as faulty. v89 confirmed stable.
- CLIPROXY_MAX_STABLE_VERSION: 6.6.80-0 → 6.6.89-0
- CLIPROXY_FAULTY_RANGE max: 6.6.999-0 → 6.6.85-0
* feat(ci): add AI code review workflow with Claude via CLIProxyAPI
- Self-hosted runner calls CLIProxyAPI at localhost:8317
- Triggers on PR open/update and /review comment
- Uses gemini-claude-opus-4-5-thinking for deep reviews
- Posts summary + inline comments via gh CLI
- Handles self-PR fallback to COMMENT mode
* chore(release): 7.15.0-dev.1 [skip ci]
* refactor(ci): use GitHub App for reviewer identity + new review format
- Posts as ccs-agy-reviewer[bot] via GitHub App token
- New review format: structured markdown with verdict, summary, issues table
- Single PR comment instead of inline comments
- Concise, focused on PR changes only
* chore(release): 7.15.0-dev.2 [skip ci]
* refactor(ci): switch to Claude Code CLI for reviews
- Use claude -p instead of custom TypeScript script
- Auto-install if not present on runner
- CLIProxyAPI via env vars (ANTHROPIC_BASE_URL, ANTHROPIC_MODEL)
- Allowed tools: Read, Glob, Grep
- Max 3 turns for file exploration
* chore(release): 7.15.0-dev.3 [skip ci]
* chore(release): 7.15.0-dev.4 [skip ci]
* feat(ci): add workflow_dispatch for manual review trigger
* chore(release): 7.15.0-dev.5 [skip ci]
* refactor(cliproxy): add faulty version range infrastructure (#289)
* refactor(cliproxy): add faulty version range infrastructure
- Add CLIPROXY_FAULTY_RANGE constant for marking known buggy versions
- Add isVersionFaulty() helper to version-checker.ts
- Update lifecycle.ts to warn users on faulty versions with upgrade suggestion
- Update health checks to distinguish faulty vs experimental versions
- Update stats routes to include faultyRange in API response
- Skip faulty versions when calculating latestStable
Infrastructure ready for future version promotions. Currently:
- v80 and below: stable
- v81+: marked as faulty (context cancellation bugs)
* chore: trigger review
* chore: re-trigger review
* chore: test PR trigger
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
- 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
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
- 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'
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/
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
- Add isAboveMaxStable() helper for version stability checks
- Add null/empty guard in clampToMaxStable() function
- Warn users on unstable v81+ without forcing downgrade
- Add context note showing latest version when it's unstable
- Clamp fallback version on GitHub API failure
- Fixed version regex to accept -N suffix (e.g., 6.6.80-0)
- Added .trim() to version input for whitespace handling
- Added Windows reserved device names (CON, PRN, AUX, NUL, COM1-9, LPT1-9) validation
- Updated binary-service, variant-service, and validation-service with checks
Before launching Claude CLI for Antigravity, check if current account
has remaining quota. If exhausted, auto-switch to alternative account
with available quota. Prevents session failures mid-use.
Add `ccs cliproxy doctor` command that:
- Fetches quota for all Antigravity accounts in parallel
- Shows per-account quota status with visual bars
- Detects shared GCP projects (critical failover limitation)
- Warns when accounts share same quota pool
Part of #252 antigravity failover enhancement.
Add functions for multi-account quota fetching and auto-failover support:
- fetchAllProviderQuotas: Fetch quota for all accounts with project grouping
- findAvailableAccount: Find account with remaining quota for auto-switch
- readProjectIdFromAuthFile: Quick project ID read without API call
Detects accounts sharing same GCP project (failover won't help).
Part of #252 antigravity failover enhancement.
When Gemini OAuth tokens expire, CLIProxyAPI attempts synchronous
refresh during API calls. If this fails or times out, the socket
connection closes abruptly causing Claude CLI's undici to report
UND_ERR_SOCKET errors.
This fix adds proactive token validation before spawning Claude CLI:
- New gemini-token-refresh.ts module handles Gemini OAuth refresh
- ensureTokenValid() in token-manager.ts checks expiry with 5min lead
- cliproxy-executor.ts calls ensureTokenValid() after auth check
The token is now refreshed BEFORE Claude CLI connects, eliminating
the race condition that caused socket errors.
Fixes#256
When OAuth accounts have empty email fields (Kiro/GHCP), the accountId
was defaulting to 'default', causing multiple accounts to overwrite
each other. Now extracts unique ID from filename pattern:
- kiro-github-<PROFILE_ID>.json → github-<PROFILE_ID>
- ghcp-amazon-<PROFILE_ID>.json → amazon-<PROFILE_ID>
Fixes#258
- Add management_key field to CliproxyServerConfig for separate management API auth
- Update proxy-target-resolver with buildManagementHeaders() for /v0/management/* endpoints
- Update stats-fetcher and remote-auth-fetcher to use management headers
- Add management_key input field to dashboard remote proxy settings
- Disable quota UI in remote mode (tokens on remote server)
- Fix preset application to use dynamic API key from config instead of hardcoded placeholder