- 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
- 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"
- Add iflow, kiro, ghcp, claude to bash completion env block
- Add --shell flag validation matching --format pattern
- Add backtick injection test case
- 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)
- 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
- 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
- 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
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.
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
- 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
- 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
- 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
- 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
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
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.
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.
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
* 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.
* 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
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
- update default model in code-reviewer.ts
- update REVIEW_MODEL, ANTHROPIC_MODEL, ANTHROPIC_DEFAULT_OPUS_MODEL
in ai-review.yml workflow
- aligns reviewer with AGY model catalog default