Commit Graph
212 Commits
Author SHA1 Message Date
kaitranntt 22dbfd91c5 refactor(errors): centralize error handling infrastructure
- add errors/ directory with error types, handler, cleanup registry

- extract claude-spawner.ts from auth modules

- update imports across auth, ccs, web-server

Phase 2 & 4: Error handling consolidation
2025-12-19 11:47:43 -05:00
kaitranntt 9346ff2be9 refactor(web-server): extract usage aggregator service
- extract usage-aggregator.ts from usage-routes.ts (883 → 188 lines)

- add services/ directory with barrel export

- separate data aggregation logic from route handlers

Phase 2: Duplicate Extraction
2025-12-19 11:47:30 -05:00
kaitranntt a12c3d800a refactor(web-server): modularize routes into dedicated files
- extract 14 route modules from monolithic routes.ts (2198 → 49 lines)

- add route-helpers.ts for shared utilities

- add index.ts barrel export for clean imports

- health, profile, config, settings, provider, copilot routes

- variant, proxy, cliproxy-auth, cliproxy-stats, websearch, misc routes

Phase 1: Routes Modularization
2025-12-19 11:47:19 -05:00
Kai (Tam Nhu) TranandGitHub af814aeee8 Merge pull request #153 from kaitranntt/kai/fix/cliproxy-port-race
fix(cliproxy): prevent port race condition with unified detection and startup lock
2025-12-19 10:54:11 -05:00
kaitranntt 2d2cd3eca2 feat(recovery): add lazy initialization for bun/pnpm users
Bun and pnpm block postinstall scripts by default for security.
This causes ~/.ccs/ directory to not be created on fresh install.

Added lazy initialization in RecoveryManager that mirrors postinstall.js:
- ensureSharedDirectories() - creates ~/.ccs/shared/ subdirs
- ensureGlmSettings() - creates glm.settings.json with defaults
- ensureGlmtSettings() - creates glmt.settings.json with thinking mode
- ensureKimiSettings() - creates kimi.settings.json with k2-thinking-turbo
- ensureShellCompletions() - installs completion files
- Fixed config.json to include glmt profile, removed deprecated default

Now any ccs command will auto-create full ~/.ccs/ structure on first run.

Fixes: bun add -g @kaitranntt/ccs not creating ~/.ccs/
2025-12-19 10:50:52 -05:00
kaitranntt 96f17e3afb fix(cliproxy): prevent port race condition with unified detection and startup lock
Add proxy-detector.ts for unified detection with multiple fallbacks:
- HTTP health check (most reliable)
- Session lock file check
- Port process detection with HTTP retry (handles Windows PID-XXXXX)

Add startup-lock.ts for file-based mutex:
- 10s timeout with 20 retries at 250ms intervals
- Stale lock detection via PID check
- Cross-platform support

Update cliproxy-executor.ts and service-manager.ts to use new modules.

Fixes race conditions when running simultaneous ccs commands.
2025-12-19 10:50:25 -05:00
kaitranntt 2373100c17 fix(web-server): add comprehensive reserved name validation
- Import isReservedName from centralized reserved-names module
- Add validation to POST /api/profiles endpoint
- Add validation to POST /api/cliproxy/openai-compat endpoint
- Refactor hardcoded arrays to use centralized isReservedName()
- Fixes DRY violation and ensures consistent validation across all endpoints
2025-12-19 09:55:27 -05:00
kaitranntt 7ea64bdb43 fix(cliproxy): prevent variant names matching reserved provider names
Added validation to reject variant names that match reserved CLIProxy
provider names (gemini, codex, agy, qwen, iflow). Also protected reserved
provider settings files from being deleted when deleting variants.

This prevents accidental deletion of default provider configurations when
users create variants with conflicting names.
2025-12-19 09:49:05 -05:00
kaitranntt 598454c931 fix(cliproxy): include BASE_URL and AUTH_TOKEN when applying presets
Presets now always include ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN
when applied to provider settings. This ensures CLIProxy routing works
correctly for Gemini, Codex, and Agy providers.

Also fixes settings save failing for new profiles by changing PUT
/api/settings/:profile to upsert behavior (create if not exists).
2025-12-19 09:44:14 -05:00
kaitranntt 68eab562ce feat(env): add debug logging for global env injection
- log injected global env var names in debug mode (CCS_DEBUG)

