Commit Graph
1784 Commits
Author SHA1 Message Date
github-actions[bot] 8262c8d205 chore(release): 7.40.0-dev.5 [skip ci] 2026-02-11 05:12:38 +00:00
Kai (Tam Nhu) Tran 355a127910 Merge pull request #508 from kaitranntt/kai/feat/507-config-dir-override
feat(config): add CCS_DIR env var and --config-dir flag
2026-02-11 12:11:34 +07:00
Tam Nhu Tran 706cca8b3e fix(config): dynamic health message, cache getters, static imports, cloud hint
- Fix hardcoded 'Created ~/.ccs directory' in health-service.ts fixHealthIssue()
- Cache getCacheFile() in local vars: readDiskCache, writeDiskCache, clearDiskCache
- Convert dynamic imports of setGlobalConfigDir/detectCloudSyncPath to static
- Add remediation hint to cloud sync warning: 'Consider: CCS_DIR=/path/outside/cloud'
2026-02-11 12:05:07 +07:00
Tam Nhu Tran 9699e01725 refactor(config): DRY precedence logic, dynamic recovery messages, CCS_HOME cloud warning
- Extract shared _resolveCcsDir() to prevent getCcsDir/getCcsDirSource divergence
- Replace all hardcoded ~/.ccs/ and ~/.claude/ in recovery-manager.ts with
  dynamic paths from instance properties (ccsDir, claudeDir, sharedDir, etc.)
- Add cloud sync detection for CCS_HOME env var (parity with CCS_DIR/--config-dir)
- Cache getSessionSecretPath() in local var in auth-middleware.ts
- Cache getCacheDir() in local var in disk-cache.ts ensureCacheDir()
2026-02-11 11:52:30 +07:00
Tam Nhu Tran c8800b418a fix(config): resolve remaining hardcoded paths and improve readability
- Replace hardcoded ~/.ccs in error messages: ccs.ts (lines 83, 151)
  and delegation-handler.ts (line 333) now use getCcsDir()
- Cache repeated getter calls in local vars for readability:
  openrouter-catalog.ts getCachedModels/setCachedModels,
  aggregator.ts getInstancePaths
- Add path.resolve() for CCS_HOME env var consistency with CCS_DIR
2026-02-11 11:35:44 +07:00
github-actions[bot] 687c3f2b83 chore(release): 7.40.0-dev.4 [skip ci] 2026-02-11 04:31:16 +00:00
Kai (Tam Nhu) Tran 7ec60a5be9 Merge pull request #505 from kaitranntt/kai/feat/503-ccs-env-command
feat(env): add ccs env command for third-party tool integration
2026-02-11 11:30:11 +07:00
Tam Nhu Tran d5abc7d691 fix(config): lazy-evaluate paths, fix TOCTOU, segment-boundary cloud detection
- Convert 4 module-level constants to lazy-evaluated functions to avoid
  import-time caching: openrouter-catalog, aggregator, disk-cache, auth-middleware
- Fix symlink-checks.ts to use ccsDir parameter instead of homedir/.ccs,
  remove unused homedir parameter from checkSettingsSymlinks()
- Replace TOCTOU existsSync+statSync with single statSync in try/catch
  for --config-dir validation in ccs.ts
- Switch detectCloudSyncPath from substring to path-segment-boundary matching
  to prevent false positives (e.g., megauser != MEGA, Dropbox-api != Dropbox)
- Add test for false-positive protection
2026-02-11 11:24:34 +07:00
Tam Nhu Tran b96eacfc06 fix(env): improve empty profile UX and consolidate shell validation constants
- Return {} instead of null for valid-but-empty settings profiles
- Consolidate VALID_SHELLS and validShellInputs into VALID_SHELL_INPUTS
- Fix docs test count 33 → 34
2026-02-11 11:20:25 +07:00
Tam Nhu Tran 60d6bbd027 fix(config): migrate all hardcoded paths to getCcsDir() and improve validation
- Replace os.homedir() + '.ccs' with getCcsDir() across 14 instances in 13 files:
  version-command, model-config, openrouter-catalog, config-checks, disk-cache,
  aggregator, auth-middleware, shell-completion, shared-manager, recovery-manager,
  auto-repair, delegation-validator, claude-dir-installer, cliproxy executor
- Add isDirectory() validation for --config-dir argument in ccs.ts
- Make detectCloudSyncPath() case-insensitive for cloud provider matching
- Fix help-command.ts to use dynamic dirDisplay for all path references
- Add 5 new tests: setGlobalConfigDir precedence, relative path resolution,
  reset behavior, getCcsDirSource with --config-dir, case-insensitive detection
