Commit Graph
316 Commits
Author SHA1 Message Date
kaitranntt 8a3c5a446b fix: improve type safety and error handling in config-manager
- Wrap JSON.parse in try-catch with clear error message for malformed JSON
- Add iflow, kiro, ghcp providers to CLIProxyVariantConfig type
- Make settings optional in CLIProxyVariantConfig (was required with empty string fallback)
- Remove unsafe type cast in loadConfigSafe()

Addresses additional edge cases from PR #215 code review.
2025-12-27 12:28:59 -05:00
kaitranntt 2fff770b6b fix: wrap RecoveryManager in try-catch to prevent blocking CLI commands
Recovery failures (permission errors, disk full) no longer block
--version/--help commands. Recovery is best-effort - warns on failure
but allows basic CLI functionality to continue.

Fixes edge case identified in PR #215 code review.
2025-12-27 12:25:59 -05:00
kaitranntt 0be3977845 fix: run RecoveryManager before early-exit commands and improve config handling
Fixes #214 - Fresh install fails with 'Config not found' when running
ccs config before RecoveryManager runs.

Changes:
- Move RecoveryManager.recoverAll() before all early-exit commands in ccs.ts
- Fix loadConfigSafe() to return empty config instead of throwing in legacy mode
- Add getActiveConfigPath() for mode-aware config path resolution
- Rename cliproxy getConfigPath() to getCliproxyConfigPath() to avoid confusion
- Update help-command.ts to show correct config path based on mode

This ensures all commands benefit from auto-recovery on fresh installs,
and gracefully handles missing config files in all code paths.
2025-12-27 00:05:31 -05:00
Kai (Tam Nhu) TranandGitHub 8833a5a77f Merge pull request #211 from kaitranntt/fix/206-dashboard-unified-config
fix(dashboard): support unified config.yaml in web server routes
2025-12-26 10:53:08 -08:00
kaitranntt a4a473ac93 fix(config): use safe inline logic in getSettingsPath() legacy fallback
The try/catch around loadConfig() in getSettingsPath() was ineffective
because process.exit() cannot be caught by try/catch - it terminates
the process immediately.

Replace with inline safe logic that:
1. Checks if config.json exists with fs.existsSync()
2. Reads and parses JSON manually
3. Uses isConfig() type guard for validation
4. Properly catches JSON parse errors

This ensures unified mode users don't crash when falling back to check
legacy config.json for profiles not found in config.yaml.
2025-12-26 13:47:17 -05:00
kaitranntt 0c69740694 fix(dashboard): support unified config.yaml in web server routes
Add loadConfigSafe() function that handles both unified (config.yaml) and
legacy (config.json) config formats. Uses throwable errors instead of
process.exit() so try/catch blocks work properly in web server routes.

Updated files to use loadConfigSafe():
- overview-routes.ts: Dashboard overview API
- route-helpers.ts: readConfigSafe() helper
- profile-reader.ts: API profile reading
- profile-writer.ts: API profile writing
- variant-config-adapter.ts: CLIProxy variant config

Fixes #206 (Problem 2: config.json not found when user has config.yaml)
2025-12-26 13:37:54 -05:00
kaitranntt 29f19308e6 fix(cliproxy): ensure version sync after binary update
- Add SIGKILL escalation after 3s SIGTERM timeout in session-tracker
- Auto-stop running proxy before binary update in binary-manager
- Add waitForPortFree utility to port-utils
- Detect version mismatch on startup and auto-restart outdated proxy
- Store and expose version in session lock for detection

Fixes issue where old proxy version continues running after update,
causing UI to show different version than actually running.
2025-12-26 13:31:27 -05:00
github-actions[bot] 2093ae2cc8 chore(sync): merge main into dev after release [skip ci]
# Conflicts:
#	package.json
2025-12-26 18:09:54 +00:00
kaitranntt 91e7b9f937 fix(health): use prefix matching for Linux process name truncation
Linux kernel truncates process names to 15 chars, causing
'cli-proxy-api-plus' to appear as 'cli-proxy-api-p' in lsof output.
Switch from exact whitelist to prefix matching for robust detection.
2025-12-26 12:57:56 -05:00
kaitranntt ac745503e2 fix(doctor): comprehensive health check fixes
- profile-check.ts: check config.yaml first, fallback to config.json
- recovery-manager.ts: remove dead code (ensureGlm/Glmt/Kimi methods)
- 4 files: use os.homedir() for cross-platform compatibility

Fixes:
- ProfilesChecker now respects unified config format (yaml)
- Removed ~100 lines of dead code that contradicted install policy
- Windows compatibility for home directory detection