- log when telemetry/reporting env vars are applied in CLIProxy
2025-12-19 07:58:19 -05:00
kaitranntt b6b18173cc fix(update-checker): resolve dev channel update and duplicate comments
Fixes tag-agnostic cache issue causing 'ccs update --dev' to require
force. Implements tag-specific caching (dev_version vs latest_version)
to correctly detect updates across channels. Disables duplicate bot
comments on dev releases in .releaserc.cjs.
2025-12-19 04:50:09 -05:00
kaitranntt 03aea4eac2 fix(remote-proxy): fix TypeError and make port optional with protocol defaults
- Fix TypeError: error.code?.toLowerCase - add type guard for non-string error codes
- Make remote proxy port optional - defaults to 443 (HTTPS) or 80 (HTTP)
- Smart URL building - omits port when using protocol default
- UI improvements - show default port hint, allow empty port field
- Better validation - only host is required, port uses smart defaults

Closes #142
2025-12-19 04:23:20 -05:00
kaitranntt a3b172cc43 fix(cliproxy): register session on dashboard start and add port-based stop fallback
Dashboard Stop/Update buttons failed with contradictory errors:
- Stop: "No active CLIProxy session found"
- Update: "CLIProxy was already running"

Root cause: service-manager spawned proxy but never called registerSession(),
so stopProxy() couldn't find the lock file.

Changes:
- service-manager.ts: Add registerSession() after spawn
- session-tracker.ts: Make stopProxy() async with port-based fallback
- routes.ts: Update proxy-stop endpoint to async
- cliproxy-command.ts: Update handleStop() to await async stopProxy()
- port-utils.ts: Fix double-escaped regex for Windows port detection
- session-tracker.test.js: Update tests for async stopProxy()
2025-12-19 03:57:06 -05:00
kaitranntt 903bc10fea fix(profiles): prevent env var inheritance for settings-based profiles
- Load settings file and explicitly inject ANTHROPIC_* env vars
- Prevents stale CLIProxy env vars from overriding settings file values
- Fixes GLM/Kimi requests incorrectly routing through CLIProxyAPI
2025-12-19 02:40:29 -05:00
kaitranntt 8d8d4c248a refactor: rename proxy to cliproxy_server and update API routes 2025-12-19 02:14:49 -05:00
kaitranntt 196422cee1 docs(cliproxy): add remote proxy documentation
- add proxy CLI flags section to help command output

- add proxy environment variables section to help

- add Remote Proxy section to README with config examples

- document CLI flag overrides and priority resolution
2025-12-19 01:18:05 -05:00
kaitranntt 8decdfb515 feat(web-server): add proxy configuration API routes
- GET /api/proxy returns current proxy config

- PUT /api/proxy updates proxy settings in config.yaml

- POST /api/proxy/test tests remote connection

- register routes in web server index
2025-12-19 01:16:10 -05:00
kaitranntt bd1ff2f059 feat(cliproxy): integrate remote proxy mode in executor
- resolve proxy config with CLI flags, ENV vars, and config.yaml

- check remote proxy health before skipping local binary spawn

- implement TTY-aware fallback prompting when remote unreachable

- support --remote-only flag to disable fallback

- use remote or local env vars based on mode
2025-12-19 01:15:33 -05:00
kaitranntt f4a50d006c feat(cliproxy): add getRemoteEnvVars for remote proxy mode
- generate environment variables for remote CLIProxyAPI

- construct ANTHROPIC_BASE_URL from host/port/protocol

- include auth token in Authorization header when provided
2025-12-19 01:15:10 -05:00
kaitranntt 30d564cda6 feat(cliproxy): add remote proxy client for health checks
- checkRemoteProxy() tests remote CLIProxyAPI /health endpoint

- testConnection() validates remote proxy connectivity

- typed error codes: CONNECTION_REFUSED, TIMEOUT, AUTH_FAILED, UNKNOWN

- support for self-signed certificates with allowSelfSigned flag

- add type-level tests for interfaces
2025-12-19 01:13:54 -05:00
kaitranntt 68a93f0500 feat(cliproxy): add proxy config resolver with CLI flag support
- parseProxyFlags() extracts --proxy-host, --proxy-port, --proxy-protocol