- Clean up unused os imports after migration
2026-02-11 11:15:08 +07:00
Tam Nhu Tran a98f4a5427 fix(env): sync CLIProxy profiles across all shell completions and improve error messages
- Add profile name completions to fish env subcommand
- Add iflow, kiro, ghcp, claude to zsh proxy_profiles and PS1 cliproxyProfiles
- Distinguish non-API profile type error from "profile not found"
2026-02-11 11:02:34 +07:00
Tam Nhu Tran 7a0e6a4112 feat(config): add CCS_DIR env var and --config-dir flag for config directory override
Allow users to relocate the entire ~/.ccs/ directory via CCS_DIR env var
or --config-dir CLI flag. Precedence: --config-dir > CCS_DIR > CCS_HOME > default.
Includes cloud sync path detection warning and doctor diagnostics.

Closes #507
2026-02-11 10:55:00 +07:00
Tam Nhu Tran 6d9351dcbc fix(env): add missing CLIProxy profiles to bash completion and shell validation
- Add iflow, kiro, ghcp, claude to bash completion env block
- Add --shell flag validation matching --format pattern
- Add backtick injection test case
2026-02-11 10:50:55 +07:00
Tam Nhu Tran 38bd562687 docs: update local docs for ccs env command
- codebase-summary: add env-command.ts and test file, update test count
- system-architecture: add env-command to CLI commands list
- project-overview-pdr: add FR-011 third-party tool integration, v7.39
- project-roadmap: add Phase 15 and v7.39 milestone
2026-02-11 07:29:36 +07:00
Tam Nhu Tran 3f5ecd4d69 fix(env): address P1-P3 review items from code review
- P1: Fix bash completion $cliproxy_profiles scoping — inline profiles
  in env block since variable is only defined at COMP_CWORD=1 scope
- P2: Detect account-based profiles and show specific error message
  instead of generic "not found"
- P2: Show `ccs migrate` hint when unified mode is disabled and settings
  profile resolution fails
- P2: transformToOpenAI omits empty entries at transform time instead of
  relying on output filter (removes fragile coupling)
- P3: Add zsh and auto to --shell completions across all 4 shells; map
  --shell zsh to bash in command handler since syntax is identical
- P3: Auto-detect PowerShell from SHELL containing pwsh on non-Windows
- Tests: 33 pass (+1 pwsh detection test, updated transform assertions)
2026-02-11 07:09:58 +07:00
Tam Nhu Tran d5c03d1f2d fix(env): fix fish escaping, profile parsing, and add OPENAI_MODEL mapping
- Fix P0: fish single-quote escaping uses '\'' (end-quote, literal, reopen)
  instead of \' which fish doesn't support inside single-quoted strings
- Fix P0: profile arg parsing now skips flag values via findProfile() so
  `ccs env --format openai gemini` correctly resolves to 'gemini'
- Add OPENAI_MODEL mapping from ANTHROPIC_MODEL in transformToOpenAI
- Add stderr warning when invalid env var keys are silently dropped
- Update --shell help text to mention zsh compatibility
- Add findProfile tests (6) and OPENAI_MODEL omission test
2026-02-11 06:52:21 +07:00
Tam Nhu Tran 44b3152d34 fix(env): address all PR review feedback
- Add settings profiles to zsh env completion (was proxy-only)
- Document intentional ANTHROPIC_MODEL omission in transformToOpenAI
- Use getCcsDir() in error hint instead of hardcoded ~/.ccs/
- Export parseFlag and add 5 unit tests for flag parsing
- Add fish and PowerShell single-quote escaping tests
2026-02-11 06:46:12 +07:00
Tam Nhu Tran 041e1c6cc2 chore: update lockfiles 2026-02-11 06:41:33 +07:00
Tam Nhu Tran 76457a567d fix(env): add key sanitization and shell completions
- Validate env var keys match ^[A-Za-z_][A-Za-z0-9_]*$ before output
  to prevent injection via crafted config files
- Add env command to all 4 shell completion scripts (bash, zsh, fish,
  PowerShell) with sub-completions for --format and --shell flags
2026-02-11 06:36:51 +07:00
Tam Nhu Tran a5dc15d174 fix(env): use single quotes to prevent shell injection via eval
Switch formatExportLine from double quotes to single quotes to prevent
shell metacharacter expansion ($(), backticks, etc.) when output is
consumed via eval. Also fix parseFlag to handle values containing =,
remove unused test imports, and add empty-output guard after format
transformation.
2026-02-11 06:26:52 +07:00
Tam Nhu Tran 2e85064b8a feat(env): add ccs env command for third-party tool integration
New `ccs env <profile>` command exports shell-evaluable environment
variables for OpenCode, Cursor, Continue, and other third-party tools.

