Commit Graph
1252 Commits
Author SHA1 Message Date
kaitranntt b2ba402d0f feat(cliproxy): auto-sync on profile create 2026-01-28 11:57:22 -05:00
kaitranntt 28b0e89b34 feat(cliproxy): enable auto_sync by default 2026-01-28 11:57:22 -05:00
kaitranntt 9924b2fb25 fix(cliproxy): address edge cases in sync module
- Reset isSyncing flag in stopAutoSyncWatcher (prevents stale state)
- Validate empty profile names in mapProfileToClaudeKey
- Add whitespace validation in API routes (POST/DELETE /aliases)
- Add Number.isInteger check for port validation
- Wrap response.json() in try-catch for React hooks (handles non-JSON 502)
2026-01-28 11:57:22 -05:00
kaitranntt fc23afdfc7 feat(cliproxy): add auto_sync config option
- export sync module from cliproxy barrel
- add auto_sync field to CLIProxyConfig interface
2026-01-28 11:57:22 -05:00
kaitranntt 56500fee98 feat(cliproxy): add sync API routes
- add /api/cliproxy/sync endpoints for local sync
- add /api/cliproxy/sync/aliases for model alias management
- add /api/cliproxy/sync/auto-sync for watcher toggle
- separate try-catch for config save vs watcher restart
2026-01-28 11:57:22 -05:00
kaitranntt cb6c21216d feat(cliproxy): add sync and alias CLI commands
- add `ccs cliproxy sync` command for manual sync
- add `ccs cliproxy alias` command for model alias management
- support --dry-run and --verbose flags
- integrate with cliproxy subcommand router
2026-01-28 11:57:22 -05:00
kaitranntt 9de2682062 feat(cliproxy): add local config sync module
- add profile mapper to transform CCS profiles to ClaudeKey format
- add model alias configuration with defaults for glm/kimi/qwen
- add local config sync to write claude-api-key section
- add auto-sync watcher with debouncing for profile changes
- include null config handling and temp file cleanup
2026-01-28 11:57:22 -05:00
kaitranntt 4cc89eaf87 feat(cliproxy): add Management API client for CLIProxy
- add types for ClaudeKey, ClaudeModel, HealthStatus
- add HTTP client for Management API endpoints
- support GET/PUT/PATCH/DELETE operations
2026-01-28 11:57:22 -05:00
kaitranntt c713d48d08 refactor(oauth): derive auth-code providers from OAUTH_FLOW_TYPES (DRY)
- Update checkAuthCodePorts() to filter from CLIPROXY_PROFILES

- Update header comment to list all OAuth ports including Claude

- Addresses PR #384 review round 3
2026-01-27 22:25:31 -05:00
kaitranntt 9fd9395588 refactor(cliproxy): use CLIPROXY_PROFILES for provider arrays (DRY)
- Replace hardcoded arrays in token-manager.ts, token-expiry-checker.ts

- Replace hardcoded arrays in account-manager.ts, oauth-port-diagnostics.ts

- Addresses PR #384 code review feedback
2026-01-27 22:04:46 -05:00
kaitranntt 8017ce8f86 fix(cliproxy): use correct --claude-login flag for Claude OAuth
- CLIProxyAPI expects --claude-login, not --anthropic-login

- Fixes 'CLIProxy auth exited with code 2' error

Closes #382
2026-01-27 21:39:19 -05:00
kaitranntt 4a2abc74ca fix: add claude provider to statsProviderMap, UI types, and provider arrays
Fixes remaining edge cases from #382:
- Add anthropic/claude mapping to statsProviderMap in cliproxy-auth-routes
- Add 'claude' case to provider-refreshers switch statement
- Add 'claude' to 4 UI type definitions in api-client.ts
- Add 'claude' to cliproxy-dialog providers array and options
- Add 'claude' to use-cliproxy-auth-flow VALID_PROVIDERS
- Fix wizard index.tsx type cast to include all 8 providers
2026-01-27 21:02:34 -05:00
kaitranntt 9cd9c423e9 fix: replace hardcoded provider validation arrays with CLIPROXY_PROFILES import
Closes #382

Replace duplicate hardcoded provider validation arrays across three route files
with a single import from CLIPROXY_PROFILES constant. This DRY fix eliminates
code duplication and ensures provider validation is consistent across all routes.