- getProxyEnvVars() reads CCS_PROXY_* environment variables

- resolveProxyConfig() merges CLI > ENV > config.yaml > defaults

- hasProxyFlags() detects proxy-related CLI arguments

- add 29 comprehensive unit tests
2025-12-19 01:12:46 -05:00
kaitranntt 197174441f feat(config): add proxy section to unified config loader
- merge proxy config with defaults in loadUnifiedConfig

- preserve user overrides for remote/fallback/local sections
2025-12-19 01:11:49 -05:00
kaitranntt eff2e2d29f feat(config): add proxy configuration types and schema
- add ProxyRemoteConfig, ProxyFallbackConfig, ProxyLocalConfig interfaces

- add ProxyConfig composite type with remote/fallback/local sections

- add ResolvedProxyConfig interface for runtime config

- bump UNIFIED_CONFIG_VERSION to 5

- add DEFAULT_PROXY_CONFIG constant
2025-12-19 01:11:29 -05:00
kaitranntt 45207b4e7f feat(cleanup): add age-based error log cleanup
- add --errors flag to target error-*.log files

- add --days=N for age filtering (default: 7 days)

- show preview of files to delete before confirmation

- keep recent logs for debugging, only delete old ones
2025-12-18 23:45:44 -05:00
kaitranntt d43079b724 feat(ui): add version sync timestamp to ProxyStatusWidget
- Show current CLIProxyAPI version (e.g., v6.5.53)
- Display "Synced Xm ago" with full timestamp on hover
- Extend API response to include checkedAt timestamp
2025-12-18 23:24:15 -05:00
kaitranntt 96762a9f6e feat(ui): show CLIProxyAPI update availability in dashboard
- Add GET /api/cliproxy/update-check endpoint
- Export checkCliproxyUpdate() function from binary-manager
- Add useCliproxyUpdateCheck hook with 1-hour cache
- Update ProxyStatusWidget with amber "Update" badge when available
- Highlight Restart button as "Update" with amber styling when update pending
2025-12-18 23:17:05 -05:00
kaitranntt c9ad0b0779 feat(ui): add Stop and Restart buttons to ProxyStatusWidget
- Add POST /api/cliproxy/proxy-stop API endpoint
- Add proxyStop method in api-client and useStopProxy hook
- Update ProxyStatusWidget with Stop and Restart controls when running
- Restart = stop + delay + start (for applying CLIProxyAPI updates)

Complements the fix in binary-manager.ts which now tells users to stop
proxy before updates can be applied.
2025-12-18 23:03:45 -05:00
kaitranntt 2adc272f27 fix(cliproxy): prevent misleading update message when proxy is running
When CLIProxyAPI is already running as a background process, the update
cannot be applied because the old process is still in memory. Previously,
the CLI would download the new binary and show "Updating CLIProxyAPI..."
even though the running process remained on the old version.

Now checks if proxy is running before attempting update:
- If running: shows update available message with instruction to stop first
- If not running: proceeds with update as before

Fixes #143
2025-12-18 22:52:12 -05:00
kaitranntt 5d343260c7 feat(global-env): add global environment variables injection for third-party profiles
- add global_env config section to unified config types and loader

- inject global env vars at runtime for cliproxy and copilot profiles

- add GET/PUT /api/global-env endpoints for UI management

- add Global Env tab to Settings page with enable toggle and var management

- add GlobalEnvIndicator component showing injected vars in profile editors

- support ?tab=globalenv query param for direct navigation from indicators
2025-12-18 22:38:25 -05:00
kaitranntt 5d4f49e4bb feat(ui): add absolute path copy for error logs
- add absolutePath field to CliproxyErrorLog interface
- inject absolute path in routes.ts from getCliproxyWritablePath()
- update copy button to use absolute path with fallback to filename
- refactor error-logs-monitor to remove demo mode
- add error-log-parser lib for structured log parsing
2025-12-18 21:06:20 -05:00
Kai (Tam Nhu) TranandGitHub 03e9bdc917 Merge pull request #133 from kaitranntt/kai/feat/error-log-viewer
feat(dashboard): add error log viewer for CLIProxy diagnostics
2025-12-18 18:31:16 -05:00
kaitranntt 126cffc6dc refactor: remove deprecated native shell installers
- Remove installers/ directory (install.sh, install.ps1, uninstall.sh, uninstall.ps1)
- Update CloudFlare worker to 301 redirect /install* to npm docs
- Remove detectInstallationMethod() - npm is now only install method
- Simplify update-command.ts to npm-only updates
- Clean up tests to remove direct install references