Supports --format (openai|anthropic|raw) and --shell (auto|bash|fish|
powershell) flags. Auto-detects shell from $SHELL env var.

Closes #503
2026-02-11 02:38:29 +07:00
github-actions[bot] 372b04e6a9 chore(release): 7.40.0-dev.3 [skip ci] 2026-02-10 19:30:48 +00:00
Kai (Tam Nhu) Tran 339cce2eb6 Merge pull request #504 from kaitranntt/fix/314-qwen-auth-hang
fix(cliproxy): prevent OAuth process hang on Qwen device code flow
2026-02-11 02:29:27 +07:00
Tam Nhu Tran dc9b27623b test(utils): add unit tests for killWithEscalation
- Add 7 test cases covering SIGTERM/SIGKILL escalation, timer cleanup,
  default and custom grace periods, and already-exited process edge case
- Add timer.unref() to prevent keeping event loop alive during shutdown
- Add comment explaining 10s grace period in headless-executor timeout
2026-02-11 02:25:10 +07:00
Tam Nhu Tran 90b4627740 refactor(utils): extract killWithEscalation to shared process-utils
- Move killWithEscalation to src/utils/process-utils.ts (DRY)
- Fix handleCancel to use exitCode === null and killWithEscalation
- Fix import ordering in both oauth-process.ts and headless-executor.ts
2026-02-11 02:08:12 +07:00
Tam Nhu Tran 4b1fcacf30 fix(delegation): use exitCode instead of killed for process termination checks
- Replace `!proc.killed` with `proc.exitCode === null` in headless-executor
- Extract `killWithEscalation` helper for SIGTERM→SIGKILL escalation
- Fixes pre-existing dead code where SIGKILL was never sent
2026-02-11 01:58:35 +07:00
Tam Nhu Tran 086bf958e9 fix(cliproxy): prevent OAuth process hang on Qwen device code flow
- Escalate SIGTERM to SIGKILL after 3s if Go binary is stuck in blocking HTTP call
- Extend timeout to 300s for device code flows matching CLIProxy binary polling window
- Apply SIGKILL escalation to both SIGINT cleanup and timeout handlers

Closes #314
2026-02-11 01:58:26 +07:00
github-actions[bot] 72ee3122bd chore(release): 7.40.0-dev.2 [skip ci] 2026-02-10 18:34:20 +00:00
Kai (Tam Nhu) Tran ebc58778b4 Merge pull request #497 from kaitranntt/kai/fix/155-gemini-schema-compat
fix(cliproxy): strip Gemini-unsupported schema fields including "examples"
2026-02-11 01:32:42 +07:00
github-actions[bot] fa293b3d53 chore(release): 7.40.0-dev.1 [skip ci] 2026-02-10 15:46:34 +00:00
kaitranntt 8c6afe2e73 feat: update cliproxy, config loader, glmt transformer, and provider routes 2026-02-10 10:45:16 -05:00
kaitranntt 917f0bbef7 test(cliproxy): add edge case coverage for Gemini schema sanitizer
Add tests for: exclusiveMinimum/exclusiveMaximum/multipleOf stripping,
uniqueItems/contains/additionalItems stripping, writeOnly/definitions
stripping, example with array values, default with complex nested
objects, empty properties/anyOf edge cases.

Fix proxy log message to say "Gemini-unsupported" instead of
"non-standard".
2026-02-07 06:25:29 -05:00
kaitranntt 505d6d0f11 fix(cliproxy): strip Gemini-unsupported schema fields including "examples"
Replace permissive JSON Schema Draft-07 whitelist with strict
Gemini-compatible field set (22 fields). The "examples" field
in Claude Code tool schemas caused 400 errors from Gemini API.

Also strips other unsupported fields: $ref, $defs, oneOf, allOf,
additionalProperties, const, if/then/else, etc.

Safe change — sanitizer only runs for CLIProxy profiles (Gemini,
Codex, Antigravity), never for direct Anthropic API requests.

Closes #155
2026-02-07 06:17:26 -05:00
semantic-release-bot 7ceb019bb7 chore(release): 7.40.0 [skip ci]
## [7.40.0](https://github.com/kaitranntt/ccs/compare/v7.39.0...v7.40.0) (2026-02-07)

### Features

