diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index 48601067f2..2606890b0a 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -686,6 +686,16 @@ their corresponding top-level category object in your `settings.json` file. ```json { + "gemini-3.1-flash-lite-preview": { + "tier": "flash-lite", + "family": "gemini-3", + "isPreview": true, + "isVisible": true, + "features": { + "thinking": false, + "multimodalToolUse": true + } + }, "gemini-3.1-pro-preview": { "tier": "pro", "family": "gemini-3", @@ -797,7 +807,7 @@ their corresponding top-level category object in your `settings.json` file. "tier": "auto", "isPreview": true, "isVisible": true, - "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-3.1-pro, gemini-3-flash", + "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash", "features": { "thinking": true, "multimodalToolUse": false @@ -826,6 +836,39 @@ their corresponding top-level category object in your `settings.json` file. ```json { + "gemini-3.1-pro-preview": { + "default": "gemini-3.1-pro-preview", + "contexts": [ + { + "condition": { + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + } + ] + }, + "gemini-3.1-pro-preview-customtools": { + "default": "gemini-3.1-pro-preview-customtools", + "contexts": [ + { + "condition": { + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + } + ] + }, + "gemini-3-flash-preview": { + "default": "gemini-3-flash-preview", + "contexts": [ + { + "condition": { + "hasAccessToPreview": false + }, + "target": "gemini-2.5-flash" + } + ] + }, "gemini-3-pro-preview": { "default": "gemini-3-pro-preview", "contexts": [ @@ -997,6 +1040,132 @@ their corresponding top-level category object in your `settings.json` file. - **Requires restart:** Yes +- **`modelConfigs.modelChains`** (object): + - **Description:** Availability policy chains defining fallback behavior for + models. + - **Default:** + + ```json + { + "preview": [ + { + "model": "gemini-3-pro-preview", + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-3-flash-preview", + "isLastResort": true, + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + } + ], + "default": [ + { + "model": "gemini-2.5-pro", + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-2.5-flash", + "isLastResort": true, + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + } + ], + "lite": [ + { + "model": "gemini-2.5-flash-lite", + "actions": { + "terminal": "silent", + "transient": "silent", + "not_found": "silent", + "unknown": "silent" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-2.5-flash", + "actions": { + "terminal": "silent", + "transient": "silent", + "not_found": "silent", + "unknown": "silent" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-2.5-pro", + "isLastResort": true, + "actions": { + "terminal": "silent", + "transient": "silent", + "not_found": "silent", + "unknown": "silent" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + } + ] + } + ``` + + - **Requires restart:** Yes + #### `agents` - **`agents.overrides`** (object): diff --git a/packages/cli/src/config/settingsSchema.ts b/packages/cli/src/config/settingsSchema.ts index ea6b9f9239..77e1bb0c09 100644 --- a/packages/cli/src/config/settingsSchema.ts +++ b/packages/cli/src/config/settingsSchema.ts @@ -1081,6 +1081,20 @@ const SETTINGS_SCHEMA = { ref: 'ModelResolution', }, }, + modelChains: { + type: 'object', + label: 'Model Chains', + category: 'Model', + requiresRestart: true, + default: DEFAULT_MODEL_CONFIGS.modelChains, + description: + 'Availability policy chains defining fallback behavior for models.', + showInDialog: false, + additionalProperties: { + type: 'array', + ref: 'ModelPolicy', + }, + }, }, }, @@ -2877,6 +2891,34 @@ export const SETTINGS_SCHEMA_DEFINITIONS: Record< }, }, }, + ModelPolicy: { + type: 'object', + description: + 'Defines the policy for a single model in the availability chain.', + properties: { + model: { type: 'string' }, + isLastResort: { type: 'boolean' }, + actions: { + type: 'object', + properties: { + terminal: { type: 'string', enum: ['silent', 'prompt'] }, + transient: { type: 'string', enum: ['silent', 'prompt'] }, + not_found: { type: 'string', enum: ['silent', 'prompt'] }, + unknown: { type: 'string', enum: ['silent', 'prompt'] }, + }, + }, + stateTransitions: { + type: 'object', + properties: { + terminal: { type: 'string', enum: ['terminal', 'sticky_retry'] }, + transient: { type: 'string', enum: ['terminal', 'sticky_retry'] }, + not_found: { type: 'string', enum: ['terminal', 'sticky_retry'] }, + unknown: { type: 'string', enum: ['terminal', 'sticky_retry'] }, + }, + }, + }, + required: ['model'], + }, }; export function getSettingsSchema(): SettingsSchemaType { diff --git a/packages/cli/src/ui/components/ModelDialog.tsx b/packages/cli/src/ui/components/ModelDialog.tsx index b8ff3f251a..85cf16de3b 100644 --- a/packages/cli/src/ui/components/ModelDialog.tsx +++ b/packages/cli/src/ui/components/ModelDialog.tsx @@ -68,6 +68,17 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { useGemini31 && selectedAuthType === AuthType.USE_GEMINI; const manualModelSelected = useMemo(() => { + if ( + config?.getExperimentalDynamicModelConfiguration?.() === true && + config.modelConfigService + ) { + const def = config.modelConfigService.getModelDefinition(preferredModel); + // Only treat as manual selection if it's a visible, non-auto model. + return def && def.tier !== 'auto' && def.isVisible === true + ? preferredModel + : ''; + } + const manualModels = [ DEFAULT_GEMINI_MODEL, DEFAULT_GEMINI_FLASH_MODEL, @@ -81,7 +92,7 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { return preferredModel; } return ''; - }, [preferredModel]); + }, [preferredModel, config]); useKeypress( (key) => { @@ -103,6 +114,47 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { ); const mainOptions = useMemo(() => { + // --- DYNAMIC PATH --- + if ( + config?.getExperimentalDynamicModelConfiguration?.() === true && + config.modelConfigService + ) { + const list = Object.entries( + config.modelConfigService.getModelDefinitions?.() ?? {}, + ) + .filter(([_, m]) => { + // Basic visibility and Preview access + if (m.isVisible !== true) return false; + if (m.isPreview && !shouldShowPreviewModels) return false; + // Only auto models are shown on the main menu + if (m.tier !== 'auto') return false; + return true; + }) + .map(([id, m]) => ({ + value: id, + title: m.displayName ?? getDisplayString(id, config ?? undefined), + description: + id === 'auto-gemini-3' && useGemini31 + ? (m.dialogDescription ?? '').replace( + 'gemini-3-pro', + 'gemini-3.1-pro', + ) + : (m.dialogDescription ?? ''), + key: id, + })); + + list.push({ + value: 'Manual', + title: manualModelSelected + ? `Manual (${getDisplayString(manualModelSelected, config ?? undefined)})` + : 'Manual', + description: 'Manually select a model', + key: 'Manual', + }); + return list; + } + + // --- LEGACY PATH --- const list = [ { value: DEFAULT_GEMINI_MODEL_AUTO, @@ -132,10 +184,65 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { }); } return list; - }, [shouldShowPreviewModels, manualModelSelected, useGemini31]); + }, [config, shouldShowPreviewModels, manualModelSelected, useGemini31]); const manualOptions = useMemo(() => { const isFreeTier = config?.getUserTier() === UserTierId.FREE; + // --- DYNAMIC PATH --- + if ( + config?.getExperimentalDynamicModelConfiguration?.() === true && + config.modelConfigService + ) { + const list = Object.entries( + config.modelConfigService.getModelDefinitions?.() ?? {}, + ) + .filter(([id, m]) => { + // Basic visibility and Preview access + if (m.isVisible !== true) return false; + if (m.isPreview && !shouldShowPreviewModels) return false; + // Auto models are for main menu only + if (m.tier === 'auto') return false; + // Pro models are shown for users with pro access + if (!hasAccessToProModel && m.tier === 'pro') return false; + // 3.1 Preview Flash-lite is only available on free tier + if (m.tier === 'flash-lite' && m.isPreview && !isFreeTier) + return false; + + // Flag Guard: Versioned models only show if their flag is active. + if (id === PREVIEW_GEMINI_3_1_MODEL && !useGemini31) return false; + if (id === PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL && !useGemini31) + return false; + + return true; + }) + .map(([id, m]) => { + const resolvedId = config.modelConfigService.resolveModelId(id, { + useGemini3_1: useGemini31, + useCustomTools: useCustomToolModel, + }); + // Title ID is the resolved ID without custom tools flag + const titleId = config.modelConfigService.resolveModelId(id, { + useGemini3_1: useGemini31, + }); + return { + value: resolvedId, + title: + m.displayName ?? getDisplayString(titleId, config ?? undefined), + key: id, + }; + }); + + // Deduplicate: only show one entry per unique resolved model value. + // This is needed because 3 pro and 3.1 pro models can resolve to the same value. + const seen = new Set(); + return list.filter((option) => { + if (seen.has(option.value)) return false; + seen.add(option.value); + return true; + }); + } + + // --- LEGACY PATH --- const list = [ { value: DEFAULT_GEMINI_MODEL, diff --git a/packages/core/src/availability/policyHelpers.test.ts b/packages/core/src/availability/policyHelpers.test.ts index 23c6ef4fd4..8ec32e8292 100644 --- a/packages/core/src/availability/policyHelpers.test.ts +++ b/packages/core/src/availability/policyHelpers.test.ts @@ -19,6 +19,8 @@ import { PREVIEW_GEMINI_3_1_MODEL, } from '../config/models.js'; import { AuthType } from '../core/contentGenerator.js'; +import { ModelConfigService } from '../services/modelConfigService.js'; +import { DEFAULT_MODEL_CONFIGS } from '../config/defaultModelConfigs.js'; const createMockConfig = (overrides: Partial = {}): Config => { const config = { @@ -163,6 +165,66 @@ describe('policyHelpers', () => { }); }); + describe('resolvePolicyChain behavior is identical between dynamic and legacy implementations', () => { + const testCases = [ + { name: 'Default Auto', model: DEFAULT_GEMINI_MODEL_AUTO }, + { name: 'Gemini 3 Auto', model: 'auto-gemini-3' }, + { name: 'Flash Lite', model: DEFAULT_GEMINI_FLASH_LITE_MODEL }, + { + name: 'Gemini 3 Auto (3.1 Enabled)', + model: 'auto-gemini-3', + useGemini31: true, + }, + { + name: 'Gemini 3 Auto (3.1 + Custom Tools)', + model: 'auto-gemini-3', + useGemini31: true, + authType: AuthType.USE_GEMINI, + }, + { + name: 'Gemini 3 Auto (No Access)', + model: 'auto-gemini-3', + hasAccess: false, + }, + { name: 'Concrete Model (2.5 Pro)', model: 'gemini-2.5-pro' }, + { name: 'Custom Model', model: 'my-custom-model' }, + { + name: 'Wrap Around', + model: DEFAULT_GEMINI_MODEL_AUTO, + wrapsAround: true, + }, + ]; + + testCases.forEach( + ({ name, model, useGemini31, hasAccess, authType, wrapsAround }) => { + it(`achieves parity for: ${name}`, () => { + const createBaseConfig = (dynamic: boolean) => + createMockConfig({ + getExperimentalDynamicModelConfiguration: () => dynamic, + getModel: () => model, + getGemini31LaunchedSync: () => useGemini31 ?? false, + getHasAccessToPreviewModel: () => hasAccess ?? true, + getContentGeneratorConfig: () => ({ authType }), + modelConfigService: new ModelConfigService(DEFAULT_MODEL_CONFIGS), + }); + + const legacyChain = resolvePolicyChain( + createBaseConfig(false), + model, + wrapsAround, + ); + const dynamicChain = resolvePolicyChain( + createBaseConfig(true), + model, + wrapsAround, + ); + + expect(dynamicChain).toEqual(legacyChain); + }); + }, + ); + }); + describe('buildFallbackPolicyContext', () => { it('returns remaining candidates after the failed model', () => { const chain = [ diff --git a/packages/core/src/availability/policyHelpers.ts b/packages/core/src/availability/policyHelpers.ts index 290c47d896..bd8cede300 100644 --- a/packages/core/src/availability/policyHelpers.ts +++ b/packages/core/src/availability/policyHelpers.ts @@ -53,12 +53,57 @@ export function resolvePolicyChain( useGemini31, useCustomToolModel, hasAccessToPreview, + config, ); const isAutoPreferred = preferredModel ? isAutoModel(preferredModel, config) : false; const isAutoConfigured = isAutoModel(configuredModel, config); + // --- DYNAMIC PATH --- + if (config.getExperimentalDynamicModelConfiguration?.() === true) { + const context = { + useGemini3_1: useGemini31, + useCustomTools: useCustomToolModel, + }; + + if (resolvedModel === DEFAULT_GEMINI_FLASH_LITE_MODEL) { + chain = config.modelConfigService.resolveChain('lite', context); + } else if ( + isGemini3Model(resolvedModel, config) || + isAutoModel(preferredModel ?? '', config) || + isAutoModel(configuredModel, config) + ) { + // 1. Try to find a chain specifically for the current configured alias + if ( + isAutoModel(configuredModel, config) && + config.modelConfigService.getModelChain(configuredModel) + ) { + chain = config.modelConfigService.resolveChain( + configuredModel, + context, + ); + } + // 2. Fallback to family-based auto-routing + if (!chain) { + const previewEnabled = + hasAccessToPreview && + (isGemini3Model(resolvedModel, config) || + preferredModel === PREVIEW_GEMINI_MODEL_AUTO || + configuredModel === PREVIEW_GEMINI_MODEL_AUTO); + const chainKey = previewEnabled ? 'preview' : 'default'; + chain = config.modelConfigService.resolveChain(chainKey, context); + } + } + if (!chain) { + // No matching modelChains found, default to single model chain + chain = createSingleModelChain(modelFromConfig); + } + return applyDynamicSlicing(chain, resolvedModel, wrapsAround); + } + + // --- LEGACY PATH --- + if (resolvedModel === DEFAULT_GEMINI_FLASH_LITE_MODEL) { chain = getFlashLitePolicyChain(); } else if ( @@ -90,7 +135,17 @@ export function resolvePolicyChain( } else { chain = createSingleModelChain(modelFromConfig); } + return applyDynamicSlicing(chain, resolvedModel, wrapsAround); +} +/** + * Applies active-index slicing and wrap-around logic to a chain template. + */ +function applyDynamicSlicing( + chain: ModelPolicy[], + resolvedModel: string, + wrapsAround: boolean, +): ModelPolicyChain { const activeIndex = chain.findIndex( (policy) => policy.model === resolvedModel, ); diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 81bfa82bd3..f9db411c9d 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -994,6 +994,10 @@ export class Config implements McpContext, AgentLoopContext { ...DEFAULT_MODEL_CONFIGS.classifierIdResolutions, ...modelConfigServiceConfig.classifierIdResolutions, }; + const mergedModelChains = { + ...DEFAULT_MODEL_CONFIGS.modelChains, + ...modelConfigServiceConfig.modelChains, + }; modelConfigServiceConfig = { // Preserve other user settings like customAliases @@ -1007,6 +1011,7 @@ export class Config implements McpContext, AgentLoopContext { modelDefinitions: mergedModelDefinitions, modelIdResolutions: mergedModelIdResolutions, classifierIdResolutions: mergedClassifierIdResolutions, + modelChains: mergedModelChains, }; } diff --git a/packages/core/src/config/defaultModelConfigs.ts b/packages/core/src/config/defaultModelConfigs.ts index 4a9315359b..3e18ee187d 100644 --- a/packages/core/src/config/defaultModelConfigs.ts +++ b/packages/core/src/config/defaultModelConfigs.ts @@ -251,6 +251,13 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { ], modelDefinitions: { // Concrete Models + 'gemini-3.1-flash-lite-preview': { + tier: 'flash-lite', + family: 'gemini-3', + isPreview: true, + isVisible: true, + features: { thinking: false, multimodalToolUse: true }, + }, 'gemini-3.1-pro-preview': { tier: 'pro', family: 'gemini-3', @@ -331,7 +338,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { isPreview: true, isVisible: true, dialogDescription: - 'Let Gemini CLI decide the best model for the task: gemini-3.1-pro, gemini-3-flash', + 'Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash', features: { thinking: true, multimodalToolUse: false }, }, 'auto-gemini-2.5': { @@ -345,6 +352,27 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { }, }, modelIdResolutions: { + 'gemini-3.1-pro-preview': { + default: 'gemini-3.1-pro-preview', + contexts: [ + { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-pro' }, + ], + }, + 'gemini-3.1-pro-preview-customtools': { + default: 'gemini-3.1-pro-preview-customtools', + contexts: [ + { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-pro' }, + ], + }, + 'gemini-3-flash-preview': { + default: 'gemini-3-flash-preview', + contexts: [ + { + condition: { hasAccessToPreview: false }, + target: 'gemini-2.5-flash', + }, + ], + }, 'gemini-3-pro-preview': { default: 'gemini-3-pro-preview', contexts: [ @@ -451,4 +479,120 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { ], }, }, + modelChains: { + preview: [ + { + model: 'gemini-3-pro-preview', + actions: { + terminal: 'prompt', + transient: 'prompt', + not_found: 'prompt', + unknown: 'prompt', + }, + stateTransitions: { + terminal: 'terminal', + transient: 'terminal', + not_found: 'terminal', + unknown: 'terminal', + }, + }, + { + model: 'gemini-3-flash-preview', + isLastResort: true, + actions: { + terminal: 'prompt', + transient: 'prompt', + not_found: 'prompt', + unknown: 'prompt', + }, + stateTransitions: { + terminal: 'terminal', + transient: 'terminal', + not_found: 'terminal', + unknown: 'terminal', + }, + }, + ], + default: [ + { + model: 'gemini-2.5-pro', + actions: { + terminal: 'prompt', + transient: 'prompt', + not_found: 'prompt', + unknown: 'prompt', + }, + stateTransitions: { + terminal: 'terminal', + transient: 'terminal', + not_found: 'terminal', + unknown: 'terminal', + }, + }, + { + model: 'gemini-2.5-flash', + isLastResort: true, + actions: { + terminal: 'prompt', + transient: 'prompt', + not_found: 'prompt', + unknown: 'prompt', + }, + stateTransitions: { + terminal: 'terminal', + transient: 'terminal', + not_found: 'terminal', + unknown: 'terminal', + }, + }, + ], + lite: [ + { + model: 'gemini-2.5-flash-lite', + actions: { + terminal: 'silent', + transient: 'silent', + not_found: 'silent', + unknown: 'silent', + }, + stateTransitions: { + terminal: 'terminal', + transient: 'terminal', + not_found: 'terminal', + unknown: 'terminal', + }, + }, + { + model: 'gemini-2.5-flash', + actions: { + terminal: 'silent', + transient: 'silent', + not_found: 'silent', + unknown: 'silent', + }, + stateTransitions: { + terminal: 'terminal', + transient: 'terminal', + not_found: 'terminal', + unknown: 'terminal', + }, + }, + { + model: 'gemini-2.5-pro', + isLastResort: true, + actions: { + terminal: 'silent', + transient: 'silent', + not_found: 'silent', + unknown: 'silent', + }, + stateTransitions: { + terminal: 'terminal', + transient: 'terminal', + not_found: 'terminal', + unknown: 'terminal', + }, + }, + ], + }, }; diff --git a/packages/core/src/config/models.test.ts b/packages/core/src/config/models.test.ts index 9aa1e00058..dbe558fc85 100644 --- a/packages/core/src/config/models.test.ts +++ b/packages/core/src/config/models.test.ts @@ -190,14 +190,6 @@ describe('Dynamic Configuration Parity', () => { } }); - it('supportsModernFeatures should match legacy behavior', () => { - for (const model of modelsToTest) { - const legacy = supportsModernFeatures(model); - const dynamic = supportsModernFeatures(model); - expect(dynamic).toBe(legacy); - } - }); - it('supportsMultimodalFunctionResponse should match legacy behavior', () => { for (const model of modelsToTest) { const legacy = supportsMultimodalFunctionResponse(model, legacyConfig); diff --git a/packages/core/src/config/models.ts b/packages/core/src/config/models.ts index 7e1a57c5c3..f356bebbaa 100644 --- a/packages/core/src/config/models.ts +++ b/packages/core/src/config/models.ts @@ -102,11 +102,24 @@ export function resolveModel( config?: ModelCapabilityContext, ): string { if (config?.getExperimentalDynamicModelConfiguration?.() === true) { - return config.modelConfigService.resolveModelId(requestedModel, { + const resolved = config.modelConfigService.resolveModelId(requestedModel, { useGemini3_1, useCustomTools: useCustomToolModel, hasAccessToPreview, }); + + if (!hasAccessToPreview && isPreviewModel(resolved, config)) { + // Fallback for unknown preview models. + if (resolved.includes('flash-lite')) { + return DEFAULT_GEMINI_FLASH_LITE_MODEL; + } + if (resolved.includes('flash')) { + return DEFAULT_GEMINI_FLASH_MODEL; + } + return DEFAULT_GEMINI_MODEL; + } + + return resolved; } let resolved: string; diff --git a/packages/core/src/services/modelConfigService.ts b/packages/core/src/services/modelConfigService.ts index 581dbfecb9..e88f1287d5 100644 --- a/packages/core/src/services/modelConfigService.ts +++ b/packages/core/src/services/modelConfigService.ts @@ -5,6 +5,7 @@ */ import type { GenerateContentConfig } from '@google/genai'; +import type { ModelPolicy } from '../availability/modelPolicy.js'; // The primary key for the ModelConfig is the model string. However, we also // support a secondary key to limit the override scope, typically an agent name. @@ -111,6 +112,7 @@ export interface ModelConfigServiceConfig { modelDefinitions?: Record; modelIdResolutions?: Record; classifierIdResolutions?: Record; + modelChains?: Record; } const MAX_ALIAS_CHAIN_DEPTH = 100; @@ -221,6 +223,29 @@ export class ModelConfigService { return resolution.default; } + getModelChain(chainName: string): ModelPolicy[] | undefined { + return this.config.modelChains?.[chainName]; + } + + /** + * Fetches a chain template and resolves all model IDs within it + * based on the provided context. + */ + resolveChain( + chainName: string, + context: ResolutionContext = {}, + ): ModelPolicy[] | undefined { + const template = this.config.modelChains?.[chainName]; + if (!template) { + return undefined; + } + // Map through the template and resolve each model ID + return template.map((policy) => ({ + ...policy, + model: this.resolveModelId(policy.model, context), + })); + } + registerRuntimeModelConfig(aliasName: string, alias: ModelConfigAlias): void { this.runtimeAliases[aliasName] = alias; } diff --git a/schemas/settings.schema.json b/schemas/settings.schema.json index 2b528ad8dc..a6f507ae63 100644 --- a/schemas/settings.schema.json +++ b/schemas/settings.schema.json @@ -629,7 +629,7 @@ "modelConfigs": { "title": "Model Configs", "description": "Model configurations.", - "markdownDescription": "Model configurations.\n\n- Category: `Model`\n- Requires restart: `no`\n- Default: `{\n \"aliases\": {\n \"base\": {\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"temperature\": 0,\n \"topP\": 1\n }\n }\n },\n \"chat-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"includeThoughts\": true\n },\n \"temperature\": 1,\n \"topP\": 0.95,\n \"topK\": 64\n }\n }\n },\n \"chat-base-2.5\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 8192\n }\n }\n }\n },\n \"chat-base-3\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingLevel\": \"HIGH\"\n }\n }\n }\n },\n \"gemini-3-pro-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"gemini-3-flash-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3-flash-preview\"\n }\n },\n \"gemini-2.5-pro\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"gemini-2.5-flash\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"gemini-2.5-flash-lite\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\"\n }\n },\n \"gemini-2.5-flash-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"gemini-3-flash-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-3-flash-preview\"\n }\n },\n \"classifier\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 1024,\n \"thinkingConfig\": {\n \"thinkingBudget\": 512\n }\n }\n }\n },\n \"prompt-completion\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"temperature\": 0.3,\n \"maxOutputTokens\": 16000,\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"fast-ack-helper\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"temperature\": 0.2,\n \"maxOutputTokens\": 120,\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"edit-corrector\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"summarizer-default\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"summarizer-shell\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"web-search\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"googleSearch\": {}\n }\n ]\n }\n }\n },\n \"web-fetch\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"urlContext\": {}\n }\n ]\n }\n }\n },\n \"web-fetch-fallback\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection-double-check\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"llm-edit-fixer\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {}\n },\n \"next-speaker-checker\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {}\n },\n \"chat-compression-3-pro\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"chat-compression-3-flash\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-flash-preview\"\n }\n },\n \"chat-compression-2.5-pro\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"chat-compression-2.5-flash\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"chat-compression-2.5-flash-lite\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\"\n }\n },\n \"chat-compression-default\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n }\n },\n \"overrides\": [\n {\n \"match\": {\n \"model\": \"chat-base\",\n \"isRetry\": true\n },\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"temperature\": 1\n }\n }\n }\n ],\n \"modelDefinitions\": {\n \"gemini-3.1-pro-preview\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3.1-pro-preview-customtools\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3-pro-preview\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3-flash-preview\": {\n \"tier\": \"flash\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-2.5-pro\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"gemini-2.5-flash\": {\n \"tier\": \"flash\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"gemini-2.5-flash-lite\": {\n \"tier\": \"flash-lite\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"auto\": {\n \"tier\": \"auto\",\n \"isPreview\": true,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"pro\": {\n \"tier\": \"pro\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"flash\": {\n \"tier\": \"flash\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"flash-lite\": {\n \"tier\": \"flash-lite\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"auto-gemini-3\": {\n \"displayName\": \"Auto (Gemini 3)\",\n \"tier\": \"auto\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"dialogDescription\": \"Let Gemini CLI decide the best model for the task: gemini-3.1-pro, gemini-3-flash\",\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"auto-gemini-2.5\": {\n \"displayName\": \"Auto (Gemini 2.5)\",\n \"tier\": \"auto\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"dialogDescription\": \"Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash\",\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n }\n },\n \"modelIdResolutions\": {\n \"gemini-3-pro-preview\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto-gemini-3\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"pro\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto-gemini-2.5\": {\n \"default\": \"gemini-2.5-pro\"\n },\n \"flash\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n }\n ]\n },\n \"flash-lite\": {\n \"default\": \"gemini-2.5-flash-lite\"\n }\n },\n \"classifierIdResolutions\": {\n \"flash\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"requestedModels\": [\n \"auto-gemini-2.5\",\n \"gemini-2.5-pro\"\n ]\n },\n \"target\": \"gemini-2.5-flash\"\n },\n {\n \"condition\": {\n \"requestedModels\": [\n \"auto-gemini-3\",\n \"gemini-3-pro-preview\"\n ]\n },\n \"target\": \"gemini-3-flash-preview\"\n }\n ]\n },\n \"pro\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"requestedModels\": [\n \"auto-gemini-2.5\",\n \"gemini-2.5-pro\"\n ]\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n }\n }\n}`", + "markdownDescription": "Model configurations.\n\n- Category: `Model`\n- Requires restart: `no`\n- Default: `{\n \"aliases\": {\n \"base\": {\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"temperature\": 0,\n \"topP\": 1\n }\n }\n },\n \"chat-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"includeThoughts\": true\n },\n \"temperature\": 1,\n \"topP\": 0.95,\n \"topK\": 64\n }\n }\n },\n \"chat-base-2.5\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 8192\n }\n }\n }\n },\n \"chat-base-3\": {\n \"extends\": \"chat-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingLevel\": \"HIGH\"\n }\n }\n }\n },\n \"gemini-3-pro-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"gemini-3-flash-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3-flash-preview\"\n }\n },\n \"gemini-2.5-pro\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"gemini-2.5-flash\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"gemini-2.5-flash-lite\": {\n \"extends\": \"chat-base-2.5\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\"\n }\n },\n \"gemini-2.5-flash-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"gemini-3-flash-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-3-flash-preview\"\n }\n },\n \"classifier\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 1024,\n \"thinkingConfig\": {\n \"thinkingBudget\": 512\n }\n }\n }\n },\n \"prompt-completion\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"temperature\": 0.3,\n \"maxOutputTokens\": 16000,\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"fast-ack-helper\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"temperature\": 0.2,\n \"maxOutputTokens\": 120,\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"edit-corrector\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"summarizer-default\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"summarizer-shell\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"web-search\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"googleSearch\": {}\n }\n ]\n }\n }\n },\n \"web-fetch\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"tools\": [\n {\n \"urlContext\": {}\n }\n ]\n }\n }\n },\n \"web-fetch-fallback\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {}\n },\n \"loop-detection-double-check\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"llm-edit-fixer\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {}\n },\n \"next-speaker-checker\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {}\n },\n \"chat-compression-3-pro\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n },\n \"chat-compression-3-flash\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-flash-preview\"\n }\n },\n \"chat-compression-2.5-pro\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-pro\"\n }\n },\n \"chat-compression-2.5-flash\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash\"\n }\n },\n \"chat-compression-2.5-flash-lite\": {\n \"modelConfig\": {\n \"model\": \"gemini-2.5-flash-lite\"\n }\n },\n \"chat-compression-default\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-pro-preview\"\n }\n }\n },\n \"overrides\": [\n {\n \"match\": {\n \"model\": \"chat-base\",\n \"isRetry\": true\n },\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"temperature\": 1\n }\n }\n }\n ],\n \"modelDefinitions\": {\n \"gemini-3.1-flash-lite-preview\": {\n \"tier\": \"flash-lite\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3.1-pro-preview\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3.1-pro-preview-customtools\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3-pro-preview\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3-flash-preview\": {\n \"tier\": \"flash\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-2.5-pro\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"gemini-2.5-flash\": {\n \"tier\": \"flash\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"gemini-2.5-flash-lite\": {\n \"tier\": \"flash-lite\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"auto\": {\n \"tier\": \"auto\",\n \"isPreview\": true,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"pro\": {\n \"tier\": \"pro\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"flash\": {\n \"tier\": \"flash\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"flash-lite\": {\n \"tier\": \"flash-lite\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"auto-gemini-3\": {\n \"displayName\": \"Auto (Gemini 3)\",\n \"tier\": \"auto\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"dialogDescription\": \"Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash\",\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"auto-gemini-2.5\": {\n \"displayName\": \"Auto (Gemini 2.5)\",\n \"tier\": \"auto\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"dialogDescription\": \"Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash\",\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n }\n },\n \"modelIdResolutions\": {\n \"gemini-3.1-pro-preview\": {\n \"default\": \"gemini-3.1-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n }\n ]\n },\n \"gemini-3.1-pro-preview-customtools\": {\n \"default\": \"gemini-3.1-pro-preview-customtools\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n }\n ]\n },\n \"gemini-3-flash-preview\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n }\n ]\n },\n \"gemini-3-pro-preview\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto-gemini-3\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"pro\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto-gemini-2.5\": {\n \"default\": \"gemini-2.5-pro\"\n },\n \"flash\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n }\n ]\n },\n \"flash-lite\": {\n \"default\": \"gemini-2.5-flash-lite\"\n }\n },\n \"classifierIdResolutions\": {\n \"flash\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"requestedModels\": [\n \"auto-gemini-2.5\",\n \"gemini-2.5-pro\"\n ]\n },\n \"target\": \"gemini-2.5-flash\"\n },\n {\n \"condition\": {\n \"requestedModels\": [\n \"auto-gemini-3\",\n \"gemini-3-pro-preview\"\n ]\n },\n \"target\": \"gemini-3-flash-preview\"\n }\n ]\n },\n \"pro\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"requestedModels\": [\n \"auto-gemini-2.5\",\n \"gemini-2.5-pro\"\n ]\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n }\n },\n \"modelChains\": {\n \"preview\": [\n {\n \"model\": \"gemini-3-pro-preview\",\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"prompt\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-3-flash-preview\",\n \"isLastResort\": true,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"prompt\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n }\n ],\n \"default\": [\n {\n \"model\": \"gemini-2.5-pro\",\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"prompt\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"isLastResort\": true,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"prompt\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n }\n ],\n \"lite\": [\n {\n \"model\": \"gemini-2.5-flash-lite\",\n \"actions\": {\n \"terminal\": \"silent\",\n \"transient\": \"silent\",\n \"not_found\": \"silent\",\n \"unknown\": \"silent\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"actions\": {\n \"terminal\": \"silent\",\n \"transient\": \"silent\",\n \"not_found\": \"silent\",\n \"unknown\": \"silent\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-pro\",\n \"isLastResort\": true,\n \"actions\": {\n \"terminal\": \"silent\",\n \"transient\": \"silent\",\n \"not_found\": \"silent\",\n \"unknown\": \"silent\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n }\n ]\n }\n}`", "default": { "aliases": { "base": { @@ -873,6 +873,16 @@ } ], "modelDefinitions": { + "gemini-3.1-flash-lite-preview": { + "tier": "flash-lite", + "family": "gemini-3", + "isPreview": true, + "isVisible": true, + "features": { + "thinking": false, + "multimodalToolUse": true + } + }, "gemini-3.1-pro-preview": { "tier": "pro", "family": "gemini-3", @@ -984,7 +994,7 @@ "tier": "auto", "isPreview": true, "isVisible": true, - "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-3.1-pro, gemini-3-flash", + "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash", "features": { "thinking": true, "multimodalToolUse": false @@ -1003,6 +1013,39 @@ } }, "modelIdResolutions": { + "gemini-3.1-pro-preview": { + "default": "gemini-3.1-pro-preview", + "contexts": [ + { + "condition": { + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + } + ] + }, + "gemini-3.1-pro-preview-customtools": { + "default": "gemini-3.1-pro-preview-customtools", + "contexts": [ + { + "condition": { + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + } + ] + }, + "gemini-3-flash-preview": { + "default": "gemini-3-flash-preview", + "contexts": [ + { + "condition": { + "hasAccessToPreview": false + }, + "target": "gemini-2.5-flash" + } + ] + }, "gemini-3-pro-preview": { "default": "gemini-3-pro-preview", "contexts": [ @@ -1159,6 +1202,122 @@ } ] } + }, + "modelChains": { + "preview": [ + { + "model": "gemini-3-pro-preview", + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-3-flash-preview", + "isLastResort": true, + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + } + ], + "default": [ + { + "model": "gemini-2.5-pro", + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-2.5-flash", + "isLastResort": true, + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + } + ], + "lite": [ + { + "model": "gemini-2.5-flash-lite", + "actions": { + "terminal": "silent", + "transient": "silent", + "not_found": "silent", + "unknown": "silent" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-2.5-flash", + "actions": { + "terminal": "silent", + "transient": "silent", + "not_found": "silent", + "unknown": "silent" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-2.5-pro", + "isLastResort": true, + "actions": { + "terminal": "silent", + "transient": "silent", + "not_found": "silent", + "unknown": "silent" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + } + ] } }, "type": "object", @@ -1425,8 +1584,18 @@ "modelDefinitions": { "title": "Model Definitions", "description": "Registry of model metadata, including tier, family, and features.", - "markdownDescription": "Registry of model metadata, including tier, family, and features.\n\n- Category: `Model`\n- Requires restart: `yes`\n- Default: `{\n \"gemini-3.1-pro-preview\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3.1-pro-preview-customtools\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3-pro-preview\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3-flash-preview\": {\n \"tier\": \"flash\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-2.5-pro\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"gemini-2.5-flash\": {\n \"tier\": \"flash\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"gemini-2.5-flash-lite\": {\n \"tier\": \"flash-lite\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"auto\": {\n \"tier\": \"auto\",\n \"isPreview\": true,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"pro\": {\n \"tier\": \"pro\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"flash\": {\n \"tier\": \"flash\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"flash-lite\": {\n \"tier\": \"flash-lite\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"auto-gemini-3\": {\n \"displayName\": \"Auto (Gemini 3)\",\n \"tier\": \"auto\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"dialogDescription\": \"Let Gemini CLI decide the best model for the task: gemini-3.1-pro, gemini-3-flash\",\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"auto-gemini-2.5\": {\n \"displayName\": \"Auto (Gemini 2.5)\",\n \"tier\": \"auto\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"dialogDescription\": \"Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash\",\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n }\n}`", + "markdownDescription": "Registry of model metadata, including tier, family, and features.\n\n- Category: `Model`\n- Requires restart: `yes`\n- Default: `{\n \"gemini-3.1-flash-lite-preview\": {\n \"tier\": \"flash-lite\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3.1-pro-preview\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3.1-pro-preview-customtools\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3-pro-preview\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-3-flash-preview\": {\n \"tier\": \"flash\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": true\n }\n },\n \"gemini-2.5-pro\": {\n \"tier\": \"pro\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"gemini-2.5-flash\": {\n \"tier\": \"flash\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"gemini-2.5-flash-lite\": {\n \"tier\": \"flash-lite\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"auto\": {\n \"tier\": \"auto\",\n \"isPreview\": true,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"pro\": {\n \"tier\": \"pro\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"flash\": {\n \"tier\": \"flash\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"flash-lite\": {\n \"tier\": \"flash-lite\",\n \"isPreview\": false,\n \"isVisible\": false,\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n },\n \"auto-gemini-3\": {\n \"displayName\": \"Auto (Gemini 3)\",\n \"tier\": \"auto\",\n \"isPreview\": true,\n \"isVisible\": true,\n \"dialogDescription\": \"Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash\",\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"auto-gemini-2.5\": {\n \"displayName\": \"Auto (Gemini 2.5)\",\n \"tier\": \"auto\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"dialogDescription\": \"Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash\",\n \"features\": {\n \"thinking\": false,\n \"multimodalToolUse\": false\n }\n }\n}`", "default": { + "gemini-3.1-flash-lite-preview": { + "tier": "flash-lite", + "family": "gemini-3", + "isPreview": true, + "isVisible": true, + "features": { + "thinking": false, + "multimodalToolUse": true + } + }, "gemini-3.1-pro-preview": { "tier": "pro", "family": "gemini-3", @@ -1538,7 +1707,7 @@ "tier": "auto", "isPreview": true, "isVisible": true, - "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-3.1-pro, gemini-3-flash", + "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash", "features": { "thinking": true, "multimodalToolUse": false @@ -1564,8 +1733,41 @@ "modelIdResolutions": { "title": "Model ID Resolutions", "description": "Rules for resolving requested model names to concrete model IDs based on context.", - "markdownDescription": "Rules for resolving requested model names to concrete model IDs based on context.\n\n- Category: `Model`\n- Requires restart: `yes`\n- Default: `{\n \"gemini-3-pro-preview\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto-gemini-3\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"pro\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto-gemini-2.5\": {\n \"default\": \"gemini-2.5-pro\"\n },\n \"flash\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n }\n ]\n },\n \"flash-lite\": {\n \"default\": \"gemini-2.5-flash-lite\"\n }\n}`", + "markdownDescription": "Rules for resolving requested model names to concrete model IDs based on context.\n\n- Category: `Model`\n- Requires restart: `yes`\n- Default: `{\n \"gemini-3.1-pro-preview\": {\n \"default\": \"gemini-3.1-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n }\n ]\n },\n \"gemini-3.1-pro-preview-customtools\": {\n \"default\": \"gemini-3.1-pro-preview-customtools\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n }\n ]\n },\n \"gemini-3-flash-preview\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n }\n ]\n },\n \"gemini-3-pro-preview\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto-gemini-3\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"pro\": {\n \"default\": \"gemini-3-pro-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-pro\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true,\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\n },\n {\n \"condition\": {\n \"useGemini3_1\": true\n },\n \"target\": \"gemini-3.1-pro-preview\"\n }\n ]\n },\n \"auto-gemini-2.5\": {\n \"default\": \"gemini-2.5-pro\"\n },\n \"flash\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n }\n ]\n },\n \"flash-lite\": {\n \"default\": \"gemini-2.5-flash-lite\"\n }\n}`", "default": { + "gemini-3.1-pro-preview": { + "default": "gemini-3.1-pro-preview", + "contexts": [ + { + "condition": { + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + } + ] + }, + "gemini-3.1-pro-preview-customtools": { + "default": "gemini-3.1-pro-preview-customtools", + "contexts": [ + { + "condition": { + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + } + ] + }, + "gemini-3-flash-preview": { + "default": "gemini-3-flash-preview", + "contexts": [ + { + "condition": { + "hasAccessToPreview": false + }, + "target": "gemini-2.5-flash" + } + ] + }, "gemini-3-pro-preview": { "default": "gemini-3-pro-preview", "contexts": [ @@ -1736,6 +1938,131 @@ "additionalProperties": { "$ref": "#/$defs/ModelResolution" } + }, + "modelChains": { + "title": "Model Chains", + "description": "Availability policy chains defining fallback behavior for models.", + "markdownDescription": "Availability policy chains defining fallback behavior for models.\n\n- Category: `Model`\n- Requires restart: `yes`\n- Default: `{\n \"preview\": [\n {\n \"model\": \"gemini-3-pro-preview\",\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"prompt\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-3-flash-preview\",\n \"isLastResort\": true,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"prompt\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n }\n ],\n \"default\": [\n {\n \"model\": \"gemini-2.5-pro\",\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"prompt\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"isLastResort\": true,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"prompt\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n }\n ],\n \"lite\": [\n {\n \"model\": \"gemini-2.5-flash-lite\",\n \"actions\": {\n \"terminal\": \"silent\",\n \"transient\": \"silent\",\n \"not_found\": \"silent\",\n \"unknown\": \"silent\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"actions\": {\n \"terminal\": \"silent\",\n \"transient\": \"silent\",\n \"not_found\": \"silent\",\n \"unknown\": \"silent\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-pro\",\n \"isLastResort\": true,\n \"actions\": {\n \"terminal\": \"silent\",\n \"transient\": \"silent\",\n \"not_found\": \"silent\",\n \"unknown\": \"silent\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"terminal\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n }\n ]\n}`", + "default": { + "preview": [ + { + "model": "gemini-3-pro-preview", + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-3-flash-preview", + "isLastResort": true, + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + } + ], + "default": [ + { + "model": "gemini-2.5-pro", + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-2.5-flash", + "isLastResort": true, + "actions": { + "terminal": "prompt", + "transient": "prompt", + "not_found": "prompt", + "unknown": "prompt" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + } + ], + "lite": [ + { + "model": "gemini-2.5-flash-lite", + "actions": { + "terminal": "silent", + "transient": "silent", + "not_found": "silent", + "unknown": "silent" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-2.5-flash", + "actions": { + "terminal": "silent", + "transient": "silent", + "not_found": "silent", + "unknown": "silent" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + }, + { + "model": "gemini-2.5-pro", + "isLastResort": true, + "actions": { + "terminal": "silent", + "transient": "silent", + "not_found": "silent", + "unknown": "silent" + }, + "stateTransitions": { + "terminal": "terminal", + "transient": "terminal", + "not_found": "terminal", + "unknown": "terminal" + } + } + ] + }, + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/ModelPolicy" + } } }, "additionalProperties": false @@ -3253,6 +3580,61 @@ } } } + }, + "ModelPolicy": { + "type": "object", + "description": "Defines the policy for a single model in the availability chain.", + "properties": { + "model": { + "type": "string" + }, + "isLastResort": { + "type": "boolean" + }, + "actions": { + "type": "object", + "properties": { + "terminal": { + "type": "string", + "enum": ["silent", "prompt"] + }, + "transient": { + "type": "string", + "enum": ["silent", "prompt"] + }, + "not_found": { + "type": "string", + "enum": ["silent", "prompt"] + }, + "unknown": { + "type": "string", + "enum": ["silent", "prompt"] + } + } + }, + "stateTransitions": { + "type": "object", + "properties": { + "terminal": { + "type": "string", + "enum": ["terminal", "sticky_retry"] + }, + "transient": { + "type": "string", + "enum": ["terminal", "sticky_retry"] + }, + "not_found": { + "type": "string", + "enum": ["terminal", "sticky_retry"] + }, + "unknown": { + "type": "string", + "enum": ["terminal", "sticky_retry"] + } + } + } + }, + "required": ["model"] } } }