- Add ENOTFOUND, ENETUNREACH, EAI_AGAIN to noRetryPatterns to prevent
infinite retries on network errors
- Update E2E test to expect exit code 2 (block) when CLIProxy unavailable
- Fix debug message expectation in test
Model resolution priority:
1. provider_models[current_provider]
2. ANTHROPIC_MODEL from profile settings
3. DEFAULT_MODEL (gemini-2.5-flash)
Allows users to override vision model via profile's ANTHROPIC_MODEL.
Use Atomics.wait for synchronous sleep instead of CPU-intensive
busy-wait loop. This properly sleeps the thread without wasting cycles.
Addresses code review feedback on PR #441.
- Empty model validation: check `model.trim()` before using
- 10MB boundary: use `>=` instead of `>` for consistent messaging
- Timeout clamping: ensure timeout is between 1-600 seconds
- Response stream error: add error handler for network failures
- Empty response validation: check before JSON.parse to prevent crashes
Changes ImageAnalysisConfig from providers array to provider_models
mapping for granular vision model control per CLIProxy provider.
Breaking change: config.yaml image_analysis section now uses
provider_models instead of providers/model fields.
Provider-to-model mappings:
- agy → gemini-2.5-flash
- gemini → gemini-2.5-flash
- codex → gpt-5.1-codex-mini
- kiro → kiro-claude-haiku-4-5
- ghcp → claude-haiku-4.5
- claude → claude-haiku-4-5-20251001
Hook checks CCS_CURRENT_PROVIDER against provider_models and skips
if no vision model configured for that provider.
Match websearch transformer format:
- Header: [Image Analysis via CLIProxy]
- Metadata: File name, size in KB, model used
- Separator lines for better readability
- Footer instruction for Claude
Intercept Read tool calls for image/PDF files and route through CLIProxy
with gemini-2.5-flash for vision analysis. Returns text descriptions
instead of blocking, enabling Claude to "see" images via proxy.
Key changes:
- Add image-analyzer-transformer.cjs hook script
- Add ImageAnalysisConfig type and loader
- Add hook installer and profile injector
- Add prompt templates for analysis customization
- Add e2e test suite (excluded from normal CI runs)
- Configure test:e2e script for manual testing
Environment variables:
- CCS_IMAGE_ANALYSIS_ENABLED: Enable/disable (default: 1)
- CCS_IMAGE_ANALYSIS_MODEL: Vision model (default: gemini-2.5-flash)
- CCS_IMAGE_ANALYSIS_TIMEOUT: Timeout in seconds (default: 60)
- CCS_CLIPROXY_API_KEY: API key for CLIProxy auth
- CCS_CLIPROXY_PORT: CLIProxy port (default: 8317)
Closes#426
Match WebSearch hook pattern:
- ENABLED by default for settings/cliproxy profiles
- DISABLED for native Claude accounts (account/default)
- User can override via config: hooks.block_image_read.enabled: false
This ensures CCS CLI users get context protection out-of-the-box
while native Claude subscription users are unaffected.
Add PreToolUse hook that intercepts Read tool calls on image files
(.png, .jpg, .webp, etc.) and blocks them with helpful message.
This prevents context exhaustion when image generation skills
produce multiple files and the agent tries to read them (each
image can consume 100K+ tokens).
Configuration:
- Enable via config.yaml: hooks.block_image_read.enabled: true
- Or env var: CCS_BLOCK_IMAGE_READ=1
Hook integration:
- lib/hooks/block-image-read.cjs - the hook script
- src/utils/hooks/image-read-block-hook-env.ts - config loader
- Integrated into all spawn locations (ccs.ts, shell-executor,
cliproxy-executor)
Closes#426
Add 17 tests for isCcsWebSearchHook and deduplicateCcsHooks functions
covering Unix/Windows paths, edge cases, and duplicate cleanup.
Also add invariant comment in hook-config.ts.
Addresses code review feedback from PR #424.
Instead of showing "Quota access forbidden" generic error, now shows:
- Antigravity: "403 Forbidden - No Gemini Code Assist access"
- Codex: "403 Forbidden - No quota API access"
Keeps success=false with isForbidden flag so UI can show distinct
"403" badge (similar to Antigravity-Manager) rather than conflating
with 0% exhausted state.
403 ≠ 0% exhausted - they are semantically different:
- 403: Account lacks API access entirely
- 0%: Account has access but quota is used up (shows reset time)
- Create hook-utils.ts with isCcsWebSearchHook() and deduplicateCcsHooks()
- Update profile-hook-injector.ts and hook-config.ts to use shared module
- Combine double writeFileSync into single write in ensureHookConfig()
Addresses code review feedback on PR #420
- Add typeof check before .replace() to prevent crash on non-string commands
- Add isCcsWebSearchHook() and deduplicateCcsHooks() to hook-config.ts
- Fix ensureHookConfig() detection to verify path, not just matcher
- Prevent overwriting user's custom WebSearch hooks
- Add --settings flag to Claude CLI spawn for CLIProxy profiles
- Use getProviderSettingsPath() for hardcoded profiles (agy, gemini, codex, qwen)
- Use cfg.customSettingsPath for CLIProxy variants (user-defined providers)
- Block user --settings flag to prevent duplicate flags
- Enables WebSearch hooks to load for all CLIProxy profiles
Closes#412
Updated default Claude model IDs from outdated v4 (May 2025) to
current v4.5 versions matching model-catalog.ts:
- ANTHROPIC_MODEL: claude-sonnet-4-5-20250929
- ANTHROPIC_DEFAULT_OPUS_MODEL: claude-opus-4-5-20251101
- ANTHROPIC_DEFAULT_SONNET_MODEL: claude-sonnet-4-5-20250929
- ANTHROPIC_DEFAULT_HAIKU_MODEL: claude-haiku-4-5-20251001
Fixes "unknown provider for model" 400 errors when users add
Claude accounts and switch to Haiku tier.
On Windows, symlinks often fail so copyFallback() copies directories instead.
Previously, subsequent `ccs sync` runs would see the copied folder, fail the
isOurSymlink() check, and create a new .backup-{date} folder every time.
This fix adds Windows copy detection in installItem() before calling backupItem().
When a valid CCS copy is detected, it refreshes the content instead of backing up.
Fixes#409
- Extract Retry-After from actual HTTP response headers instead of parsing error messages
- Cap GLMT_MAX_RETRIES at 10 to prevent misconfiguration
- Prefer header-based Retry-After over message parsing (fallback preserved)
Addresses PR review feedback.
- Validate GLMT_MAX_RETRIES and GLMT_RETRY_BASE_DELAY for NaN/negative
- Add 30s max delay cap to prevent excessively long waits
Addresses PR review feedback.
Address review feedback:
- Add line-buffering to handle chunk splitting edge case
- Add 14 unit tests for stderr filter logic
- Test chunk boundary handling, mixed output, edge cases
Handles case where "npm warn cleanup" could be split across chunks.
Filter cosmetic EPERM warnings during update on Windows when npm fails
to unlink native module prebuilds (bcrypt.node) due to file locking by
antivirus/indexing services. Update still succeeds - warnings are noise.
Closes#405