Files modified:
- src/management/checks/profile-check.ts
- src/management/recovery-manager.ts
- src/cliproxy/model-config.ts
- src/cliproxy/services/variant-service.ts
- src/web-server/health/config-checks.ts
- src/web-server/routes/settings-routes.ts
2025-12-26 12:54:54 -05:00
kaitranntt 4fca7d16ed fix(doctor): prefer config.yaml and make settings files optional
- Check config.yaml first (v2 format), fallback to config.json (legacy)
- Make glm.settings.json and kimi.settings.json optional
- Only validate settings files if they exist
- Fix false positives: postinstall no longer creates these files

Fixes health check reporting errors for missing files that are now
optional and created on-demand when user configures a profile.
2025-12-26 12:45:12 -05:00
Kai (Tam Nhu) TranandGitHub 3a6e3cf6b6 Merge pull request #205 from kaitranntt/kai/feat/customizable-auth-tokens
feat(cliproxy): customizable auth tokens for CLIProxyAPI
2025-12-26 09:35:21 -08:00
Shun KakinokiandClaude Opus 4.5 d1a0ebee61 fix(health): correct CLIProxy port detection on macOS/Linux
Two bugs caused the health check to incorrectly report "Proxy not running":

1. lsof command used mutually exclusive flags (-t and -F)
   - Removed -t flag since -F already provides structured output

2. isCLIProxyProcess whitelist was missing common binary names
   - Added: cliproxyapi, cli-proxy-api-plus (and .exe variants)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 19:42:23 +09:00
kaitranntt 7e031b5097 fix(ui): simplify config header and add explicit save button
- Reduce config.yaml header from 26 lines to 2 lines
- Replace auto-save on blur with explicit Save button in Auth section
- Add hasChanges detection to enable/disable Save button
- Remove unused saveApiKey and saveSecret functions
2025-12-25 17:02:14 -05:00
kaitranntt 9722e1905d fix(dashboard): support unified config across health checks and settings
- health-service.ts: respect isUnifiedMode() in fixHealthIssue()
- config-checks.ts: check config.yaml in unified mode
- profile-checks.ts: read profiles from unified config
- settings-routes.ts: use atomic writes (temp+rename) for presets
- profile-registry.ts: add DRY helpers getAllProfilesMerged(), getDefaultResolved()

Closes #203
2025-12-25 16:50:55 -05:00
kaitranntt 133aebaabc fix(cliproxy): use auth inheritance in stats-fetcher and config-generator
- Replace hardcoded CCS_CONTROL_PANEL_SECRET with getEffectiveManagementSecret()
- Replace hardcoded CCS_INTERNAL_API_KEY with getEffectiveApiKey()
- Ensures custom tokens work across entire CLIProxy integration
2025-12-25 14:37:53 -05:00
kaitranntt ffd499698e feat(api): add auth tokens REST endpoints
- GET /api/settings/auth/tokens - masked token status
- GET /api/settings/auth/tokens/raw - unmasked (Cache-Control: no-store)
- PUT /api/settings/auth/tokens - update API key or management secret
- POST /api/settings/auth/tokens/regenerate-secret - generate secure secret
- POST /api/settings/auth/tokens/reset - reset to defaults
2025-12-25 14:36:34 -05:00
kaitranntt 0c6491c9d2 feat(cli): add tokens command for auth token management
- Add ccs tokens command with subcommands:
  --show, --api-key, --secret, --regenerate-secret, --reset, --variant
- Integrate tokens command into main CLI (ccs.ts)
- Display masked tokens by default, --show for unmasked
- Auto-regenerate CLIProxy config on token changes
2025-12-25 14:36:11 -05:00
kaitranntt c4f09168ff feat(cliproxy): add customizable auth token manager
- Add CLIProxyAuthConfig type with api_key and management_secret fields
- Implement auth-token-manager.ts with inheritance chain:
  variant auth → global auth → default constants
- Add secure token generation using crypto.randomBytes (256-bit entropy)
- Export auth functions from cliproxy barrel (index.ts)
- Bump UNIFIED_CONFIG_VERSION to 6
2025-12-25 14:35:43 -05:00
kaitranntt 25f0ddb9dd fix(dashboard): support unified config in overview and file watcher
- overview-routes: Use ProfileRegistry for account count, merge both
  legacy and unified sources
- file-watcher: Add config.yaml to watch list for real-time updates
  in unified mode

Related to #203
2025-12-25 14:35:31 -05:00
kaitranntt 8d7845d67f fix(dashboard): read accounts from unified config
Dashboard accounts page was only reading from profiles.json, ignoring
accounts stored in config.yaml when in unified mode. This caused
accounts created via CLI to be invisible in the dashboard.