BREAKING CHANGE: Native shell installers (curl/irm) no longer work.
Use `npm install -g @kaitranntt/ccs` instead.
2025-12-18 16:52:57 -05:00
kaitranntt 8a0ad53082 feat(update): add automatic update check on startup
- check cached update result synchronously on every command
- show warnBox notification if update available
- skip check for version/help/update commands
- refresh cache in background if stale (>24h)
- use proper UI components (warnBox) for notification
2025-12-18 06:12:40 -05:00
Kai (Tam Nhu) TranandGitHub efdf53c83c Merge pull request #138 from kaitranntt/kai/feat/copilot-integration
feat(copilot): add GitHub Copilot integration with CLI, API, and dashboard
2025-12-18 05:41:38 -05:00
kaitranntt ec6face8db fix(copilot): use gpt-4.1 as default model and 127.0.0.1 for local connections
Key changes:
- Changed default model from claude-sonnet-4.5 to gpt-4.1 (free tier compatible)
- Updated all Claude models to minPlan: 'pro' (requires paid Copilot subscription)
- Replaced 'localhost' with '127.0.0.1' for more reliable local connections
  (bypasses DNS resolution and potential IPv6 issues)
- Updated UI presets: replaced Claude Haiku with Raptor Mini in free tier
- Fixed FREE_PRESETS to only include actually free models

This fixes the "model_not_supported" error when using free tier GitHub Copilot
subscription, which doesn't have access to Claude models.
2025-12-18 04:58:49 -05:00
kaitranntt 2c6dfe746b fix(cli): allow ccs copilot as profile by routing only known subcommands
Changed copilot command routing logic to only intercept known subcommands
(auth, status, models, start, stop, enable, disable, help). When user runs
bare 'ccs copilot' without subcommands, it now falls through to profile
detection and executes Claude with the Copilot API backend.

This allows:
- `ccs copilot auth` → command handler (authenticate)
- `ccs copilot status` → command handler (show status)
- `ccs copilot` → profile execution (run Claude with Copilot)
2025-12-18 04:47:44 -05:00
kaitranntt 3a7cb0c4e8 docs(cli): improve copilot help with quick start guide 2025-12-18 04:43:35 -05:00
kaitranntt 671a9e76fb fix(cli): route 'ccs copilot' without subcommand to help 2025-12-18 04:34:33 -05:00
kaitranntt a9788d02ea docs(copilot): add prominent disclaimer for unofficial API
Make the "use at your own risk" warning more transparent:
- UI: Expanded warning banner with clear "Unofficial API" heading
- UI: Added explicit no warranty/no responsibility text
- Config YAML: Updated comments with !! DISCLAIMER !! section
- Types: Updated CopilotConfig JSDoc with full disclaimer

CCS provides no warranty and accepts no responsibility for
consequences of using this reverse-engineered GitHub Copilot API.
2025-12-18 04:20:58 -05:00
kaitranntt a66abba174 feat(cliproxy): implement interactive project selection for OAuth flows
- Add ProjectSelectionHandler to parse and handle CLIProxy project prompts
- Integrate project selection into AuthHandler with UI-first support
- Add project selection API endpoints and WebSocket events
- Implement ProjectSelectionDialog and useProjectSelection hook in UI
- Fixes macOS OAuth timeout by handling interactive project selection via UI
2025-12-18 04:11:59 -05:00
kaitranntt 7653caba71 feat(copilot): add complete model catalog with plan tiers
Add 19 GitHub Copilot supported models with metadata:
- Anthropic: claude-sonnet-4.5, claude-sonnet-4, claude-opus-4.5,
  claude-opus-4.1, claude-haiku-4.5
- OpenAI: gpt-5.2, gpt-5.1-codex-max, gpt-5.1-codex, gpt-5.1-codex-mini,
  gpt-5.1, gpt-5-codex, gpt-5, gpt-5-mini, gpt-4.1