Files updated:
- account-routes.ts
- cliproxy-auth-routes.ts
- cliproxy-stats-routes.ts

Reduces code by 21 lines while improving maintainability.
2026-01-27 20:50:24 -05:00
kaitranntt 2091a90b77 fix(cliproxy): address PR review feedback
- Remove claude from PLUS_ONLY_PROVIDERS (Claude works with normal CLIProxy too)
- Fix color inconsistency: use #D97757 to match SVG brand color
- Add iflow to checkAuthCodePorts (pre-existing issue, fixed opportunistically)
2026-01-27 20:24:01 -05:00
kaitranntt b385ab131d refactor(cliproxy): reorder providers - Antigravity first, then Claude 2026-01-27 20:17:10 -05:00
kaitranntt d2129957d7 fix(cliproxy): add Claude to all provider lists for sidebar display
Claude was missing from:
- getAllAuthStatus() providers array in token-manager.ts
- PROVIDER_ASSETS, PROVIDER_COLORS, PROVIDER_NAMES in provider-config.ts
- PROVIDERS array in setup wizard constants.ts
- PLUS_ONLY_PROVIDERS in proxy settings
2026-01-27 20:14:22 -05:00
kaitranntt 28d8bd84a5 feat(cliproxy): add Claude (Anthropic) OAuth provider support
Add Claude as a first-class OAuth provider in CCS CLI and dashboard.
Backend support already exists in CLIProxyAPIPlus (port 54545).

Changes:
- Add 'claude' to CLIProxyProvider type and profile detector
- Add Claude OAuth config (port 54545, --anthropic-login flag)
- Add Claude to oauth-port-diagnostics flow types
- Add Claude token discovery prefixes (claude-, anthropic-)
- Add Claude model catalog (Opus 4.5, Sonnet 4.5/4, Haiku 4.5)
- Add Claude logo and provider display name
- Update variant config types and adapters

Closes #380
2026-01-27 15:43:21 -05:00
Kai (Tam Nhu) TranandGitHub d6e187a04d Merge pull request #375 from shunkakinoki/feat/skip-oauth-for-remote-proxy
feat: skip local OAuth when using remote proxy with auth token
2026-01-26 16:26:26 -05:00
kaitrannttandShun Kakinoki 21e819b590 fix(cliproxy): improve skip-local-auth edge case handling
- Validate authToken with trim() to reject whitespace-only values
- Show broken model warning for both remote and local modes
- Add context-aware messaging for remote proxy users
- Add comprehensive test coverage for authToken edge cases:
  - Whitespace-only strings
  - Null values
  - Tabs/newlines
  - Tokens with leading/trailing whitespace

Co-authored-by: Shun Kakinoki <shunkakinoki@gmail.com>
2026-01-26 16:16:23 -05:00
kaitranntt 0216341b2c fix(websearch): stop polluting global ~/.claude/settings.json with hooks
Remove global hook registration from installWebSearchHook() - now only
copies hook file to ~/.ccs/hooks/. Hook registration handled by
ensureProfileHooks() which writes to per-profile settings.

Changes:
- hook-installer.ts: Remove ensureHookConfig() call
- ccs.ts: Remove redundant installWebSearchHook() call
- hook-config.ts: Add getClaudeSettingsPath() for test isolation
2026-01-26 14:51:51 -05:00
kaitranntt fb77d72a30 fix(cliproxy): pin version to 6.7.25, add disable-cooling
- Update fallbackVersion: 6.7.8 → 6.7.25 (original)
- Update fallbackVersion: 6.7.8-0 → 6.7.25-0 (plus)
- Add disable-cooling: true to generated config
- Bump CLIPROXY_CONFIG_VERSION to 5 for regeneration
2026-01-26 14:12:14 -05:00
Shun Kakinoki 1f5d11930e feat: skip local OAuth when using remote proxy with auth token
When --proxy-host and --proxy-auth-token are provided, the remote proxy
handles authentication via its own OAuth sessions. This change skips:

- Local OAuth check/trigger
- Preflight quota check (managed by remote server)
- Model configuration prompts (configured on remote server)
- Broken model warnings (model selection is remote)