- Use ProfileRegistry instead of direct file access
- Merge legacy and unified accounts (unified takes precedence)
- Set default via unified config when in unified mode

Fixes #203
2025-12-25 14:25:40 -05:00
Kai (Tam Nhu) TranandGitHub 459d730029 Merge pull request #184 from kaitranntt/kai/feat/variant-port-isolation
feat(cliproxy): add variant port isolation
2025-12-25 05:19:06 -05:00
kaitranntt e38af6ad6e fix(ui): initialize colors early for consistent status output
Call initUI() at the start of main() to ensure chalk is loaded
before any status messages. Previously, colors only worked when
an update notification was displayed because showUpdateNotification()
was the only place calling initUI().

Fixes #201
2025-12-25 04:53:32 -05:00
kaitranntt 2b4d21e8ae fix(cliproxy): preserve user API keys during config regeneration
When CCS updates trigger CLIProxy config regeneration, user-added API
keys in ~/.ccs/cliproxy/config.yaml were being overwritten with only
the internal CCS key.

Changes:
- Add parseUserApiKeys() to extract user keys from existing config
- Modify regenerateConfig() to preserve user API keys alongside port
- Update generateUnifiedConfigContent() to accept userApiKeys param
- Add comprehensive test suite (14 tests) for key preservation

Fixes #200
2025-12-24 22:12:09 -05:00
Kai (Tam Nhu) TranandGitHub b52e6d69d6 Merge pull request #193 from kaitranntt/kai/fix/kiro-incognito
fix(kiro): add --no-incognito option for normal browser auth
2025-12-24 21:59:19 -05:00
kaitranntt f2a4200625 fix(core): address all code review issues from PR #199
Critical fixes:
- CRIT-1: Fix placeholder detection case sensitivity in api-key-validator
- CRIT-2: Add TOCTOU protection via loadMigrationCheckData() for atomic config reads
- CRIT-3: Restore fs.existsSync mock in profile-detector tests

High priority fixes:
- H1-H3: API validator HTTP/HTTPS support, timeout abort, debug log
- H4-H6: OAuth explicit flow type, signal handling, TTY detection
- H7-H8: Profile collision warning, config-first save order
- H9-H11: expandPath consistency, preset sync CLI/UI
2025-12-24 20:18:57 -05:00
Kai (Tam Nhu) TranandGitHub 080ad11804 Merge pull request #197 from kaitranntt/fix/glm-auth-persistence
fix(profiles): prevent GLM auth regression from first-time install detection
2025-12-24 18:48:40 -05:00
kaitranntt 92a79aa78b test(auth): add comprehensive tests for GLM auth persistence fix
Add 26 new unit tests covering:
- isFirstTimeInstall() legacy config detection (8 tests)
- loadSettingsFromFile() path expansion (5 tests)
- ProfileDetector detectProfileType() (4 tests)
- expandPath() cross-platform handling (10 tests)

Test coverage for issue #195:
- Legacy config.json/profiles.json detection
- Tilde expansion to home directory
- Environment variable expansion (${VAR}, $VAR, %VAR%)
- Mixed path separator normalization
- Corrupted config graceful handling

Files:
- tests/unit/commands/setup-command.test.ts
- tests/unit/auth/profile-detector.test.ts
- tests/unit/utils/expand-path.test.ts
2025-12-24 18:33:52 -05:00
kaitranntt e7066b9997 feat(api): add Minimax, DeepSeek, Qwen provider presets
Add three new Anthropic-compatible API providers as presets:
- Minimax: M2.1/M2.1-lightning/M2 models with 1M context
- DeepSeek: V3.2 and R1 reasoning model (128K context)
- Qwen: Alibaba Cloud qwen3-coder-plus (256K context)

Closes #123
2025-12-24 18:32:07 -05:00
kaitranntt adb6222bc6 refactor(paths): use expandPath() consistently for cross-platform path handling
- variant-settings.ts: Use expandPath() in deleteSettingsFile()
- profile-writer.ts: Use expandPath() in removeApiProfileUnified()
- migration-manager.ts: Remove local expandPath(), import from helpers

All path expansion now uses the central expandPath() from utils/helpers.ts
which handles ~, ~\, ${VAR}, $VAR, and %VAR% on all platforms.
2025-12-24 18:19:47 -05:00
kaitranntt cc2d62db38 fix(profiles): prevent GLM auth regression from first-time install detection
- Check legacy config.json/profiles.json in isFirstTimeInstall()
- Use expandPath() for cross-platform path handling in profile-detector
- Add pre-flight API key validation for better error messages
- Enhance 401 error handling with Z.AI refresh guidance

