diff --git a/src/cliproxy/services/variant-config-adapter.ts b/src/cliproxy/services/variant-config-adapter.ts index 40cfbfa7..3f6a869c 100644 --- a/src/cliproxy/services/variant-config-adapter.ts +++ b/src/cliproxy/services/variant-config-adapter.ts @@ -41,6 +41,8 @@ export interface VariantConfig { sonnet: CompositeTierConfig; haiku: CompositeTierConfig; }; + /** Whether any tier has fallback configured */ + hasFallback?: boolean; } /** @@ -100,13 +102,20 @@ export function listVariantsFromConfig(): Record { const v = variants[name]; if ('type' in v && v.type === 'composite') { const composite = v as CompositeVariantConfig; + const tiers = composite.tiers; + const hasFallback = !!( + tiers.opus.fallback || + tiers.sonnet.fallback || + tiers.haiku.fallback + ); result[name] = { - provider: composite.tiers[composite.default_tier].provider, + provider: tiers[composite.default_tier].provider, settings: composite.settings, port: composite.port, type: 'composite', default_tier: composite.default_tier, - tiers: composite.tiers, + tiers, + hasFallback, }; } else { const single = v as CLIProxyVariantConfig; diff --git a/src/config/unified-config-types.ts b/src/config/unified-config-types.ts index 621dc7d4..f4c4eb44 100644 --- a/src/config/unified-config-types.ts +++ b/src/config/unified-config-types.ts @@ -97,6 +97,14 @@ export interface CompositeTierConfig { model: string; /** Account nickname (optional, references oauth_accounts) */ account?: string; + /** Fallback provider+model if primary fails */ + fallback?: { + provider: 'gemini' | 'codex' | 'agy' | 'qwen' | 'iflow' | 'kiro' | 'ghcp' | 'claude'; + model: string; + account?: string; + }; + /** Per-tier thinking budget override (e.g. 'xhigh', 'medium', 'off') */ + thinking?: string; } /**