* **cliproxy:** add hybrid catalog sync with CLIProxyAPI ([#485](https://github.com/kaitranntt/ccs/issues/485)) ([c8a0995](https://github.com/kaitranntt/ccs/commit/c8a099509a878f24a211f01ee0000f01020c4d6b)), closes [#477](https://github.com/kaitranntt/ccs/issues/477)
* **cliproxy:** delegate kiro/ghcp token refresh to CLIProxyAPIPlus ([#488](https://github.com/kaitranntt/ccs/issues/488)) ([215c00e](https://github.com/kaitranntt/ccs/commit/215c00e9830e4a604231dd64c01154c91574ace9)), closes [#487](https://github.com/kaitranntt/ccs/issues/487)

### Bug Fixes

* **cliproxy:** disable 1M extended context for opus 4.6 (256k limit) ([#492](https://github.com/kaitranntt/ccs/issues/492)) ([43cd19a](https://github.com/kaitranntt/ccs/commit/43cd19a52b128363c7202590869fb4bd9349b859)), closes [#490](https://github.com/kaitranntt/ccs/issues/490)
* **cliproxy:** guard against empty upstream SSE responses in agy profile ([#489](https://github.com/kaitranntt/ccs/issues/489)) ([545c8b9](https://github.com/kaitranntt/ccs/commit/545c8b9515d5afeda17976f418e22037cc9acef9)), closes [#350](https://github.com/kaitranntt/ccs/issues/350)
* **hooks:** add image analysis env vars for settings-based profiles ([#484](https://github.com/kaitranntt/ccs/issues/484)) ([b0dff7a](https://github.com/kaitranntt/ccs/commit/b0dff7a148c795994c2e3f871db9f60dd1cc737a)), closes [#440](https://github.com/kaitranntt/ccs/issues/440)
* **teams:** propagate CLAUDE_CONFIG_DIR to tmux session for agent teammates ([db88290](https://github.com/kaitranntt/ccs/commit/db88290b9110ba78f484d707ae3e64521db4e622))

### Code Refactoring

* **cliproxy:** check lifecycle events in remaining SSE buffer ([42a3eb1](https://github.com/kaitranntt/ccs/commit/42a3eb150630b3a466b7ec9063a2256ecc38c60e))
* **cliproxy:** deduplicate message_delta/message_stop in synthetic SSE response ([152f543](https://github.com/kaitranntt/ccs/commit/152f5432ae26e42e07ea422b882298033ed66c7f)), closes [#491](https://github.com/kaitranntt/ccs/issues/491)
* **cliproxy:** extract SSE lifecycle tracker and add backpressure handling ([1b3440b](https://github.com/kaitranntt/ccs/commit/1b3440b93962e347797105b9bf92c2aaeb954a27))
* **teams:** use spawnSync array args instead of execSync string ([0f7d5f9](https://github.com/kaitranntt/ccs/commit/0f7d5f97576d68b9c73ea952a4ea5853b0993467))
2026-02-07 10:46:43 +00:00
Kai (Tam Nhu) Tran 57f6bab9e9 Merge pull request #496 from kaitranntt/dev
release: merge dev to main for v7.39.0 production release
2026-02-07 05:45:35 -05:00
github-actions[bot] cff5133e14 chore(release): 7.39.0-dev.5 [skip ci] 2026-02-07 10:41:42 +00:00
kaitranntt 1b3440b939 refactor(cliproxy): extract SSE lifecycle tracker and add backpressure handling
Consolidate 5 duplicate boolean tracking variables into a lifecycle
object with an update() method, reducing event detection from 4
locations to centralized calls. Add pause/drain/resume backpressure
to the passthrough path to prevent unbounded memory buffering with
slow clients.
2026-02-07 05:40:24 -05:00
github-actions[bot] 68f37efda9 chore(release): 7.39.0-dev.4 [skip ci] 2026-02-07 09:39:23 +00:00
Kai (Tam Nhu) Tran b92049c956 Merge pull request #493 from kaitranntt/kai/refactor/491-dedup-sse-events
refactor(cliproxy): deduplicate message_delta/message_stop in synthetic SSE response
2026-02-07 04:38:21 -05:00
kaitranntt 42a3eb1506 refactor(cliproxy): check lifecycle events in remaining SSE buffer
Add message_start/message_delta/message_stop detection to the
remaining-buffer block in the SSE processing path for defensive
completeness. Addresses code review feedback on PR #493.
2026-02-07 04:30:42 -05:00
kaitranntt 152f5432ae refactor(cliproxy): deduplicate message_delta/message_stop in synthetic SSE response
Track hasReceivedMessageDelta and hasReceivedMessageStop in both
streaming paths (pipe-through and SSE-processing). Conditionally
omit these events from buildSyntheticErrorResponse() when upstream
already sent them, preventing protocol violations.

Closes #491
2026-02-07 04:24:54 -05:00
github-actions[bot] 17029c0ca2 chore(release): 7.39.0-dev.3 [skip ci] 2026-02-07 09:20:42 +00:00
Kai (Tam Nhu) Tran 43cd19a52b fix(cliproxy): disable 1M extended context for opus 4.6 (256k limit) (#492)
* fix(cliproxy): disable 1M extended context for gemini-claude-opus-4-6-thinking

Antigravity backend only supports 256k context window for this model,
not 1M as previously declared. Set extendedContext: false with TODO
comment for easy re-enable when backend adds support.

Closes #490

* fix(cliproxy): strip [1m] suffix at runtime for models without extended context

Users with existing [1m] in saved agy.settings.json will now have it
automatically stripped at runtime when the model no longer supports
extended context. Prevents misleading context window claims.
2026-02-07 04:19:44 -05:00
github-actions[bot] 2599136876 chore(release): 7.39.0-dev.2 [skip ci] 2026-02-07 09:10:32 +00:00
Kai (Tam Nhu) Tran 545c8b9515 fix(cliproxy): guard against empty upstream SSE responses in agy profile (#489)
* fix(cliproxy): guard against empty upstream SSE responses in agy profile

When CLIProxyAPIPlus drops unsigned thinking blocks during sub-agent
execution, the response stream can contain no content_block_start or
message_delta events. This causes Claude Code CLI to crash with
"No assistant message found".

Add empty response detection in the tool sanitization proxy's streaming
handler. Both the pipe-through and SSE-processing paths now track
whether meaningful content was received. If upstream sent data but no
content blocks on a 200 OK, a synthetic minimal valid SSE response is
injected to prevent the client crash and surface a clear error message.

Closes #350

* fix(cliproxy): improve empty response detection and add tests

Address code review findings:
- Remove message_delta from content detection (lifecycle event, not
  content); only content_block_start indicates actual content
- Add try-catch in end handlers to handle client disconnects gracefully
- Add 3 integration tests: empty stream injection, normal stream
  passthrough, 4xx/5xx non-injection

* fix(cliproxy): avoid duplicate message_start in synthetic response

Track whether upstream already sent a message_start event. When
injecting the synthetic error response, omit message_start if upstream
already sent one, preventing duplicate events in the SSE stream.

Addresses PR review feedback from ccs-reviewer[bot].

* test(cliproxy): add SSE processing path and real failure mode tests

Address code review observations:
- Add test exercising SSE processing path (sanitized tool names) for
  empty response detection, ensuring both code paths are covered
- Add test mirroring real failure mode where upstream sends only
  message_start then ends abruptly (no message_delta/message_stop)
- Document duplicate message_start assumption with inline comment
2026-02-07 04:09:30 -05:00
github-actions[bot] 984e007468 chore(release): 7.39.0-dev.1 [skip ci] 2026-02-07 08:35:20 +00:00
Kai (Tam Nhu) Tran 215c00e983 feat(cliproxy): delegate kiro/ghcp token refresh to CLIProxyAPIPlus (#488)
CLIProxyAPIPlus already handles background token refresh for kiro (every
1 min via background_refresh.go) and other providers. CCS was incorrectly
returning "not implemented" errors for these providers, causing noisy
worker logs and preventing proper token expiry tracking.

Changes:
- Classify providers into CCS-managed (gemini), CLIProxy-delegated
  (codex, agy, kiro, ghcp, qwen, iflow), and not-implemented (claude)
- Delegated providers return success with delegated flag instead of error
- Skip refresh_token requirement for delegated providers in expiry checker
- Filter delegated providers from background worker refresh loop

Closes #487
2026-02-07 03:34:14 -05:00
github-actions[bot] 8172c65d1e chore(sync): merge main into dev after release [skip ci]
# Conflicts:
#	package.json
2026-02-07 05:06:12 +00:00
semantic-release-bot 5ed6fd9fa3 chore(release): 7.39.0 [skip ci]
## [7.39.0](https://github.com/kaitranntt/ccs/compare/v7.38.0...v7.39.0) (2026-02-07)

### Features

* hybrid CLIProxy catalog sync + agent teams env fix ([#486](https://github.com/kaitranntt/ccs/issues/486)) ([0b39493](https://github.com/kaitranntt/ccs/commit/0b394933aec723f77a552b7d951afaf065399a92)), closes [#485](https://github.com/kaitranntt/ccs/issues/485) [#477](https://github.com/kaitranntt/ccs/issues/477)
2026-02-07 05:05:37 +00:00
github-actions[bot] fe263707c7 chore(release): 7.38.0-dev.4 [skip ci] 2026-02-07 04:55:27 +00:00