Fixes #195
2025-12-24 18:09:09 -05:00
kaitranntt df0c94781e feat(kiro): improve auth UX with normal browser default and URL display
- Change default to noIncognito=true (normal browser) for reliability
- Always print OAuth URL to terminal for VS Code popup detection
- Move incognito toggle from Proxy settings to Kiro provider page
- Add --incognito flag to opt into incognito mode (was --no-incognito)
- Update help text to reflect new defaults
2025-12-24 06:17:17 -05:00
kaitranntt 083e67426c feat(kiro): add UI toggle and auth hint for --no-incognito option
- Add "Kiro: Use normal browser" toggle in config dashboard (Proxy section)
- Add --no-incognito documentation to ccs --help output
- Show hint after successful Kiro auth about saving AWS credentials
2025-12-24 05:26:02 -05:00
kaitranntt 13e4baca22 fix(kiro): add --no-incognito option for normal browser auth
Kiro OAuth always opens in incognito browser mode, which doesn't save
login credentials. Users need to re-enter email each authentication.

Changes:
- Add noIncognito option to OAuthOptions interface
- Add kiro_no_incognito config option to CLIProxyConfig
- Pass --no-incognito flag to CLIProxyAPI binary when enabled
- Support both CLI flag (--no-incognito) and config.yaml setting

Usage:
- CLI: ccs kiro --auth --no-incognito
- Config: cliproxy.kiro_no_incognito: true in config.yaml
2025-12-24 05:02:33 -05:00
kaitranntt 0bcaf4bc68 feat(cliproxy): add variant port isolation for concurrent proxy instances
Enables running multiple CLIProxy variants simultaneously on different
ports. Each variant now gets a unique port in the 18100-18199 range,
allowing concurrent use of providers like Gemini + Codex + custom variants.

Key changes:
- Add port field to variant config schema
- Implement automatic port allocation (18100 + variant index)
- Support variant-specific settings paths in config generator
- Display port in dashboard UI for debugging
- Show all models in variant editor dropdown
- Add comprehensive tests for port allocation edge cases

Closes related variant isolation work.
2025-12-24 04:15:04 -05:00
kaitranntt c811fdfc79 fix(qwen): inherit stdin for Device Code flows to enable interactive prompts
Device Code flows (Qwen, GHCP) may require interactive terminal input
before generating the device code. For example, Qwen prompts for email.

Previously, all auth processes used piped stdin which blocked user input.
Now Device Code flows use 'inherit' for stdin, allowing users to respond
to prompts directly in the terminal.

Authorization Code flows (Gemini, Codex) still use piped stdin for
programmatic project selection.

Closes #188
2025-12-24 04:04:22 -05:00
kaitranntt a99b6eb93f fix(cliproxy): respect enabled:false and use protocol-based port defaults
- Fix port default logic: HTTP→8317, HTTPS→443 (was always 8317)
- Fix enabled:false being ignored in proxy config resolution
- Update stale comments referencing HTTP:80 to HTTP:8317
- Add 9 unit tests for edge cases (enabled handling, port defaults)
2025-12-24 03:36:48 -05:00
kaitranntt 5de6cccee0 refactor(ghcp): remove unused device code session management
- Remove unused functions: registerDeviceCode, completeDeviceCode,
  failDeviceCode, getActiveDeviceCode, hasActiveDeviceCode,
  getAllActiveDeviceCodes, ActiveSession interface, activeSessions Map
- Reduce device-code-handler.ts from 168 to 33 lines (YAGNI)
- Add ARIA labels to copy button for accessibility
- Fix timer to stop at 0 seconds instead of continuing negative
- Add "(Code expired)" visual indicator with destructive styling
- Change void sessionId to data-session-id attribute for debugging

Code review findings applied. Gemini OAuth unaffected (uses separate
project-selection-handler.ts with Authorization Code Flow).
2025-12-24 03:15:57 -05:00
kaitranntt 46f1699b1c fix(ghcp): display device code during OAuth device code flow
When authenticating with GitHub Copilot using device code flow,
the user code was not being displayed. This fix:

- Parses device codes from CLIProxy output in oauth-process.ts
- Displays code prominently in CLI terminal with box formatting
- Broadcasts device code events via WebSocket for UI display
- Creates DeviceCodeDialog component for web UI (ccs config)
- Follows same pattern as Gemini project selection dialog

Closes #189
2025-12-24 03:02:36 -05:00
kaitranntt ca78993e76 fix(config): improve edge case handling for config initialization
- setup-command.ts: Add Ctrl+C handling (UserCancelledError), port
  validation (1-65535), protocol stripping from host, try-catch with
  user-friendly error messages
