From 26154c3e13b14d76fee87473b84365457139c553 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Fri, 5 Dec 2025 14:55:01 -0500 Subject: [PATCH 01/16] fix(skill): use yaml block scalar for ccs-delegation description --- .claude/skills/ccs-delegation/SKILL.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.claude/skills/ccs-delegation/SKILL.md b/.claude/skills/ccs-delegation/SKILL.md index 89462939..0842d904 100644 --- a/.claude/skills/ccs-delegation/SKILL.md +++ b/.claude/skills/ccs-delegation/SKILL.md @@ -1,6 +1,12 @@ --- name: ccs-delegation -description: Auto-activate CCS CLI delegation for deterministic tasks. Parses user input, auto-selects optimal profile (glm/kimi/custom) from ~/.ccs/config.json, enhances prompts with context, executes via `ccs {profile} -p "task"` or `ccs {profile}:continue`, and reports results. Trigger: "use ccs [task]" patterns, typo/test/refactor keywords. Excludes: complex architecture, security-critical code, performance optimization, breaking changes. +description: >- + Auto-activate CCS CLI delegation for deterministic tasks. Parses user input, + auto-selects optimal profile (glm/kimi/custom) from ~/.ccs/config.json, + enhances prompts with context, executes via `ccs {profile} -p "task"` or + `ccs {profile}:continue`, and reports results. Triggers on "use ccs [task]" + patterns, typo/test/refactor keywords. Excludes complex architecture, + security-critical code, performance optimization, breaking changes. version: 3.0.0 --- From 2f575c5434fd4ac1d25b29f2d8ef9789bc9cf261 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 5 Dec 2025 19:56:28 +0000 Subject: [PATCH 02/16] chore(release): 5.7.0-dev.1 [skip ci] --- VERSION | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 42cdd0b5..30913374 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.7.0 +5.7.0-dev.1 diff --git a/package.json b/package.json index f0d36e37..bc9dd69e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "5.7.0", + "version": "5.7.0-dev.1", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli", From 9063c11e1f4231f8acb85eff7f4c77c77b472976 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Fri, 5 Dec 2025 15:01:40 -0500 Subject: [PATCH 03/16] ci: add pr validation workflow for install, build, and lint --- .github/workflows/ci.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..eb61958a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: CI + +on: + pull_request: + branches: [main, dev] + +jobs: + validate: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Build package + run: bun run build + + - name: Validate (typecheck + lint + tests) + run: bun run validate From fff40b6a27667fbeb93517c3ca473771ced46c70 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 5 Dec 2025 20:03:06 +0000 Subject: [PATCH 04/16] chore(release): 5.7.0-dev.2 [skip ci] --- VERSION | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 30913374..3090b362 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.7.0-dev.1 +5.7.0-dev.2 diff --git a/package.json b/package.json index bc9dd69e..1c30589a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "5.7.0-dev.1", + "version": "5.7.0-dev.2", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli", From 26d72cfa5bbd7ea5d4a42dc7d5c4010ae5247711 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Fri, 5 Dec 2025 16:43:08 -0500 Subject: [PATCH 05/16] feat(delegation): add passthrough args for claude cli flags Support passing through additional CLI flags like --agent, --system-prompt-file to the underlying Claude CLI when using delegation mode. --- src/delegation/delegation-handler.ts | 34 ++++++++++++++++++++++++++++ src/delegation/headless-executor.ts | 7 ++++++ 2 files changed, 41 insertions(+) diff --git a/src/delegation/delegation-handler.ts b/src/delegation/delegation-handler.ts index da245f6a..868b39cf 100644 --- a/src/delegation/delegation-handler.ts +++ b/src/delegation/delegation-handler.ts @@ -16,6 +16,7 @@ interface ParsedArgs { timeout?: number; resumeSession?: boolean; sessionId?: string; + extraArgs?: string[]; // Passthrough args for Claude CLI }; } @@ -185,6 +186,39 @@ export class DelegationHandler { options.timeout = parseInt(args[timeoutIndex + 1], 10); } + // Collect extra args to pass through to Claude CLI + // CCS-handled flags with values (skip these and their values): + const ccsFlagsWithValue = new Set(['-p', '--prompt', '--timeout', '--permission-mode']); + const extraArgs: string[] = []; + const profile = this._extractProfile(args); + + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + + // Skip profile name (non-flag first arg) + if (arg === profile && !arg.startsWith('-')) continue; + + // Skip CCS-handled flags and their values + if (ccsFlagsWithValue.has(arg)) { + i++; // Skip next arg (the value) + continue; + } + + // Collect flags and their values as passthrough + if (arg.startsWith('-')) { + extraArgs.push(arg); + // If next arg exists and doesn't start with '-', it's likely a value + if (i + 1 < args.length && !args[i + 1].startsWith('-')) { + extraArgs.push(args[i + 1]); + i++; // Skip the value we just added + } + } + } + + if (extraArgs.length > 0) { + options.extraArgs = extraArgs; + } + return options; } diff --git a/src/delegation/headless-executor.ts b/src/delegation/headless-executor.ts index a9d723d2..0416f470 100644 --- a/src/delegation/headless-executor.ts +++ b/src/delegation/headless-executor.ts @@ -45,6 +45,7 @@ interface ExecutionOptions { resumeSession?: boolean; sessionId?: string; maxRetries?: number; + extraArgs?: string[]; // Passthrough args for Claude CLI } interface ExecutionResult { @@ -112,6 +113,7 @@ export class HeadlessExecutor { permissionMode = 'acceptEdits', resumeSession = false, sessionId = null, + extraArgs = [], } = options; // Validate permission mode @@ -210,6 +212,11 @@ export class HeadlessExecutor { // Note: No max-turns limit - using time-based limits instead (default 10min timeout) + // Passthrough extra args (from Claude CLI flags like --agent, --system-prompt-file, etc.) + if (extraArgs.length > 0) { + args.push(...extraArgs); + } + // Debug log args if (process.env.CCS_DEBUG) { console.error(`[i] Claude CLI args: ${args.join(' ')}`); From f5a1b81e553d2d057dc1f49fabac1945a83fc361 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Fri, 5 Dec 2025 16:44:33 -0500 Subject: [PATCH 06/16] feat(agy): disable thinking toggle for claude models via antigravity Claude models routed through Google's Antigravity protocol don't support the thinking toggle due to protocol conversion limitations. Changes: - Add alwaysThinkingEnabled: false when selecting Claude models - Show warning about thinking toggle limitation after model selection - Reference GitHub issue #415 for technical details --- src/cliproxy/model-config.ts | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/cliproxy/model-config.ts b/src/cliproxy/model-config.ts index 0e9c9190..227d41a2 100644 --- a/src/cliproxy/model-config.ts +++ b/src/cliproxy/model-config.ts @@ -11,7 +11,15 @@ import { InteractivePrompt } from '../utils/prompt'; import { getProviderCatalog, supportsModelConfig, ModelEntry } from './model-catalog'; import { getProviderSettingsPath, getClaudeEnvVars } from './config-generator'; import { CLIProxyProvider } from './types'; -import { initUI, color, bold, dim, ok, info, header } from '../utils/ui'; +import { initUI, color, bold, dim, ok, info, warn, header } from '../utils/ui'; + +/** + * Check if model is a Claude model routed via Antigravity + * These models don't support thinking toggle due to protocol limitations + */ +function isClaudeModel(modelId: string): boolean { + return modelId.includes('claude'); +} /** CCS directory */ const CCS_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '', '.ccs'); @@ -121,7 +129,9 @@ export async function configureProviderModel( const baseEnv = getClaudeEnvVars(provider); // Build settings with selected model - const settings = { + // For Claude models via Antigravity: disable thinking toggle (protocol limitation) + const isClaude = isClaudeModel(selectedModel); + const settings: Record = { env: { ...baseEnv, ANTHROPIC_MODEL: selectedModel, @@ -131,6 +141,12 @@ export async function configureProviderModel( }, }; + // Claude models via Antigravity don't support thinking toggle + // Google's protocol conversion layer doesn't properly handle tool schemas + if (isClaude) { + settings.alwaysThinkingEnabled = false; + } + // Ensure CCS directory exists if (!fs.existsSync(CCS_DIR)) { fs.mkdirSync(CCS_DIR, { recursive: true }); @@ -146,6 +162,14 @@ export async function configureProviderModel( console.error(''); console.error(ok(`Model set to: ${bold(displayName)}`)); console.error(dim(` Config saved: ${settingsPath}`)); + + // Show warning for Claude models about thinking limitation + if (isClaude) { + console.error(''); + console.error(warn('Claude models via Antigravity have limited thinking support.')); + console.error(dim(' Thinking toggle (Tab) disabled - Google protocol limitation.')); + console.error(dim(' See: https://github.com/router-for-me/CLIProxyAPI/issues/415')); + } console.error(''); return true; From c71b1b9889e8c7064c17e86ad1f62ff3b6016ad5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 5 Dec 2025 21:45:57 +0000 Subject: [PATCH 07/16] chore(release): 5.7.0-dev.4 [skip ci] --- VERSION | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 3090b362..c60c1086 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.7.0-dev.2 +5.7.0-dev.4 diff --git a/package.json b/package.json index 1c30589a..eb87e324 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "5.7.0-dev.2", + "version": "5.7.0-dev.4", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli", From f5c31dab55033cd8db99247ca9eab8a47fcb24fb Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Fri, 5 Dec 2025 17:02:19 -0500 Subject: [PATCH 08/16] fix(agy): preserve user settings during model switch Model configuration now uses selective merge instead of full replacement: - Preserves all user customizations (includeCoAuthoredBy, MAX_TOKENS, etc.) - Only updates CCS-controlled fields (model selection, base URL, auth token) - Still enforces alwaysThinkingEnabled: false for Claude models --- src/cliproxy/model-config.ts | 48 +++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/src/cliproxy/model-config.ts b/src/cliproxy/model-config.ts index 227d41a2..2a654bc5 100644 --- a/src/cliproxy/model-config.ts +++ b/src/cliproxy/model-config.ts @@ -125,24 +125,50 @@ export async function configureProviderModel( defaultIndex: safeDefaultIdx, }); - // Get base env vars to preserve haiku model and base URL + // Get base env vars for defaults const baseEnv = getClaudeEnvVars(provider); - // Build settings with selected model - // For Claude models via Antigravity: disable thinking toggle (protocol limitation) + // Read existing settings to preserve user customizations + let existingSettings: Record = {}; + let existingEnv: Record = {}; + if (fs.existsSync(settingsPath)) { + try { + existingSettings = JSON.parse(fs.readFileSync(settingsPath, 'utf8')); + existingEnv = (existingSettings.env as Record) || {}; + } catch { + // Invalid JSON - start fresh + } + } + + // Build settings with selective merge: + // - Preserve ALL user settings (top-level and env vars) + // - Only update CCS-controlled fields (model selection + thinking toggle for Claude) const isClaude = isClaudeModel(selectedModel); + + // CCS-controlled env vars (always override with our values) + const ccsControlledEnv = { + ANTHROPIC_BASE_URL: baseEnv.ANTHROPIC_BASE_URL, + ANTHROPIC_AUTH_TOKEN: baseEnv.ANTHROPIC_AUTH_TOKEN, + ANTHROPIC_MODEL: selectedModel, + ANTHROPIC_DEFAULT_OPUS_MODEL: selectedModel, + ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel, + ANTHROPIC_DEFAULT_HAIKU_MODEL: baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL, + }; + + // Merge: user env vars (preserved) + CCS controlled (override) + const mergedEnv = { + ...existingEnv, + ...ccsControlledEnv, + }; + + // Build final settings: preserve user top-level settings + update env const settings: Record = { - env: { - ...baseEnv, - ANTHROPIC_MODEL: selectedModel, - ANTHROPIC_DEFAULT_OPUS_MODEL: selectedModel, - ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel, - // Keep haiku as-is from base config (usually flash model) - }, + ...existingSettings, + env: mergedEnv, }; // Claude models via Antigravity don't support thinking toggle - // Google's protocol conversion layer doesn't properly handle tool schemas + // Always set to false for Claude models (CCS-controlled) if (isClaude) { settings.alwaysThinkingEnabled = false; } From 9ddaa76c1bc7e57bf08ce973c6f07b2f51f02b0f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 5 Dec 2025 22:03:42 +0000 Subject: [PATCH 09/16] chore(release): 5.7.0-dev.5 [skip ci] --- VERSION | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index c60c1086..767d0ef7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.7.0-dev.4 +5.7.0-dev.5 diff --git a/package.json b/package.json index eb87e324..25e82e9a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "5.7.0-dev.4", + "version": "5.7.0-dev.5", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli", From 47700474a40539fad85c58fc5c971b85ddab45c4 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Fri, 5 Dec 2025 17:23:28 -0500 Subject: [PATCH 10/16] fix(cliproxy): only remove provider-specific auth files on logout Previously --logout cleared all files in shared auth directory. Now filters by provider prefix or JSON type field to preserve other providers. --- src/cliproxy/auth-handler.ts | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/cliproxy/auth-handler.ts b/src/cliproxy/auth-handler.ts index 311ad428..512303ce 100644 --- a/src/cliproxy/auth-handler.ts +++ b/src/cliproxy/auth-handler.ts @@ -342,6 +342,8 @@ export function getAllAuthStatus(): AuthStatus[] { /** * Clear authentication for provider + * Only removes files belonging to the specified provider (by prefix or content) + * Does NOT remove the shared auth directory or other providers' files */ export function clearAuth(provider: CLIProxyProvider): boolean { const tokenDir = getProviderTokenDir(provider); @@ -350,16 +352,33 @@ export function clearAuth(provider: CLIProxyProvider): boolean { return false; } - // Remove all files in token directory + const validPrefixes = PROVIDER_AUTH_PREFIXES[provider] || []; const files = fs.readdirSync(tokenDir); + let removedCount = 0; + + // Only remove files that belong to this provider for (const file of files) { - fs.unlinkSync(path.join(tokenDir, file)); + const filePath = path.join(tokenDir, file); + const lowerFile = file.toLowerCase(); + + // Check by prefix first (fast path) + const matchesByPrefix = validPrefixes.some((prefix) => lowerFile.startsWith(prefix)); + + // If no prefix match, check by content (for Gemini tokens without prefix) + const matchesByContent = !matchesByPrefix && isTokenFileForProvider(filePath, provider); + + if (matchesByPrefix || matchesByContent) { + try { + fs.unlinkSync(filePath); + removedCount++; + } catch { + // Failed to remove - skip + } + } } - // Remove directory - fs.rmdirSync(tokenDir); - - return true; + // DO NOT remove the shared auth directory - other providers may still have tokens + return removedCount > 0; } /** From ace5ba87502c51a7e8fe35df5fe4a8f7aaacd173 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Fri, 5 Dec 2025 17:24:12 -0500 Subject: [PATCH 11/16] fix(cliproxy): consolidate download ui to single spinner Use single spinner with update() instead of multiple spinners. Prevents UI jumping during download/verify/extract phases. --- src/cliproxy/binary-manager.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/cliproxy/binary-manager.ts b/src/cliproxy/binary-manager.ts index 81a5c8f6..bdc6df0e 100644 --- a/src/cliproxy/binary-manager.ts +++ b/src/cliproxy/binary-manager.ts @@ -383,6 +383,7 @@ export class BinaryManager { // Download archive const archivePath = path.join(this.config.binPath, `cliproxy-archive.${platform.extension}`); + // Use single spinner and update text as we progress (avoids UI jumping) const spinner = new ProgressIndicator(`Downloading CLIProxyAPI v${this.config.version}`); spinner.start(); @@ -394,11 +395,8 @@ export class BinaryManager { throw new Error(result.error || 'Download failed after retries'); } - spinner.succeed('Download complete'); - - // Verify checksum - const verifySpinner = new ProgressIndicator('Verifying checksum'); - verifySpinner.start(); + // Verify checksum (update spinner text instead of creating new one) + spinner.update('Verifying checksum'); const checksumResult = await this.verifyChecksum( archivePath, @@ -407,7 +405,7 @@ export class BinaryManager { ); if (!checksumResult.valid) { - verifySpinner.fail('Checksum mismatch'); + spinner.fail('Checksum mismatch'); fs.unlinkSync(archivePath); throw new Error( `Checksum mismatch for ${platform.binaryName}\n` + @@ -417,15 +415,12 @@ export class BinaryManager { ); } - verifySpinner.succeed('Checksum verified'); - - // Extract archive - const extractSpinner = new ProgressIndicator('Extracting binary'); - extractSpinner.start(); + // Extract archive (update spinner text) + spinner.update('Extracting binary'); await this.extractArchive(archivePath, platform.extension); - extractSpinner.succeed('Extraction complete'); + spinner.succeed('CLIProxyAPI ready'); // Cleanup archive fs.unlinkSync(archivePath); From 30eb5d255347040b18199cc8616de7e2ee8c8a85 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 5 Dec 2025 22:25:40 +0000 Subject: [PATCH 12/16] chore(release): 5.7.0-dev.6 [skip ci] --- VERSION | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 767d0ef7..0f8a41a0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.7.0-dev.5 +5.7.0-dev.6 diff --git a/package.json b/package.json index 25e82e9a..9e9680dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "5.7.0-dev.5", + "version": "5.7.0-dev.6", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli", From 6f194404722e63990f64d250d08c5f5e33235e05 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Fri, 5 Dec 2025 17:37:19 -0500 Subject: [PATCH 13/16] fix(agy): enable claude model thinking via antigravity profile - Removed broken: true and issueUrl from Claude thinking models - Added MAX_THINKING_TOKENS=8191 for Antigravity-proxied Claude models - Removed alwaysThinkingEnabled:false requirement - Updated info message explaining thinking token limit Claude models now work with extended thinking when using Antigravity proxy (MAX_THINKING_TOKENS < 8192 is required). --- src/cliproxy/model-catalog.ts | 6 ------ src/cliproxy/model-config.ts | 38 ++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/cliproxy/model-catalog.ts b/src/cliproxy/model-catalog.ts index 767fdfaf..f6b5af1c 100644 --- a/src/cliproxy/model-catalog.ts +++ b/src/cliproxy/model-catalog.ts @@ -50,22 +50,16 @@ export const MODEL_CATALOG: Partial> = id: 'gemini-claude-opus-4-5-thinking', name: 'Claude Opus 4.5 Thinking', description: 'Most capable, extended thinking', - broken: true, - issueUrl: 'https://github.com/router-for-me/CLIProxyAPI/issues/415', }, { id: 'gemini-claude-sonnet-4-5-thinking', name: 'Claude Sonnet 4.5 Thinking', description: 'Balanced with extended thinking', - broken: true, - issueUrl: 'https://github.com/router-for-me/CLIProxyAPI/issues/415', }, { id: 'gemini-claude-sonnet-4-5', name: 'Claude Sonnet 4.5', description: 'Fast and capable', - broken: true, - issueUrl: 'https://github.com/router-for-me/CLIProxyAPI/issues/415', }, { id: 'gemini-3-pro-preview', diff --git a/src/cliproxy/model-config.ts b/src/cliproxy/model-config.ts index 2a654bc5..68158e98 100644 --- a/src/cliproxy/model-config.ts +++ b/src/cliproxy/model-config.ts @@ -11,16 +11,22 @@ import { InteractivePrompt } from '../utils/prompt'; import { getProviderCatalog, supportsModelConfig, ModelEntry } from './model-catalog'; import { getProviderSettingsPath, getClaudeEnvVars } from './config-generator'; import { CLIProxyProvider } from './types'; -import { initUI, color, bold, dim, ok, info, warn, header } from '../utils/ui'; +import { initUI, color, bold, dim, ok, info, header } from '../utils/ui'; /** * Check if model is a Claude model routed via Antigravity - * These models don't support thinking toggle due to protocol limitations + * Claude models require MAX_THINKING_TOKENS < 8192 for thinking to work */ function isClaudeModel(modelId: string): boolean { return modelId.includes('claude'); } +/** + * Max thinking tokens for Claude models via Antigravity + * Must be < 8192 due to Google protocol conversion limitations + */ +const CLAUDE_MAX_THINKING_TOKENS = '8191'; + /** CCS directory */ const CCS_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '', '.ccs'); @@ -146,15 +152,20 @@ export async function configureProviderModel( const isClaude = isClaudeModel(selectedModel); // CCS-controlled env vars (always override with our values) - const ccsControlledEnv = { - ANTHROPIC_BASE_URL: baseEnv.ANTHROPIC_BASE_URL, - ANTHROPIC_AUTH_TOKEN: baseEnv.ANTHROPIC_AUTH_TOKEN, + const ccsControlledEnv: Record = { + ANTHROPIC_BASE_URL: baseEnv.ANTHROPIC_BASE_URL || '', + ANTHROPIC_AUTH_TOKEN: baseEnv.ANTHROPIC_AUTH_TOKEN || '', ANTHROPIC_MODEL: selectedModel, ANTHROPIC_DEFAULT_OPUS_MODEL: selectedModel, ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel, - ANTHROPIC_DEFAULT_HAIKU_MODEL: baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL, + ANTHROPIC_DEFAULT_HAIKU_MODEL: baseEnv.ANTHROPIC_DEFAULT_HAIKU_MODEL || '', }; + // Claude models require MAX_THINKING_TOKENS < 8192 for thinking to work + if (isClaude) { + ccsControlledEnv.MAX_THINKING_TOKENS = CLAUDE_MAX_THINKING_TOKENS; + } + // Merge: user env vars (preserved) + CCS controlled (override) const mergedEnv = { ...existingEnv, @@ -167,12 +178,6 @@ export async function configureProviderModel( env: mergedEnv, }; - // Claude models via Antigravity don't support thinking toggle - // Always set to false for Claude models (CCS-controlled) - if (isClaude) { - settings.alwaysThinkingEnabled = false; - } - // Ensure CCS directory exists if (!fs.existsSync(CCS_DIR)) { fs.mkdirSync(CCS_DIR, { recursive: true }); @@ -189,12 +194,13 @@ export async function configureProviderModel( console.error(ok(`Model set to: ${bold(displayName)}`)); console.error(dim(` Config saved: ${settingsPath}`)); - // Show warning for Claude models about thinking limitation + // Show info for Claude models about thinking token limit if (isClaude) { console.error(''); - console.error(warn('Claude models via Antigravity have limited thinking support.')); - console.error(dim(' Thinking toggle (Tab) disabled - Google protocol limitation.')); - console.error(dim(' See: https://github.com/router-for-me/CLIProxyAPI/issues/415')); + console.error( + info(`MAX_THINKING_TOKENS set to ${CLAUDE_MAX_THINKING_TOKENS} (required < 8192)`) + ); + console.error(dim(' Google protocol conversion requires this limit for thinking to work.')); } console.error(''); From b2941abdb3dadcb7d4cba146a940ee4fc4a784a9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 5 Dec 2025 22:38:46 +0000 Subject: [PATCH 14/16] chore(release): 5.7.0-dev.7 [skip ci] --- VERSION | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 0f8a41a0..1ef74a3b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.7.0-dev.6 +5.7.0-dev.7 diff --git a/package.json b/package.json index 9e9680dd..a5fed563 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "5.7.0-dev.6", + "version": "5.7.0-dev.7", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli", From 6decd157e5e7b4d19ed3dac2cfdcb0131ce9d782 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Fri, 5 Dec 2025 17:41:20 -0500 Subject: [PATCH 15/16] fix(agy): remove max_thinking_tokens when switching to non-claude model Cleans up the thinking token limit setting when user switches from a Claude model to a Gemini model via ccs agy --config. --- src/cliproxy/model-config.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cliproxy/model-config.ts b/src/cliproxy/model-config.ts index 68158e98..9ae139fb 100644 --- a/src/cliproxy/model-config.ts +++ b/src/cliproxy/model-config.ts @@ -172,6 +172,11 @@ export async function configureProviderModel( ...ccsControlledEnv, }; + // Remove MAX_THINKING_TOKENS when switching away from Claude model + if (!isClaude && mergedEnv.MAX_THINKING_TOKENS) { + delete mergedEnv.MAX_THINKING_TOKENS; + } + // Build final settings: preserve user top-level settings + update env const settings: Record = { ...existingSettings, From 165c43aa9eed9ef2289ea4d0bf18d27936fba622 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 5 Dec 2025 22:42:45 +0000 Subject: [PATCH 16/16] chore(release): 5.7.0-dev.8 [skip ci] --- VERSION | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 1ef74a3b..b54e6f23 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.7.0-dev.7 +5.7.0-dev.8 diff --git a/package.json b/package.json index a5fed563..5e0bb481 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "5.7.0-dev.7", + "version": "5.7.0-dev.8", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli",