mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-15 02:16:27 +00:00
main
9
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
02c45e088a |
fix(extended-context): suffix the Fable tier and default it on 1M launches
The previous commit assumed Claude Code's fable resolver strips [1m] and therefore never wrote the suffix into ANTHROPIC_DEFAULT_FABLE_MODEL. That premise only holds when ANTHROPIC_BASE_URL is unset or points at api.anthropic.com. Behind a proxy (CLIProxy, headroom, ...) Claude Code 2.1.259 does the opposite: - the fable alias resolver passes the env value through untouched, so a saved `claude-fable-5-1[1m]` reaches the model picker as-is; - the context-window resolver grants 1M unconditionally when the model id carries [1m], and otherwise trusts a natively-1M model only when the base URL is first-party. Bare `claude-fable-5-1` via 127.0.0.1 is clamped to 200k even though CLIProxy's /v1/models advertises max_input_tokens 1M. So the suffix is the only thing that turns the long window on for CCS, and stripping it from the Fable key is what kept `ccs claude --model fable` at 200k. A headroom settings profile with the suffix saved on that key showed the 1M window in the same Claude Code build, which is how the inversion was caught. Changes: - Drop the suffix-stripping key guard; ANTHROPIC_DEFAULT_FABLE_MODEL now receives and keeps [1m] exactly like the opus/sonnet tiers. - On a long-context launch (explicit --1m, or a saved [1m] on any Anthropic tier key) fill a missing Fable tier with the catalog Fable model plus [1m]. The model-neutral claude profile pins no Fable model, so `--model fable` used to fall back to Claude Code's bare default and lose the window even when every other tier asked for 1M. An explicit mapping always wins, --no-1m never fills, and providers without a catalog Fable model are left alone. - Add getDefaultFableTierModel() to the model catalog for that default. Verified with a stub Claude binary that dumps its environment: ccs claude --model fable -> ANTHROPIC_DEFAULT_FABLE_MODEL=claude-fable-5-1[1m] ccs claude --1m -> ANTHROPIC_DEFAULT_FABLE_MODEL=claude-fable-5-1[1m] ccs claude --no-1m --model fable -> no Fable tier written, ANTHROPIC_MODEL stripped |
||
|
|
2b780ceae3 |
fix(extended-context): never write [1m] into the Fable tier key
Claude Code resolves ANTHROPIC_DEFAULT_FABLE_MODEL through a resolver that strips the [1m] suffix before use, unlike the opus/sonnet resolvers which pass their env value through untouched. The stripped value is then treated as an env-supplied default and held to the standard 200k window instead of the model's native 1M, so writing [1m] into that key costs the long context window rather than granting it. Measured against a Claude Code 2.1.259 session (`/context` on a live proxy endpoint): ANTHROPIC_MODEL=claude-fable-5-1[1m] -> 1m window ANTHROPIC_MODEL=claude-fable-5-1 -> 200k window ANTHROPIC_DEFAULT_FABLE_MODEL=claude-fable-5-1[1m] -> 200k window The fix is key-scoped rather than model-scoped, since the suffix is what grants 1M on every other key. Adds envKeyAcceptsExtendedContextSuffix() as the single place recording which keys reject the suffix, enforces it as a floor inside applyExtendedContextPreferenceToAnthropicModels() so no caller can bypass it, and strips a previously saved suffix from that key on the next launch through the auto path. Also extends the preference to CLAUDE_CODE_SUBAGENT_MODEL. Subagent windows come from the same resolver as the main loop (the Explore inheritCap bounds the model tier, not the context window), so a bare subagent model id sits at 200k while the suffixed form gets 1M. The new key list is kept separate from ANTHROPIC_MODEL_ENV_KEYS, which also drives routing, model-id normalization and profile validation. Claude-Session: https://claude.ai/code/session_01NPkafQjVf4pSwPBwBistGk |
||
|
|
1c72b4b8d5 |
refactor(cliproxy): flatten module structure and colocate tests (#1135)
- Split types.ts (331 LOC) into 4 concern-based files under types/: platform-types, binary-types, provider-types, config-types - Preserve backward compat via barrel re-export (types.ts → types/index) - Reorganize 53 root-level files into 8 subdirectories: accounts/, ai-providers/, auth/, binary/, config/, executor/, management/, proxy/, quota/, routing/, services/, sync/ - Reduce src/cliproxy/ root from 65 to 8 files (target: ≤10) - Colocate 87 unit tests from tests/unit/cliproxy/ into src/cliproxy/*/__tests__/ (13 colocated test directories) - Update import paths across 40+ consumer files - Add TDD backward-compat test for types split Refs #1135 |
||
|
|
5e11bba514 |
test(cliproxy): cover Claude long-context parity flows
- add regression coverage for runtime, api create flags, and help text - add provider-editor tests for multi-key [1m] state and preset preservation Refs #789 |
||
|
|
343ec959fc | fix(core): resolve edge cases and hardcoded drift | ||
|
|
539afea737 | style: format source and test files | ||
|
|
051805074e |
feat: account safety, quota monitoring, and stability fixes (#530)
* fix(cliproxy): migrate deprecated gemini-claude-* model names to upstream claude-* names (#515) * fix(cliproxy): migrate deprecated gemini-claude-* model names to upstream claude-* names CLIProxyAPI registry no longer recognizes the gemini-claude-* prefix convention. Model names in catalog, base config, and user settings are migrated to upstream claude-* names. Auto-migration in env-builder rewrites existing user settings on load and persists the change. Closes #513 * fix: address code review feedback — sync UI layer and add migration tests - Sync UI isNativeGeminiModel() with backend (remove gemini-claude- exclusion) - Update UI model catalog agy entries from gemini-claude-* to claude-* - Update CI/CD workflow and code-reviewer default model names - Add unit tests for migrateDeprecatedModelNames() logic * fix(hooks): isolate image type check before error-prone processing (#514) * fix(hooks): isolate image type check before error-prone processing Restructure processHook() into two phases so non-image Read calls never see hook error messages. Phase 1 defensively checks tool name and file extension, exiting 0 silently on any failure. Phase 2 only runs for confirmed image/PDF files where errors are relevant. Closes #511 * fix(hooks): sync image analyzer hook file on every profile launch Add installImageAnalyzerHook() call to cliproxy executor, matching the existing installWebSearchHook() pattern. This ensures the .cjs file in ~/.ccs/hooks/ gets refreshed from the npm package on every launch, so users receive hook updates after npm update. * chore(release): 7.41.0-dev.1 [skip ci] * fix(cliproxy): add fork:true for Claude model aliases in config generator (#523) Config generator now outputs fork:true for Claude model alias entries, ensuring both upstream (claude-*) and aliased (gemini-claude-*) model names appear in /v1/models listings. Also preserves fork flag when parsing user-added aliases during config regeneration. Bumps config version to v7 to trigger regeneration on next ccs doctor. Closes #522 * chore(release): 7.41.0-dev.2 [skip ci] * feat(cliproxy): add account safety guards to prevent Google account bans (#516) * feat(cliproxy): add account safety guards to prevent Google account bans Implements cross-provider isolation to prevent Google from flagging concurrent OAuth usage across different client IDs (ref: #509, #512). Three pillars: 1. Auto-pause enforcement at session launch — conflicting accounts in other Google OAuth providers are paused so CLIProxyAPI can't use them, restored on session exit with crash recovery via auto-paused.json 2. Ban/disable detection — error responses matching Google ban patterns auto-pause the affected account to prevent further damage 3. Cross-provider conflict warnings during OAuth registration Key design decisions: - PID-based session tracking for crash recovery (dead PID = restore) - Timestamp comparison prevents restoring ban-paused accounts on exit - Schema validation on auto-paused.json prevents corrupted state - Falls back to warn-only when another session is managing isolation * fix(cliproxy): address code review feedback (attempt 1/5) - Re-read auto-paused.json before write in enforceProviderIsolation to reduce concurrent write race window - Use actual email from registry for display instead of raw accountId - Export maskEmail for testability - Add 27 unit tests covering ban detection, email masking, cross-provider duplicate detection, enforcement lifecycle, crash recovery, and timestamp-guarded restore * fix(cliproxy): address remaining review feedback (attempt 2/5) - Add handleBanDetection test verifying account pause on ban error - Add warnCrossProviderDuplicates tests (true/false/non-Google) - Document PID reuse limitation in isPidAlive JSDoc comment * chore(release): 7.41.0-dev.3 [skip ci] * feat(cliproxy): runtime quota monitoring during active sessions (#529) * feat(cliproxy): add runtime quota monitoring during active sessions Adds adaptive background quota polling to detect and respond to quota exhaustion during active CLIProxy sessions. Prevents rate-limit-driven account bans by auto-cooling exhausted accounts and switching defaults. - Adaptive polling: 300s normal, 60s at 20% threshold, stops at 0% - Stderr warnings at 20%, boxed exhaustion alerts at 0% - Cooldown + default switch on exhaustion (existing patterns) - Configurable via quota_management.runtime_monitor in config.yaml - Timer.unref() prevents blocking process exit - monitorStopped guard for in-flight poll safety Closes #524 * fix: address code review feedback (attempt 1/5) - M1: Round quotaPercent display with Math.round() to avoid ugly floats - M2: Rename exhaust_threshold -> exhaustion_threshold for consistency with existing auto.exhaustion_threshold config field - M3: Replace async not.toThrow() with direct await assertion pattern * fix: address code review feedback (attempt 2/5) - Remove .claude/agent-memory/ from tracking and add to .gitignore - Unify cooldown_minutes default to 5 (was 10 in runtime_monitor, 5 in auto) - Add threshold validation in startQuotaMonitor (warn > exhaustion) - Document intentional post-switch monitoring gap in code comment * chore(release): 7.41.0-dev.4 [skip ci] * fix(cliproxy): mask email in ban detection and fix JSDoc default - Use maskEmail() in handleBanDetection output for consistency - Fix cooldown_minutes JSDoc: default is 5, not 10 * chore(release): 7.41.0-dev.5 [skip ci] * fix(cliproxy): address all review feedback (Low + informational) - Add sync constraint comment on process.exit handler (executor) - Add TOCTOU race acceptability comment (account-safety) - Mask email in handleQuotaExhaustion reason string - Use realistic exhaustion_threshold (5) in test configs * chore(release): 7.41.0-dev.6 [skip ci] --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> |
||
|
|
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. |
||
|
|
b454834175 |
feat(release): v7.38.0 - Extended Context, Qwen Models, Bug Fixes (#480)
* fix(version): show active config path instead of deprecated config.json The version command was using deprecated getConfigPath() which always returned config.json path. Now uses getActiveConfigPath() which shows config.yaml in unified mode or config.json in legacy mode. * chore(release): 7.37.1-dev.1 [skip ci] * fix(ui): use native dynamic import to fix Node 24 ESM/CJS interop TypeScript compiles import() to require() when targeting CommonJS, which breaks ESM packages like ora on Node 24. Use new Function() to create native dynamic import at runtime, bypassing TS transform. Closes #472 * chore(release): 7.37.1-dev.2 [skip ci] * fix(env): strip ANTHROPIC_* from account/default profiles Account and default profiles inherit process.env which may contain stale ANTHROPIC_BASE_URL from prior CLIProxy sessions. This causes ConnectionRefused errors when Claude tries to hit an unavailable proxy. Settings-based profiles already handle this by explicitly injecting their own ANTHROPIC_* values. This fix applies the same protection to account/default profiles by stripping ANTHROPIC_* before spawn. Closes #474 * test(env): add unit tests for stripAnthropicEnv Address code review feedback from PR #475. Tests cover: - Removing all ANTHROPIC_* keys - Preserving non-ANTHROPIC keys - Empty object handling - Undefined value preservation - Case sensitivity (only uppercase ANTHROPIC_) - All ANTHROPIC_ prefixed variants stripped * chore(release): 7.37.1-dev.3 [skip ci] * feat(cliproxy): add extended context support for 1M token window Add --1m and --no-1m flags to enable/disable 1M token context window. Uses Claude Code's [1m] suffix mechanism. Behavior: - Gemini models: auto-enabled by default - Claude models: opt-in with --1m flag - New extendedContext field in model catalog Also adds Claude Opus 4.6 to model catalog with extended context support. Closes #103 * feat(ui): add extended context toggle in dashboard model config - Add ExtendedContextToggle component for 1M token context window - Add Claude Opus 4.6 (claude-opus-4-6-20260203) to model catalogs - Mark Gemini and Claude models with extendedContext: true - Toggle only appears when selected model supports extended context - Auto-enabled info for native Gemini, opt-in info for Claude Part of extended context feature implementation for issue #103. * fix: address code review findings and CI failure - Fix CI error: add missing 'provider' prop to ModelConfigSection - Fix case sensitivity in applyExtendedContextSuffix - Fix whitespace handling in stripModelSuffixes - Handle --1m=value and --no-1m=value CLI patterns - Add warning when --1m used on unsupported model - Sync agy catalog: add extendedContext to gemini-3-pro-preview - Extract isNativeGeminiModel to shared utility (DRY) - Add 21 unit tests for extended-context-config * fix(catalog): rename claude-opus-4-6-20260203 to claude-opus-4-6 * fix(ui): wire extended context toggle through component tree - Add extendedContextEnabled and toggleExtendedContext to useProviderEditor hook - Store setting as CCS_EXTENDED_CONTEXT env var in provider settings - Pass props through provider-editor → model-config-tab → model-config-section - Update UseProviderEditorReturn type with new properties * fix(ui): apply [1m] suffix directly to model strings in settings - Toggle now applies/strips [1m] suffix to all ANTHROPIC_*MODEL env vars - Extended context detected by checking if any model has [1m] suffix - Remove legacy CCS_EXTENDED_CONTEXT flag approach - Add suffix utilities: applyExtendedContextSuffix, stripExtendedContextSuffix - Raw Configuration now shows actual model values with [1m] suffix * fix(qwen): update model catalog with correct context windows and tier mappings - Update context window specs from official Alibaba docs: - Qwen3 Coder Plus: 1M context (was 32K) - Qwen3 Max: 256K context (flagship) - Qwen3 Coder Flash: fast code generation - Fix preset mappings for Claude tier equivalence: - Opus → qwen3-max (flagship 256K) - Sonnet → qwen3-coder-plus (balanced 1M) - Haiku → qwen3-coder-flash (fast) - Update provider descriptions to reflect 256K-1M context range - Add all 7 Qwen models from CLIProxyAPI: qwen3-coder-plus, qwen3-max, qwen3-max-preview, qwen3-235b, qwen3-vl-plus, qwen3-coder-flash, qwen3-32b Closes #478 * fix(ui): only apply [1m] suffix to ANTHROPIC_MODEL, fix toggle refresh - Only ANTHROPIC_MODEL gets [1m] suffix, not tier mappings - Strip [1m] when looking up model in catalog to prevent toggle disappearing - Fix odd page refresh when toggling extended context * chore(release): 7.37.1-dev.4 [skip ci] * fix(ui): remove duplicate import in use-provider-editor * chore: address PR review feedback - sync comment and unused import * chore(release): 7.37.1-dev.5 [skip ci] * feat(cliproxy): add Opus 4.6 to Antigravity model catalog (#482) * feat(cliproxy): add Opus 4.6 to Antigravity model catalog - Add gemini-claude-opus-4-6-thinking as new default agy model - Update preset mappings to route opus tier to Opus 4.6 - Bump CLIProxy fallback versions to v6.8.2 - Keep Opus 4.5 as previous flagship option * fix(cliproxy): include oauth-model-alias in config generation Root cause: CLIProxy config.yaml was missing Opus 4.6 alias because: 1. CLIProxyPlus startup migration is disabled (intentional) 2. CCS config generator never wrote oauth-model-alias section 3. Existing users with outdated aliases got 502 on Opus 4.6 Fix: - Add DEFAULT_ANTIGRAVITY_ALIASES to config generator - Generate oauth-model-alias section in config.yaml template - Preserve claude-api-key and custom aliases during regeneration - Bump config version to v6 to trigger auto-regeneration - Update model catalog tests for new model count * fix(cliproxy): preserve YAML indentation in extractYamlSection - Replace .trim() with regex to strip only leading/trailing newlines, preserving 2-space indent on claude-api-key children - Skip standalone comments at col 0 in section boundary detection - Update stale test description (4 → 5 models) * chore(release): 7.37.1-dev.6 [skip ci] --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> |