- postinstall.js: Add ~/.ccs file check (not directory), wrap js-yaml
  require in try-catch with JSON fallback, validate config.json before
  migration, warn when both config files exist
- recovery-manager.ts: Verify config is loadable (not just exists),
  add nested error handling for fallback write
- ccs.ts: Make first-time install hint independent of recovery status
  (shows even when user manually created empty config.yaml)

All edge cases identified by code review addressed.
2025-12-23 22:34:32 -05:00
kaitranntt b34469d75f refactor(config): migrate to config.yaml as primary format
- Update postinstall.js to create config.yaml instead of config.json
- Update recovery-manager to create config.yaml as primary config
- Fix isFirstTimeInstall() to check for meaningful config content
  (profiles, accounts, variants, oauth_accounts, remote proxy)
- Update validation to accept config.yaml OR config.json
- Preserve backward compatibility: legacy config.json is migrated
  to config.yaml on first run via autoMigrate()
- Update postinstall tests to verify config.yaml creation

Fixes #142 - remote CLIProxyAPI configuration
2025-12-23 21:54:55 -05:00
kaitranntt cec616d530 feat(setup): add first-time setup wizard for config initialization
Addresses Issue #142 - remote CLIProxyAPI configuration for Docker/server deployments.

Changes:
- Add `ccs setup` command with interactive wizard
- Support local vs remote CLIProxy mode selection
- Guide users through remote proxy config (host, port, auth token)
- Auto-detect first-time install and suggest setup wizard
- Update help command to include setup

Scenarios covered:
1. New users - wizard guides through local/remote/skip choice
2. Remote proxy users - configure host/port/protocol/auth_token
3. Local users - default auto-start behavior
4. Skip CLIProxy - only API profiles or Claude accounts
2025-12-23 21:28:38 -05:00
kaitranntt e981c391a2 feat(cli): add config command hints to help and error messages
Enhance discoverability of the 'ccs config' command by adding hints to
the help menu, post-update/doctor messages, and relevant error states.
2025-12-23 00:55:17 -05:00
kaitranntt 91cd9ffc16 fix(ui): use UI color system for consistent CLI indicators 2025-12-22 19:41:05 -05:00
kaitranntt c2dd0261b7 refactor(cliproxy): enhance binary downloader with robust error handling
- Add categorized error detection for socket, timeout, HTTP, and redirect errors
- Implement smarter exponential backoff (longer delays for socket errors)
- Increase max retries from 3 to 5 with dynamic timeout adjustment
- Add resource cleanup (disable connection pooling for clean process exit)
- Add user-friendly error messages for each error type
- Refactor fetchText/fetchJson with retry logic and proper error handling
- Set 120s timeout for large binary downloads, 15-30s for text/JSON
- Prevent double-resolution and race conditions in Promise handlers
2025-12-22 18:22:32 -05:00
kaitranntt a827b73eef feat(glm): add GLM 4.7 model support
- Update default GLM/GLMT model from glm-4.6 to glm-4.7
- Add glm-4.7 pricing entry
- Sync UI presets with CLI changes

Closes #179
2025-12-22 16:13:19 -05:00
kaitrannttandMinhOmega 31bafaab8d feat(api): add Azure Foundry preset
Add Microsoft Azure AI Foundry as a provider preset for `ccs api create`.

Usage: `ccs api create --preset foundry`

This is a cleaner implementation than the postinstall-based approach,
leveraging the existing preset system.

Co-authored-by: MinhOmega <49482201+MinhOmega@users.noreply.github.com>
2025-12-22 15:34:27 -05:00
kaitranntt 8c8a15f1e1 docs(cli): add ccs kiro and ccs ghcp to help text
- add 'ccs kiro' entry for AWS CodeWhisperer

- add 'ccs ghcp' entry for GitHub Copilot OAuth

- clarify ccs copilot is for copilot-api integration
2025-12-22 00:46:01 -05:00
kaitranntt d04bcc117f feat(config): add kiro and ghcp to unified config and auth routes
- extend CLIProxyVariantConfig provider type

- update createEmptyUnifiedConfig providers array

- add kiro and ghcp to validProviders in auth routes
2025-12-22 00:45:38 -05:00
kaitranntt 49bc0a44cc feat(cliproxy): add kiro and ghcp to OAuth diagnostics and account manager
- add OAUTH_CALLBACK_PORTS: kiro=9876, ghcp=null (device code)

- add OAUTH_FLOW_TYPES for both providers

- update getAllAccountsSummary providers array
2025-12-22 00:45:13 -05:00