This enables headless CI/CD usage without requiring pre-cached
CCS_SESSIONS when a remote proxy with auth token is available.
2026-01-26 16:25:24 +09:00
kaitranntt e98a92fded fix: address PR #373 review feedback
- postuninstall.js: add file logging for debugging on error
- profile-hook-injector.ts: use 'wx' flag for atomic marker creation
- profile-hook-injector.ts: include parse error message in debug log
- install-command.ts: use actual counts for consistent semantics
- Windows tests: align Section 7 with per-profile hook architecture
2026-01-25 22:02:25 -05:00
Kai (Tam Nhu) TranandGitHub 2f66f74ff9 Merge pull request #371 from kaitranntt/kai/fix/uninstall-hooks-cleanup
fix: uninstall hooks cleanup + test isolation
2026-01-25 21:53:00 -05:00
kaitranntt cd7a1121d4 fix: address PR review feedback
- ClaudeSymlinkManager.uninstall() now returns count for accurate reporting
- install-command.ts uses return value instead of always incrementing
- claude-dir-installer.ts uses getCcsHome() directly instead of string manipulation
- Add TODO comments to tests explaining --install is a no-op
2026-01-25 21:50:25 -05:00
kaitranntt 6a2c82917d fix(isolation): add getCcsDir/getCcsHome to more files
Fix test isolation in symlink managers and checkers to prevent tests
from touching user's real ~/.ccs/ and ~/.claude/ directories.

Files fixed:
- src/api/services/profile-writer.ts - use getCcsDir()
- src/management/checks/symlink-check.ts - use functions instead of
  module-level constants
- src/utils/claude-dir-installer.ts - use getCcsDir() for CCS paths
- src/utils/claude-symlink-manager.ts - use getCcsHome()/getCcsDir()
2026-01-25 21:42:17 -05:00
kaitranntt 9b61f5318e fix(isolation): use getCcsDir() for test isolation
Replace os.homedir() with getCcsDir() in 11 source files to ensure
tests don't touch the user's real ~/.ccs/ directory. The getCcsDir()
function from config-manager.ts respects CCS_HOME env var for
test isolation.

Files fixed:
- src/auth/profile-detector.ts
- src/auth/profile-registry.ts
- src/delegation/headless-executor.ts
- src/delegation/session-manager.ts
- src/glmt/glmt-transformer.ts
- src/management/checks/config-check.ts
- src/management/checks/profile-check.ts
- src/management/checks/system-check.ts
- src/management/instance-manager.ts
- src/management/shared-manager.ts
- src/utils/update-checker.ts
2026-01-25 21:38:27 -05:00
kaitranntt a8c46cc8ed fix(config): persist setup_completed flag to YAML file
Critical fix: setup_completed was set in memory but never written to disk.

- Add setup_completed to generateYamlWithComments() for YAML serialization
- Add setup_completed to mergeWithDefaults() to preserve during config merge

Without these changes, the flag was lost on save/reload, causing first-time
notice to reappear.

Addresses critical code review feedback on PR #372.
2026-01-25 21:33:29 -05:00
kaitranntt fca8dbd6cf feat(websearch): inject hooks on profile creation
Add hook injection at profile creation time (not just runtime):
- profile-writer.ts: inject on API profile create/update
- variant-settings.ts: inject on CLIProxy variant create

Hooks now present immediately after profile creation.
2026-01-25 21:31:20 -05:00
kaitranntt 596a9c6843 test(setup): add unit tests for setup_completed flag detection
- Add 3 test cases for setup_completed flag:
  - Detect flag when present and true
  - Treat missing flag as first-time eligible
  - Treat false flag as first-time eligible
- Update JSDoc to document detection priority order

Addresses code review feedback on PR #372.
2026-01-25 21:26:23 -05:00
kaitranntt 85e41a56e9 fix(setup): persist setup_completed flag to prevent repeated first-time notice
After running ccs setup with local proxy mode, the CLI was still showing
the first-time install notice because isFirstTimeInstall() only checked
for user-created content (profiles, accounts, variants, etc.). When user
chose "Local" mode and skipped API profiles, config had empty objects,
causing all checks to return false.