- Google: gemini-3-pro, gemini-3-flash, gemini-2.5-pro
- xAI: grok-code-fast-1
- Fine-tuned: raptor-mini

Each model includes:
- minPlan: free, pro, pro+, business, enterprise
- multiplier: 0 = free tier, 0.25-0.33 = cheap, 1 = standard, 3-10 = premium
- preview: boolean for non-GA models

Update default model to claude-sonnet-4.5 (standard multiplier).
2025-12-18 03:48:47 -05:00
kaitranntt 98c21efb5a fix(websearch): detect Gemini CLI auth status before showing Ready
Previously, WebSearch status showed "Ready (Gemini)" when the CLI binary
was installed, misleading users who hadn't authenticated yet.

Changes:
- Add isGeminiAuthenticated() to check ~/.gemini/oauth_creds.json
- Add 'needs_auth' state to WebSearchReadiness type
- Show warning "[!] Gemini: run 'gemini' to login" when not authenticated
- Fix incorrect 'gemini auth login' references (no such command exists)
- Update docs with correct npm install and authentication instructions
2025-12-18 03:24:59 -05:00
kaitranntt 4783632958 fix(copilot): use token file check for instant auth status
- add hasTokenFile() for fast auth check without subprocess

- capture device code from copilot-api auth output

- export AuthFlowResult type with deviceCode and verificationUrl

- echo auth output to terminal while capturing for UI
2025-12-18 03:00:43 -05:00
kaitranntt 6b9396fbc6 feat(cliproxy): set WRITABLE_PATH for log storage in ~/.ccs/cliproxy/
- Add getCliproxyWritablePath() helper function
- Set WRITABLE_PATH env var when spawning CLIProxy in both executors
- Logs will now be stored in ~/.ccs/cliproxy/logs/ instead of CWD
- Enables error log viewer to find logs in predictable location

Note: CLIProxyAPI still has hardcoded MaxBackups=0 (unlimited).
Log rotation should be addressed in CLIProxyAPI upstream.
2025-12-18 02:54:46 -05:00
kaitranntt fee241d00b feat(api): add copilot install and info endpoints
- POST /api/copilot/install: install copilot-api (optional version)

- GET /api/copilot/info: get install status, version, path

- GET /api/copilot/status: include version in response
2025-12-18 02:27:11 -05:00
kaitranntt 9a8eea82c5 refactor(copilot): use local installation from package manager
- copilot-auth: use getCopilotApiBinPath() instead of npx

- copilot-daemon: move PID file to ~/.ccs/copilot/daemon.pid

- copilot-executor: auto-install copilot-api on first use

- index: export package manager functions
2025-12-18 02:26:46 -05:00
kaitranntt ecdad1d6d0 feat(copilot): add self-managed package manager for copilot-api
- install copilot-api locally to ~/.ccs/copilot/

- auto-update with version caching (1hr TTL)

- version pinning support via .version-pin file

- mirrors CLIProxy binary-manager pattern
2025-12-18 02:26:11 -05:00
kaitranntt 5b3d56548a feat(dashboard): add error log viewer for CLIProxy diagnostics
Add ErrorLogsMonitor component to Home page that displays CLIProxyAPI
error logs when requests fail. Users can now diagnose why success rates
drop by viewing detailed error log contents.

Backend:
- Add fetchCliproxyErrorLogs/fetchCliproxyErrorLogContent in stats-fetcher
- Add GET /api/cliproxy/error-logs and /api/cliproxy/error-logs/:name routes
- Include path traversal protection for filename validation

Frontend:
- Add CliproxyErrorLog type and errorLogs API methods
- Add useCliproxyErrorLogs/useCliproxyErrorLogContent hooks
- Create ErrorLogsMonitor component with expandable log viewer
- Integrate into Home page below AuthMonitor

Closes #132
2025-12-18 02:15:35 -05:00
kaitranntt 85cfbde5fd fix(dashboard): detect legacy proxy instances without session lock
Proxy status endpoint now falls back to port check when session tracker
has no data. Handles proxies started before session persistence feature.
2025-12-18 01:30:35 -05:00
kaitranntt 589cd2c2b7 feat(dashboard): add CLIProxy status widget with start button 2025-12-18 01:26:30 -05:00