diff --git a/src/config/unified-config-loader.ts b/src/config/unified-config-loader.ts index 9f3935b2..17d28742 100644 --- a/src/config/unified-config-loader.ts +++ b/src/config/unified-config-loader.ts @@ -18,7 +18,9 @@ import { DEFAULT_GLOBAL_ENV, DEFAULT_CLIPROXY_SERVER_CONFIG, DEFAULT_QUOTA_MANAGEMENT_CONFIG, + DEFAULT_THINKING_CONFIG, GlobalEnvConfig, + ThinkingConfig, } from './unified-config-types'; import { isUnifiedConfigEnabled } from './feature-flags'; @@ -242,6 +244,20 @@ function mergeWithDefaults(partial: Partial): UnifiedConfig { DEFAULT_QUOTA_MANAGEMENT_CONFIG.manual.tier_lock, }, }, + // Thinking config - auto/manual/off control for reasoning budget + thinking: { + mode: partial.thinking?.mode ?? DEFAULT_THINKING_CONFIG.mode, + override: partial.thinking?.override, + tier_defaults: { + opus: partial.thinking?.tier_defaults?.opus ?? DEFAULT_THINKING_CONFIG.tier_defaults.opus, + sonnet: + partial.thinking?.tier_defaults?.sonnet ?? DEFAULT_THINKING_CONFIG.tier_defaults.sonnet, + haiku: + partial.thinking?.tier_defaults?.haiku ?? DEFAULT_THINKING_CONFIG.tier_defaults.haiku, + }, + provider_overrides: partial.thinking?.provider_overrides, + show_warnings: partial.thinking?.show_warnings ?? DEFAULT_THINKING_CONFIG.show_warnings, + }, }; } @@ -575,3 +591,23 @@ export function getGlobalEnvConfig(): GlobalEnvConfig { env: config.global_env?.env ?? { ...DEFAULT_GLOBAL_ENV }, }; } + +/** + * Get thinking configuration. + * Returns defaults if not configured. + */ +export function getThinkingConfig(): ThinkingConfig { + const config = loadOrCreateUnifiedConfig(); + return { + mode: config.thinking?.mode ?? DEFAULT_THINKING_CONFIG.mode, + override: config.thinking?.override, + tier_defaults: { + opus: config.thinking?.tier_defaults?.opus ?? DEFAULT_THINKING_CONFIG.tier_defaults.opus, + sonnet: + config.thinking?.tier_defaults?.sonnet ?? DEFAULT_THINKING_CONFIG.tier_defaults.sonnet, + haiku: config.thinking?.tier_defaults?.haiku ?? DEFAULT_THINKING_CONFIG.tier_defaults.haiku, + }, + provider_overrides: config.thinking?.provider_overrides, + show_warnings: config.thinking?.show_warnings ?? DEFAULT_THINKING_CONFIG.show_warnings, + }; +} diff --git a/src/config/unified-config-types.ts b/src/config/unified-config-types.ts index e5eec79b..ecb3e636 100644 --- a/src/config/unified-config-types.ts +++ b/src/config/unified-config-types.ts @@ -17,8 +17,9 @@ * Version 5 = Remote proxy configuration (connect to remote CLIProxyAPI) * Version 6 = Customizable auth tokens (API key and management secret) * Version 7 = Quota management for hybrid auto+manual account control + * Version 8 = Thinking/reasoning budget configuration */ -export const UNIFIED_CONFIG_VERSION = 7; +export const UNIFIED_CONFIG_VERSION = 8; /** * Account configuration (formerly in profiles.json). @@ -424,6 +425,66 @@ export const DEFAULT_QUOTA_MANAGEMENT_CONFIG: QuotaManagementConfig = { manual: { ...DEFAULT_MANUAL_QUOTA_CONFIG }, }; +// ============================================================================ +// THINKING CONFIGURATION (v8+) +// ============================================================================ + +/** + * Thinking mode for auto/manual/off control. + * - auto: Apply tier-based defaults (opus→high, sonnet→medium, haiku→low) + * - off: Disable thinking entirely + * - manual: Use explicit override value + */ +export type ThinkingMode = 'auto' | 'off' | 'manual'; + +/** + * Tier-to-thinking level defaults. + * Maps Claude tier names to thinking level names. + */ +export interface ThinkingTierDefaults { + /** Thinking level for opus tier (default: 'high') */ + opus: string; + /** Thinking level for sonnet tier (default: 'medium') */ + sonnet: string; + /** Thinking level for haiku tier (default: 'low') */ + haiku: string; +} + +/** + * Thinking configuration section. + * Controls thinking/reasoning budget injection for CLIProxy providers. + */ +export interface ThinkingConfig { + /** Thinking mode (default: 'auto') */ + mode: ThinkingMode; + /** Manual override value (level name or budget number) */ + override?: string | number; + /** Tier-to-level mapping */ + tier_defaults: ThinkingTierDefaults; + /** Per-provider overrides (e.g., { gemini: { opus: 'high' } }) */ + provider_overrides?: Record>; + /** Show warning when values are clamped (default: true) */ + show_warnings?: boolean; +} + +/** + * Default thinking tier defaults. + */ +export const DEFAULT_THINKING_TIER_DEFAULTS: ThinkingTierDefaults = { + opus: 'high', + sonnet: 'medium', + haiku: 'low', +}; + +/** + * Default thinking configuration. + */ +export const DEFAULT_THINKING_CONFIG: ThinkingConfig = { + mode: 'auto', + tier_defaults: { ...DEFAULT_THINKING_TIER_DEFAULTS }, + show_warnings: true, +}; + /** * Main unified configuration structure. * Stored in ~/.ccs/config.yaml @@ -451,6 +512,8 @@ export interface UnifiedConfig { cliproxy_server?: CliproxyServerConfig; /** Quota management configuration (v7+) */ quota_management?: QuotaManagementConfig; + /** Thinking/reasoning budget configuration (v8+) */ + thinking?: ThinkingConfig; } /** @@ -540,6 +603,7 @@ export function createEmptyUnifiedConfig(): UnifiedConfig { copilot: { ...DEFAULT_COPILOT_CONFIG }, cliproxy_server: { ...DEFAULT_CLIPROXY_SERVER_CONFIG }, quota_management: { ...DEFAULT_QUOTA_MANAGEMENT_CONFIG }, + thinking: { ...DEFAULT_THINKING_CONFIG }, }; }