Added setup_completed flag to UnifiedConfig interface and set it to true
when setup wizard completes. isFirstTimeInstall() now checks this flag
first.
2026-01-25 21:21:02 -05:00
kaitranntt 21b18d0c4e refactor(websearch): address PR review recommendations
- Add comment in postuninstall.js explaining intentional os.homedir()
- Fix comment in install-command.ts (doesn't touch global settings.json)
- Consolidate duplicate getCcsHooksDir() - export from hook-config.ts
- Add debug logging to silent catch blocks in profile-hook-injector.ts
2026-01-25 21:13:55 -05:00
kaitranntt b33674b3b2 fix(websearch): use getCcsDir() for test isolation
Ensure all hook-related modules use getCcsDir() from environment.ts
for consistent test isolation. Prevents tests from touching the user's
real ~/.ccs/ directory during test runs.

Changes:
- hook-config.ts: Use getCcsDir() for hookConfigPath
- hook-installer.ts: Use getCcsDir() for HOOK_SOURCE_PATH
- profile-hook-injector.ts: Use getCcsDir() for hook sources
- CLAUDE.md: Add test isolation rules
2026-01-25 21:03:01 -05:00
kaitranntt ba1fb7eeb3 refactor(uninstall): stop modifying global settings.json
- remove removeHookConfig() call from uninstallWebSearchHook()

- add removeMigrationMarker() cleanup

- update postuninstall.js to only clean CCS files

- global ~/.claude/settings.json is never touched
2026-01-25 20:26:27 -05:00
kaitranntt 0099ab5a1c feat(cli): inject hooks into profile settings on launch
- call ensureProfileHooks() before CLIProxy execution

- call ensureProfileHooks() before Copilot execution

- call ensureProfileHooks() before Settings-based execution

- account-based profiles skip (use native WebSearch)
2026-01-25 20:25:01 -05:00
kaitranntt 242ab76453 feat(websearch): add per-profile hook injection module
- ensureProfileHooks() injects hooks into profile settings

- migrateGlobalHook() one-time migration from global settings

- removeMigrationMarker() cleanup for uninstall

- export from barrel files for module access
2026-01-25 20:24:47 -05:00
kaitranntt c44a5c221f feat(cli): implement --uninstall handler
- add handleUninstallCommand() with proper cleanup flow

- remove WebSearch hook (file + settings.json)

- remove symlinks from ~/.claude/

- display summary with removal count

- preserve ~/.ccs/ directory
2026-01-25 20:05:31 -05:00
kaitranntt fc4d987d20 feat(websearch): call removeHookConfig on uninstall
- uninstallWebSearchHook() now calls removeHookConfig()

- ensures settings.json cleanup when hook file is removed
2026-01-25 20:04:04 -05:00
kaitranntt 9159aa52cb feat(websearch): add removeHookConfig function
- add removeHookConfig() to remove CCS hook from settings.json

- only removes hooks matching CCS pattern (.ccs/hooks/websearch-transformer)

- preserves user-defined WebSearch hooks

- cleans up empty hooks object after removal

- export from barrel file

Closes #317
2026-01-25 20:03:52 -05:00
kaitranntt e3920e0776 fix(quota): return exhausted models with resetTime from API
- treat models with resetTime but null/missing remainingFraction as 0%
- matches CLIProxy Management Center behavior
- enables accurate Claude reset time display when quota exhausted
- mark primary models at 0% as exhausted for red styling
2026-01-25 17:34:30 -05:00
kaitranntt 27e8813cae fix(quota): fetch quota for paused accounts + simplify exhausted display
- Remove early return for paused accounts in quota fetcher
- Check both auth/ and auth-paused/ directories when reading auth data
- Allows users to see quota status of paused accounts to know when to unpause
- Remove "Exhausted" text in tooltip, just show 0% in red (saves width)
2026-01-25 17:12:45 -05:00
kaitranntt d1b579ad1b fix(api): add race condition prevention and input validation for account control
- add mutex pattern with providerLocks Map for solo mode

- convert soloAccount to async function

- extract VALID_PROVIDERS constant and isValidProvider helper (DRY)

- allow empty arrays in bulk endpoints (return early success)

- add accountIds string validation (non-empty strings only)
2026-01-24 12:22:49 -05:00
kaitranntt 2a0efbd954 fix(cliproxy): propagate backend parameter to version check functions
Root cause: fetchLatestCliproxyVersion() and checkCliproxyUpdate()
ignored the caller's backend selection, always re-computing from config.
This caused --update to report wrong version when config wasn't synced.

Changes:
- Add optional backend param to fetchLatestCliproxyVersion()
- Add optional backend param to checkCliproxyUpdate()
- Pass effectiveBackend in binary-service.ts calls
- Pass backend in cliproxy-stats-routes.ts web endpoints

Fixes inconsistent version reporting when switching between
CLIProxyAPI (original) and CLIProxyAPIPlus backends.
2026-01-23 22:56:27 -05:00
kaitrannttandClaude bd343f3f02 fix(glmt): respect user-configured model instead of hardcoding glm-4.6
Root cause: execClaudeWithProxy() was ignoring ANTHROPIC_MODEL from
user settings and always using hardcoded 'glm-4.6'.

Changes:
- Read model from user's settings file in GLMT proxy flow
- Update default model to glm-4.7 in base configs (matches presets)
- Update fallback models in transformer/response-builder

Closes #358

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-23 17:08:08 -05:00
kaitranntt f0c845c32e fix(cliproxy): use backend-aware labels in error messages and API
- Use checkCliproxyUpdate() in checkLatestVersion() for correct repo
- Dynamic error messages based on backend in service-manager
- Dynamic error messages based on backend in cliproxy-executor
- Generic "CLIProxy" message in oauth-process (no backend context)
2026-01-23 15:37:40 -05:00
kaitranntt 2794a548a5 fix(cliproxy): complete backend switching with proper binary extraction
- Add backend field to BinaryManagerConfig type for installer context
- Thread backend parameter through tar/zip extractors to use correct names
- Delete existing binary before install to prevent mismatched binaries
- Track backend in session metadata for debugging/monitoring
- Validate and preserve backend field in config mergeWithDefaults
- Pass backend to registerSession for session tracking

The core issue was extractors calling getExecutableName() without the
backend parameter, causing it to default to 'plus' regardless of user
selection. This resulted in wrong binaries being extracted/renamed.
2026-01-23 15:17:32 -05:00
kaitranntt 0a1cbcc612 fix(cliproxy): use backend-specific GitHub repos for version fetching
Root cause: fetchLatestVersion and fetchAllVersions were hardcoded to
CLIProxyAPIPlus repo, ignoring backend selection.

Changes:
- Add getGitHubApiUrls(backend) helper to types.ts
- Make fetchLatestVersion and fetchAllVersions backend-aware
- Make version list cache backend-specific (bin/{backend}/.version-list-cache.json)
- Update /api/cliproxy/versions route to use configured backend
- Allow version management even when proxy not running (ProxyStatusWidget)
- Show settings button in all states for easier access
2026-01-23 14:55:51 -05:00
kaitranntt a41fd2a093 fix(cliproxy): make version cache backend-specific for proper switching
- Add backend parameter to version cache functions (read/write/path)
- Store cache at bin/{backend}/.version-cache.json instead of shared location
- Pass backend through checkForUpdates() and BinaryManager
- Add refetchType: 'all' to force immediate query refetch on backend change
- Add cliproxy-server-config query invalidation for consistency
2026-01-23 14:40:40 -05:00
kaitranntt 88560c7119 fix(ui): sync backend state across all CLIProxy UI components
- Add useUpdateBackend mutation hook that invalidates related queries
- Reduce update-check stale time from 1hr to 5min + enable refetchOnWindowFocus
- Settings proxy page now uses mutation hook for proper query invalidation
- Make all CLIProxy labels dynamic based on backendLabel from API:
  - cliproxy-header.tsx: page title
  - app-sidebar.tsx: nav item label
  - cliproxy-stats-overview.tsx: both offline and running descriptions
  - model-preferences-grid.tsx: card description
  - settings proxy section: descriptions for local/remote modes
- Fix API route to use DEFAULT_BACKEND constant instead of hardcoded 'plus'

Ensures backend switching in Settings immediately reflects in all CLIProxy pages.
2026-01-23 13:46:47 -05:00
kaitranntt dad4349994 fix(ui): display dynamic backend label in dashboard
- Add backend/backendLabel fields to CliproxyUpdateCheckResult
- Update proxy-status-widget to show backendLabel from API
- Update cliproxy page header to use backendLabel

Dashboard now shows "CLIProxy" or "CLIProxy Plus" based on configured
backend in config.yaml instead of hardcoded "CLIProxy Plus".
2026-01-23 13:25:24 -05:00