diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index 04034c19732..96830bf5851 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -105,9 +105,19 @@ their corresponding top-level category object in your `settings.json` file. #### `general` -- **`general.preferredEditor`** (string): - - **Description:** The preferred editor to open files in. +- **`general.preferredEditor`** (enum): + - **Description:** The preferred editor to open files in. Must be one of the + built-in supported identifiers. Use /editor in the CLI to pick + interactively, or leave unset to use $VISUAL/$EDITOR. - **Default:** `undefined` + - **Values:** `"vscode"`, `"vscodium"`, `"windsurf"`, `"cursor"`, `"zed"`, + `"antigravity"`, `"sublimetext"`, `"lapce"`, `"nova"`, `"bbedit"`, `"vim"`, + `"neovim"`, `"emacs"`, `"hx"`, `"emacsclient"`, `"micro"` + +- **`general.openEditorInNewWindow`** (boolean): + - **Description:** Open VS Code-family editors in a new window when editing + files. + - **Default:** `false` - **`general.vimMode`** (boolean): - **Description:** Enable Vim keybindings @@ -203,6 +213,11 @@ their corresponding top-level category object in your `settings.json` file. chattiness and structured progress reporting. - **Default:** `true` +- **`general.logRagSnippets`** (boolean): + - **Description:** Log full Code Customization (RAG) retrieved snippets to a + local file for debugging. + - **Default:** `false` + #### `output` - **`output.format`** (enum): @@ -545,6 +560,24 @@ their corresponding top-level category object in your `settings.json` file. "model": "gemini-3-flash-preview" } }, + "gemini-3.1-pro-preview": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-pro-preview" + } + }, + "gemini-3.1-pro-preview-customtools": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-pro-preview-customtools" + } + }, + "gemini-3.1-flash-lite-preview": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-flash-lite-preview" + } + }, "gemini-2.5-pro": { "extends": "chat-base-2.5", "modelConfig": { @@ -563,6 +596,18 @@ their corresponding top-level category object in your `settings.json` file. "model": "gemini-2.5-flash-lite" } }, + "gemini-3.1-flash-lite": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-flash-lite" + } + }, + "gemini-3.5-flash": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.5-flash" + } + }, "gemma-4-31b-it": { "extends": "chat-base-3", "modelConfig": { @@ -587,10 +632,16 @@ their corresponding top-level category object in your `settings.json` file. "model": "gemini-3-flash-preview" } }, + "gemini-3.5-flash-base": { + "extends": "base", + "modelConfig": { + "model": "gemini-3.5-flash" + } + }, "classifier": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "maxOutputTokens": 1024, "thinkingConfig": { @@ -602,7 +653,7 @@ their corresponding top-level category object in your `settings.json` file. "prompt-completion": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0.3, "maxOutputTokens": 16000, @@ -615,7 +666,7 @@ their corresponding top-level category object in your `settings.json` file. "fast-ack-helper": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0.2, "maxOutputTokens": 120, @@ -628,7 +679,7 @@ their corresponding top-level category object in your `settings.json` file. "edit-corrector": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "thinkingConfig": { "thinkingBudget": 0 @@ -639,7 +690,7 @@ their corresponding top-level category object in your `settings.json` file. "summarizer-default": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "maxOutputTokens": 2000 } @@ -648,7 +699,7 @@ their corresponding top-level category object in your `settings.json` file. "summarizer-shell": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "maxOutputTokens": 2000 } @@ -725,7 +776,7 @@ their corresponding top-level category object in your `settings.json` file. }, "chat-compression-3.1-flash-lite": { "modelConfig": { - "model": "gemini-3.1-flash-lite-preview" + "model": "gemini-3.1-flash-lite" } }, "chat-compression-2.5-pro": { @@ -779,10 +830,10 @@ their corresponding top-level category object in your `settings.json` file. ```json { - "gemini-3.1-flash-lite-preview": { + "gemini-3.1-flash-lite": { "tier": "flash-lite", "family": "gemini-3", - "isPreview": true, + "isPreview": false, "isVisible": true, "features": { "thinking": false, @@ -829,6 +880,16 @@ their corresponding top-level category object in your `settings.json` file. "multimodalToolUse": true } }, + "gemini-3.5-flash": { + "tier": "flash", + "family": "gemini-3", + "isPreview": false, + "isVisible": true, + "features": { + "thinking": false, + "multimodalToolUse": true + } + }, "gemini-2.5-pro": { "tier": "pro", "family": "gemini-2.5", @@ -882,9 +943,10 @@ their corresponding top-level category object in your `settings.json` file. } }, "auto": { + "displayName": "Auto", "tier": "auto", "isPreview": true, - "isVisible": false, + "isVisible": true, "features": { "thinking": true, "multimodalToolUse": false @@ -918,26 +980,16 @@ their corresponding top-level category object in your `settings.json` file. } }, "auto-gemini-3": { - "displayName": "Auto (Gemini 3)", "tier": "auto", + "family": "gemini-3", "isPreview": true, - "isVisible": true, - "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash", - "features": { - "thinking": true, - "multimodalToolUse": false - } + "isVisible": false }, "auto-gemini-2.5": { - "displayName": "Auto (Gemini 2.5)", "tier": "auto", + "family": "gemini-2.5", "isPreview": false, - "isVisible": true, - "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash", - "features": { - "thinking": false, - "multimodalToolUse": false - } + "isVisible": false } } ``` @@ -990,37 +1042,50 @@ their corresponding top-level category object in your `settings.json` file. "contexts": [ { "condition": { - "hasAccessToPreview": false + "hasAccessToPreview": false, + "useGemini3_5Flash": true + }, + "target": "gemini-3.5-flash" + }, + { + "condition": { + "hasAccessToPreview": false, + "useGemini3_5Flash": false }, "target": "gemini-2.5-flash" } ] }, - "gemini-3-pro-preview": { - "default": "gemini-3-pro-preview", + "gemini-3.5-flash": { + "default": "gemini-3.5-flash", "contexts": [ { "condition": { + "useGemini3_5Flash": false, "hasAccessToPreview": false }, - "target": "gemini-2.5-pro" + "target": "gemini-2.5-flash" }, { "condition": { - "useGemini3_1": true, - "useCustomTools": true + "useGemini3_5Flash": false }, - "target": "gemini-3.1-pro-preview-customtools" - }, + "target": "gemini-3-flash-preview" + } + ] + }, + "gemini-2.5-flash": { + "default": "gemini-2.5-flash", + "contexts": [ { "condition": { - "useGemini3_1": true + "useGemini3_5Flash": true }, - "target": "gemini-3.1-pro-preview" + "target": "gemini-3.5-flash" } ] }, - "auto-gemini-3": { + "gemini-3-pro-preview": { "default": "gemini-3-pro-preview", "contexts": [ { @@ -1092,23 +1157,18 @@ their corresponding top-level category object in your `settings.json` file. } ] }, - "auto-gemini-2.5": { - "default": "gemini-2.5-pro" + "gemini-3.1-flash-lite": { + "default": "gemini-3.1-flash-lite" }, - "gemini-3.1-flash-lite-preview": { - "default": "gemini-3.1-flash-lite-preview", + "flash": { + "default": "gemini-3-flash-preview", "contexts": [ { "condition": { - "useGemini3_1FlashLite": false + "useGemini3_5Flash": true }, - "target": "gemini-2.5-flash-lite" - } - ] - }, - "flash": { - "default": "gemini-3-flash-preview", - "contexts": [ + "target": "gemini-3.5-flash" + }, { "condition": { "hasAccessToPreview": false @@ -1118,15 +1178,34 @@ their corresponding top-level category object in your `settings.json` file. ] }, "flash-lite": { - "default": "gemini-2.5-flash-lite", + "default": "gemini-3.1-flash-lite" + }, + "auto-gemini-3": { + "default": "gemini-3-pro-preview", "contexts": [ { "condition": { - "useGemini3_1FlashLite": true + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + }, + { + "condition": { + "useGemini3_1": true, + "useCustomTools": true + }, + "target": "gemini-3.1-pro-preview-customtools" + }, + { + "condition": { + "useGemini3_1": true }, - "target": "gemini-3.1-flash-lite-preview" + "target": "gemini-3.1-pro-preview" } ] + }, + "auto-gemini-2.5": { + "default": "gemini-2.5-pro" } } ``` @@ -1145,15 +1224,21 @@ their corresponding top-level category object in your `settings.json` file. "contexts": [ { "condition": { - "requestedModels": ["auto-gemini-2.5", "gemini-2.5-pro"] + "useGemini3_5Flash": true + }, + "target": "gemini-3.5-flash" + }, + { + "condition": { + "hasAccessToPreview": false }, "target": "gemini-2.5-flash" }, { "condition": { - "requestedModels": ["auto-gemini-3", "gemini-3-pro-preview"] + "requestedModels": ["gemini-2.5-pro", "auto-gemini-2.5"] }, - "target": "gemini-3-flash-preview" + "target": "gemini-2.5-flash" } ] }, @@ -1162,7 +1247,13 @@ their corresponding top-level category object in your `settings.json` file. "contexts": [ { "condition": { - "requestedModels": ["auto-gemini-2.5", "gemini-2.5-pro"] + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + }, + { + "condition": { + "requestedModels": ["gemini-2.5-pro", "auto-gemini-2.5"] }, "target": "gemini-2.5-pro" }, @@ -1333,7 +1424,7 @@ their corresponding top-level category object in your `settings.json` file. ], "lite": [ { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "actions": { "terminal": "silent", "transient": "silent", @@ -1821,6 +1912,12 @@ their corresponding top-level category object in your `settings.json` file. - **Default:** `false` - **Requires restart:** Yes +- **`experimental.adk.agentSessionSubagentEnabled`** (boolean): + - **Description:** Route subagent invocations through the AgentSession + protocol instead of legacy executors. + - **Default:** `false` + - **Requires restart:** Yes + - **`experimental.enableAgents`** (boolean): - **Description:** Enable local and remote subagents. - **Default:** `true` @@ -1857,13 +1954,6 @@ their corresponding top-level category object in your `settings.json` file. - **Default:** `false` - **Requires restart:** Yes -- **`experimental.jitContext`** (boolean): - - **Description:** Enable Just-In-Time (JIT) context loading. Defaults to - true; set to false to opt out and load all GEMINI.md files into the system - instruction up-front. - - **Default:** `true` - - **Requires restart:** Yes - - **`experimental.useOSC52Paste`** (boolean): - **Description:** Use OSC 52 for pasting. This may be more robust than the default system when using remote terminal sessions (if your terminal is @@ -1926,19 +2016,6 @@ their corresponding top-level category object in your `settings.json` file. - **Default:** `"gemma3-1b-gpu-custom"` - **Requires restart:** Yes -- **`experimental.memoryV2`** (boolean): - - **Description:** Disable the built-in save_memory tool and let the main - agent persist project context by editing markdown files directly with - edit/write_file. Route facts across four tiers: team-shared conventions go - to project GEMINI.md files, project-specific personal notes go to the - per-project private memory folder (MEMORY.md as index + sibling .md files - for detail), and cross-project personal preferences go to the global - ~/.gemini/GEMINI.md (the only file under ~/.gemini/ that the agent can edit - — settings, credentials, etc. remain off-limits). Set to false to fall back - to the legacy save_memory tool. - - **Default:** `true` - - **Requires restart:** Yes - - **`experimental.stressTestProfile`** (boolean): - **Description:** Significantly lowers token limits to force early garbage collection and distillation for testing purposes. @@ -1958,6 +2035,11 @@ their corresponding top-level category object in your `settings.json` file. - **Default:** `false` - **Requires restart:** Yes +- **`experimental.powerUserProfile`** (boolean): + - **Description:** Less cache friendly version of the generalist profile. + - **Default:** `false` + - **Requires restart:** Yes + - **`experimental.contextManagement`** (boolean): - **Description:** Enable logic for context management. - **Default:** `false` diff --git a/evals/llm-judge.ts b/evals/llm-judge.ts index a7490e26265..f830202403d 100644 --- a/evals/llm-judge.ts +++ b/evals/llm-judge.ts @@ -76,10 +76,30 @@ export class LLMJudge { for (const res of rawResults) { // Remove any punctuation the model might have appended - const cleanRes = res.replace(/[^A-Z]/g, ''); - if (cleanRes.startsWith('YES')) yes++; - else if (cleanRes.startsWith('NO')) no++; - else other++; + const cleanRes = res.replace(/[^A-Z ]/g, ''); + if ( + cleanRes.includes('THE ANSWER IS YES') || + cleanRes.includes('ANSWER IS YES') || + cleanRes.endsWith('YES') + ) { + yes++; + } else if ( + cleanRes.includes('THE ANSWER IS NO') || + cleanRes.includes('ANSWER IS NO') || + cleanRes.endsWith('NO') + ) { + no++; + } else if (cleanRes.trim() === 'YES') { + yes++; + } else if (cleanRes.trim() === 'NO') { + no++; + } else { + // Fallback: look for YES or NO as standalone words or at the end + const words = cleanRes.split(/\s+/); + if (words.includes('YES')) yes++; + else if (words.includes('NO')) no++; + else other++; + } } // Pass if YES > NO and YES > OTHER (plurality) diff --git a/packages/cli/src/acp/acpSessionManager.test.ts b/packages/cli/src/acp/acpSessionManager.test.ts index 81a556a9527..03673cdf234 100644 --- a/packages/cli/src/acp/acpSessionManager.test.ts +++ b/packages/cli/src/acp/acpSessionManager.test.ts @@ -215,13 +215,12 @@ describe('AcpSessionManager', () => { ); }); - it('should include gemini-3.1-flash-lite when useGemini31FlashLite is true', async () => { + it('should NOT include retired preview models (none) in available models', async () => { mockConfig.getContentGeneratorConfig = vi.fn().mockReturnValue({ apiKey: 'test-key', }); mockConfig.getHasAccessToPreviewModel = vi.fn().mockReturnValue(true); mockConfig.getGemini31LaunchedSync = vi.fn().mockReturnValue(true); - mockConfig.getGemini31FlashLiteLaunchedSync = vi.fn().mockReturnValue(true); const response = await manager.newSession( { @@ -231,14 +230,9 @@ describe('AcpSessionManager', () => { {}, ); - expect(response.models?.availableModels).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - modelId: 'gemini-3.1-flash-lite-preview', - name: 'gemini-3.1-flash-lite-preview', - }), - ]), - ); + const modelIds = + response.models?.availableModels?.map((m) => m.modelId) ?? []; + expect(modelIds).not.toContain('none'); }); it('should return modes with plan mode when plan is enabled', async () => { diff --git a/packages/cli/src/acp/acpUtils.ts b/packages/cli/src/acp/acpUtils.ts index 403227628e5..ea5e160f54a 100644 --- a/packages/cli/src/acp/acpUtils.ts +++ b/packages/cli/src/acp/acpUtils.ts @@ -10,8 +10,7 @@ import { type ToolCallConfirmationDetails, Kind, ApprovalMode, - DEFAULT_GEMINI_MODEL_AUTO, - PREVIEW_GEMINI_MODEL_AUTO, + GEMINI_MODEL_ALIAS_AUTO, DEFAULT_GEMINI_MODEL, DEFAULT_GEMINI_FLASH_MODEL, DEFAULT_GEMINI_FLASH_LITE_MODEL, @@ -19,10 +18,11 @@ import { PREVIEW_GEMINI_MODEL, PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, PREVIEW_GEMINI_FLASH_MODEL, - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, + PREVIEW_GEMINI_FLASH_LITE_MODEL, getDisplayString, AuthType, ToolConfirmationOutcome, + getAutoModelDescription, } from '@google/gemini-cli-core'; import type * as acp from '@agentclientprotocol/sdk'; import { z } from 'zod'; @@ -262,11 +262,10 @@ export function buildAvailableModels( }>; currentModelId: string; } { - const preferredModel = config.getModel() || DEFAULT_GEMINI_MODEL_AUTO; + const preferredModel = config.getModel() || GEMINI_MODEL_ALIAS_AUTO; const shouldShowPreviewModels = config.getHasAccessToPreviewModel(); const useGemini31 = config.getGemini31LaunchedSync?.() ?? false; - const useGemini31FlashLite = - config.getGemini31FlashLiteLaunchedSync?.() ?? false; + const useGemini3_5Flash = config.hasGemini35FlashGAAccess?.() ?? false; const selectedAuthType = settings.merged.security.auth.selectedType; const useCustomToolModel = useGemini31 && selectedAuthType === AuthType.USE_GEMINI; @@ -278,7 +277,7 @@ export function buildAvailableModels( ) { const options = config.getModelConfigService().getAvailableModelOptions({ useGemini3_1: useGemini31, - useGemini3_1FlashLite: useGemini31FlashLite, + useGemini3_5Flash, useCustomTools: useCustomToolModel, hasAccessToPreview: shouldShowPreviewModels, }); @@ -292,23 +291,16 @@ export function buildAvailableModels( // --- LEGACY PATH --- const mainOptions = [ { - value: DEFAULT_GEMINI_MODEL_AUTO, - title: getDisplayString(DEFAULT_GEMINI_MODEL_AUTO), - description: - 'Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash', + value: GEMINI_MODEL_ALIAS_AUTO, + title: getDisplayString(GEMINI_MODEL_ALIAS_AUTO), + description: getAutoModelDescription( + shouldShowPreviewModels, + useGemini31, + useGemini3_5Flash, + ), }, ]; - if (shouldShowPreviewModels) { - mainOptions.unshift({ - value: PREVIEW_GEMINI_MODEL_AUTO, - title: getDisplayString(PREVIEW_GEMINI_MODEL_AUTO), - description: useGemini31 - ? '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', - }); - } - const manualOptions = [ { value: DEFAULT_GEMINI_MODEL, @@ -344,10 +336,10 @@ export function buildAvailableModels( }, ]; - if (useGemini31FlashLite) { + if (PREVIEW_GEMINI_FLASH_LITE_MODEL !== 'none') { previewOptions.push({ - value: PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, - title: getDisplayString(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL), + value: PREVIEW_GEMINI_FLASH_LITE_MODEL, + title: getDisplayString(PREVIEW_GEMINI_FLASH_LITE_MODEL), }); } diff --git a/packages/cli/src/ui/components/ModelDialog.test.tsx b/packages/cli/src/ui/components/ModelDialog.test.tsx index c313e53a983..f694d7174b2 100644 --- a/packages/cli/src/ui/components/ModelDialog.test.tsx +++ b/packages/cli/src/ui/components/ModelDialog.test.tsx @@ -12,14 +12,14 @@ import { waitFor } from '../../test-utils/async.js'; import { createMockSettings } from '../../test-utils/settings.js'; import { DEFAULT_GEMINI_MODEL, - DEFAULT_GEMINI_MODEL_AUTO, + GEMINI_MODEL_ALIAS_AUTO, DEFAULT_GEMINI_FLASH_MODEL, DEFAULT_GEMINI_FLASH_LITE_MODEL, PREVIEW_GEMINI_MODEL, PREVIEW_GEMINI_3_1_MODEL, PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, PREVIEW_GEMINI_FLASH_MODEL, - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, + PREVIEW_GEMINI_FLASH_LITE_MODEL, AuthType, } from '@google/gemini-cli-core'; import type { Config, ModelSlashCommandEvent } from '@google/gemini-cli-core'; @@ -34,6 +34,11 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => { await importOriginal(); return { ...actual, + getAutoModelDescription: ( + hasAccessToPreview: boolean, + useGemini3_1?: boolean, + ) => + `Auto Model Description (preview: ${hasAccessToPreview}, 3.1: ${useGemini3_1})`, getDisplayString: (val: string) => mockGetDisplayString(val), logModelSlashCommand: (config: Config, event: ModelSlashCommandEvent) => mockLogModelSlashCommand(config, event), @@ -42,7 +47,7 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => { mockModelSlashCommandEvent(model); } }, - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL: 'gemini-3.1-flash-lite-preview', + PREVIEW_GEMINI_FLASH_LITE_MODEL: 'none', }; }); @@ -62,7 +67,6 @@ describe('', () => { getHasAccessToPreviewModel: () => boolean; getIdeMode: () => boolean; getGemini31LaunchedSync: () => boolean; - getGemini31FlashLiteLaunchedSync: () => boolean; getProModelNoAccess: () => Promise; getProModelNoAccessSync: () => boolean; getExperimentalGemma: () => boolean; @@ -83,7 +87,6 @@ describe('', () => { getHasAccessToPreviewModel: mockGetHasAccessToPreviewModel, getIdeMode: () => false, getGemini31LaunchedSync: mockGetGemini31LaunchedSync, - getGemini31FlashLiteLaunchedSync: mockGetGemini31FlashLiteLaunchedSync, getProModelNoAccess: mockGetProModelNoAccess, getProModelNoAccessSync: mockGetProModelNoAccessSync, getExperimentalGemma: () => false, @@ -93,17 +96,15 @@ describe('', () => { beforeEach(() => { vi.resetAllMocks(); - mockGetModel.mockReturnValue(DEFAULT_GEMINI_MODEL_AUTO); + mockGetModel.mockReturnValue(GEMINI_MODEL_ALIAS_AUTO); mockGetHasAccessToPreviewModel.mockReturnValue(false); mockGetGemini31LaunchedSync.mockReturnValue(false); - mockGetGemini31FlashLiteLaunchedSync.mockReturnValue(false); mockGetProModelNoAccess.mockResolvedValue(false); mockGetProModelNoAccessSync.mockReturnValue(false); // Default implementation for getDisplayString mockGetDisplayString.mockImplementation((val: string) => { - if (val === 'auto-gemini-2.5') return 'Auto (Gemini 2.5)'; - if (val === 'auto-gemini-3') return 'Auto (Preview)'; + if (val === 'auto') return 'Auto'; return val; }); }); @@ -153,17 +154,13 @@ describe('', () => { expect(output).not.toContain(DEFAULT_GEMINI_MODEL); expect(output).not.toContain(PREVIEW_GEMINI_MODEL); - // Verify order: Flash Preview -> Flash Lite Preview -> Flash -> Flash Lite + // Verify order: Flash Preview -> Flash Lite (Preview/Default) -> Flash const flashPreviewIdx = output.indexOf(PREVIEW_GEMINI_FLASH_MODEL); - const flashLitePreviewIdx = output.indexOf( - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, - ); - const flashIdx = output.indexOf(DEFAULT_GEMINI_FLASH_MODEL); const flashLiteIdx = output.indexOf(DEFAULT_GEMINI_FLASH_LITE_MODEL); + const flashIdx = output.indexOf(DEFAULT_GEMINI_FLASH_MODEL); - expect(flashPreviewIdx).toBeLessThan(flashLitePreviewIdx); - expect(flashLitePreviewIdx).toBeLessThan(flashIdx); - expect(flashIdx).toBeLessThan(flashLiteIdx); + expect(flashPreviewIdx).toBeLessThan(flashLiteIdx); + expect(flashLiteIdx).toBeLessThan(flashIdx); expect(output).not.toContain('Auto'); unmount(); @@ -234,7 +231,7 @@ describe('', () => { await waitFor(() => { expect(mockSetModel).toHaveBeenCalledWith( - DEFAULT_GEMINI_MODEL_AUTO, + GEMINI_MODEL_ALIAS_AUTO, true, // Session only by default ); expect(mockOnClose).toHaveBeenCalled(); @@ -292,7 +289,7 @@ describe('', () => { await waitFor(() => { expect(mockSetModel).toHaveBeenCalledWith( - DEFAULT_GEMINI_MODEL_AUTO, + GEMINI_MODEL_ALIAS_AUTO, false, // Persist enabled ); expect(mockOnClose).toHaveBeenCalled(); @@ -355,7 +352,7 @@ describe('', () => { mockGetModel.mockReturnValue(DEFAULT_GEMINI_MODEL); mockGetDisplayString.mockImplementation((val: string) => { if (val === DEFAULT_GEMINI_MODEL) return 'My Custom Model Display'; - if (val === 'auto-gemini-2.5') return 'Auto (Gemini 2.5)'; + if (val === 'auto') return 'Auto'; return val; }); const { lastFrame, unmount } = await renderComponent(); @@ -369,9 +366,9 @@ describe('', () => { mockGetHasAccessToPreviewModel.mockReturnValue(true); }); - it('shows Auto (Preview) in main view when access is granted', async () => { + it('shows Auto in main view when access is granted', async () => { const { lastFrame, unmount } = await renderComponent(); - expect(lastFrame()).toContain('Auto (Preview)'); + expect(lastFrame()).toContain('Auto'); unmount(); }); @@ -449,7 +446,7 @@ describe('', () => { unmount(); }); - it('shows Flash Lite Preview model regardless of tier when flag is enabled', async () => { + it('does not show Flash Lite Preview model when it is retired (none) even if flag is enabled', async () => { mockGetProModelNoAccessSync.mockReturnValue(false); mockGetProModelNoAccess.mockResolvedValue(false); mockGetHasAccessToPreviewModel.mockReturnValue(true); @@ -468,7 +465,8 @@ describe('', () => { await waitUntilReady(); const output = lastFrame(); - expect(output).toContain(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL); + expect(output).not.toContain(PREVIEW_GEMINI_FLASH_LITE_MODEL); + expect(output).toContain(DEFAULT_GEMINI_FLASH_LITE_MODEL); unmount(); }); }); diff --git a/packages/cli/src/ui/components/ModelDialog.tsx b/packages/cli/src/ui/components/ModelDialog.tsx index e65811690ad..e5db594684b 100644 --- a/packages/cli/src/ui/components/ModelDialog.tsx +++ b/packages/cli/src/ui/components/ModelDialog.tsx @@ -13,12 +13,11 @@ import { PREVIEW_GEMINI_MODEL, PREVIEW_GEMINI_3_1_MODEL, PREVIEW_GEMINI_FLASH_MODEL, - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, - PREVIEW_GEMINI_MODEL_AUTO, + PREVIEW_GEMINI_FLASH_LITE_MODEL, DEFAULT_GEMINI_MODEL, DEFAULT_GEMINI_FLASH_MODEL, DEFAULT_GEMINI_FLASH_LITE_MODEL, - DEFAULT_GEMINI_MODEL_AUTO, + GEMINI_MODEL_ALIAS_AUTO, GEMMA_4_31B_IT_MODEL, GEMMA_4_26B_A4B_IT_MODEL, ModelSlashCommandEvent, @@ -27,6 +26,7 @@ import { AuthType, PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, isProModel, + getAutoModelDescription, } from '@google/gemini-cli-core'; import { useKeypress } from '../hooks/useKeypress.js'; import { theme } from '../semantic-colors.js'; @@ -63,12 +63,11 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { }, [config]); // Determine the Preferred Model (read once when the dialog opens). - const preferredModel = config?.getModel() || DEFAULT_GEMINI_MODEL_AUTO; + const preferredModel = config?.getModel() || GEMINI_MODEL_ALIAS_AUTO; - const shouldShowPreviewModels = config?.getHasAccessToPreviewModel(); + const shouldShowPreviewModels = config?.getHasAccessToPreviewModel() ?? false; const useGemini31 = config?.getGemini31LaunchedSync?.() ?? false; - const useGemini31FlashLite = - config?.getGemini31FlashLiteLaunchedSync?.() ?? false; + const useGemini3_5Flash = config?.hasGemini35FlashGAAccess?.() ?? false; const selectedAuthType = settings.merged.security.auth.selectedType; const useCustomToolModel = useGemini31 && selectedAuthType === AuthType.USE_GEMINI; @@ -94,9 +93,9 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { PREVIEW_GEMINI_MODEL, PREVIEW_GEMINI_3_1_MODEL, PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, + PREVIEW_GEMINI_FLASH_LITE_MODEL, PREVIEW_GEMINI_FLASH_MODEL, - ]; + ].filter((m) => m !== 'none'); if (manualModels.includes(preferredModel)) { return preferredModel; } @@ -121,7 +120,6 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { }, { isActive: true }, ); - const mainOptions = useMemo(() => { // --- DYNAMIC PATH --- if ( @@ -132,7 +130,7 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { .getModelConfigService() .getAvailableModelOptions({ useGemini3_1: useGemini31, - useGemini3_1FlashLite: useGemini31FlashLite, + useGemini3_5Flash, useCustomTools: useCustomToolModel, hasAccessToPreview: shouldShowPreviewModels, hasAccessToProModel, @@ -161,11 +159,14 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { // --- LEGACY PATH --- const list = [ { - value: DEFAULT_GEMINI_MODEL_AUTO, - title: getDisplayString(DEFAULT_GEMINI_MODEL_AUTO), - description: - 'Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash', - key: DEFAULT_GEMINI_MODEL_AUTO, + value: GEMINI_MODEL_ALIAS_AUTO, + title: getDisplayString(GEMINI_MODEL_ALIAS_AUTO), + description: getAutoModelDescription( + shouldShowPreviewModels, + useGemini31, + useGemini3_5Flash, + ), + key: GEMINI_MODEL_ALIAS_AUTO, }, { value: 'Manual', @@ -177,23 +178,13 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { }, ]; - if (shouldShowPreviewModels) { - list.unshift({ - value: PREVIEW_GEMINI_MODEL_AUTO, - title: getDisplayString(PREVIEW_GEMINI_MODEL_AUTO), - description: useGemini31 - ? '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', - key: PREVIEW_GEMINI_MODEL_AUTO, - }); - } return list; }, [ config, shouldShowPreviewModels, manualModelSelected, useGemini31, - useGemini31FlashLite, + useGemini3_5Flash, useCustomToolModel, hasAccessToProModel, ]); @@ -208,7 +199,7 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { .getModelConfigService() .getAvailableModelOptions({ useGemini3_1: useGemini31, - useGemini3_1FlashLite: useGemini31FlashLite, + useGemini3_5Flash, useCustomTools: useCustomToolModel, hasAccessToPreview: shouldShowPreviewModels, hasAccessToProModel, @@ -232,16 +223,16 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { title: getDisplayString(DEFAULT_GEMINI_MODEL), key: DEFAULT_GEMINI_MODEL, }, - { - value: DEFAULT_GEMINI_FLASH_MODEL, - title: getDisplayString(DEFAULT_GEMINI_FLASH_MODEL), - key: DEFAULT_GEMINI_FLASH_MODEL, - }, { value: DEFAULT_GEMINI_FLASH_LITE_MODEL, title: getDisplayString(DEFAULT_GEMINI_FLASH_LITE_MODEL), key: DEFAULT_GEMINI_FLASH_LITE_MODEL, }, + { + value: DEFAULT_GEMINI_FLASH_MODEL, + title: getDisplayString(DEFAULT_GEMINI_FLASH_MODEL), + key: DEFAULT_GEMINI_FLASH_MODEL, + }, ]; if (showGemmaModels) { @@ -281,11 +272,11 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { }, ]; - if (useGemini31FlashLite) { + if (PREVIEW_GEMINI_FLASH_LITE_MODEL !== 'none') { previewOptions.push({ - value: PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, - title: getDisplayString(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL), - key: PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, + value: PREVIEW_GEMINI_FLASH_LITE_MODEL, + title: getDisplayString(PREVIEW_GEMINI_FLASH_LITE_MODEL), + key: PREVIEW_GEMINI_FLASH_LITE_MODEL, }); } @@ -301,13 +292,23 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element { }, [ shouldShowPreviewModels, useGemini31, - useGemini31FlashLite, + useGemini3_5Flash, useCustomToolModel, hasAccessToProModel, config, ]); - const options = view === 'main' ? mainOptions : manualOptions; + const options = useMemo(() => { + const rawOptions = view === 'main' ? mainOptions : manualOptions; + const seen = new Set(); + return rawOptions.filter((option) => { + if (seen.has(option.value)) { + return false; + } + seen.add(option.value); + return true; + }); + }, [view, mainOptions, manualOptions]); // Calculate the initial index based on the preferred model. const initialIndex = useMemo(() => { diff --git a/packages/cli/src/ui/components/ModelStatsDisplay.test.tsx b/packages/cli/src/ui/components/ModelStatsDisplay.test.tsx index f71eb72266a..dce6c604b0c 100644 --- a/packages/cli/src/ui/components/ModelStatsDisplay.test.tsx +++ b/packages/cli/src/ui/components/ModelStatsDisplay.test.tsx @@ -353,6 +353,49 @@ describe('', () => { unmount(); }); + it('should resolve gemini-3-flash to gemini-3.5-flash via getDisplayString', async () => { + const { lastFrame, unmount } = await renderWithMockedStats({ + models: { + 'gemini-3-flash': { + api: { totalRequests: 1, totalErrors: 0, totalLatencyMs: 100 }, + tokens: { + input: 5, + prompt: 10, + candidates: 20, + total: 30, + cached: 5, + thoughts: 2, + tool: 1, + }, + roles: {}, + }, + }, + tools: { + totalCalls: 0, + totalSuccess: 0, + totalFail: 0, + totalDurationMs: 0, + totalDecisions: { + accept: 0, + reject: 0, + modify: 0, + [ToolCallDecision.AUTO_ACCEPT]: 0, + }, + byName: {}, + }, + files: { + totalLinesAdded: 0, + totalLinesRemoved: 0, + }, + }); + + const output = lastFrame(); + expect(output).toContain('gemini-3.5-flash'); + expect(output).not.toContain('gemini-3-flash'); + expect(output).toMatchSnapshot(); + unmount(); + }); + it('should handle models with long names (gemini-3-*-preview) without layout breaking', async () => { const { lastFrame, unmount } = await renderWithMockedStats( { diff --git a/packages/cli/src/ui/components/ModelStatsDisplay.tsx b/packages/cli/src/ui/components/ModelStatsDisplay.tsx index 0c6ae45e8c2..f4e739e6d87 100644 --- a/packages/cli/src/ui/components/ModelStatsDisplay.tsx +++ b/packages/cli/src/ui/components/ModelStatsDisplay.tsx @@ -299,7 +299,7 @@ export const ModelStatsDisplay: React.FC = ({ }, ...modelNames.map((name) => ({ key: name, - header: name, + header: getDisplayString(name), flexGrow: 1, renderCell: (row: StatRowData) => { // Don't render anything for section headers in model columns diff --git a/packages/cli/src/ui/components/SessionBrowser/__snapshots__/SessionBrowserSearchNav.test.tsx.snap b/packages/cli/src/ui/components/SessionBrowser/__snapshots__/SessionBrowserSearchNav.test.tsx.snap index c5ed5e54548..110490fb26c 100644 --- a/packages/cli/src/ui/components/SessionBrowser/__snapshots__/SessionBrowserSearchNav.test.tsx.snap +++ b/packages/cli/src/ui/components/SessionBrowser/__snapshots__/SessionBrowserSearchNav.test.tsx.snap @@ -6,6 +6,12 @@ Sort: s Reverse: r First/Last: g/G " `; +exports[`SessionBrowser Search and Navigation Components > NavigationHelp renders correctly 2`] = ` +"Navigate: ↑/↓ Resume: Enter Search: / Delete: x Quit: q +Sort: s Reverse: r First/Last: g/G +" +`; + exports[`SessionBrowser Search and Navigation Components > NoResultsDisplay renders correctly 1`] = ` " No sessions found matching 'no match'. diff --git a/packages/cli/src/ui/components/SessionBrowser/__snapshots__/SessionBrowserStates.test.tsx.snap b/packages/cli/src/ui/components/SessionBrowser/__snapshots__/SessionBrowserStates.test.tsx.snap index e5939219cb0..1b062e73b6d 100644 --- a/packages/cli/src/ui/components/SessionBrowser/__snapshots__/SessionBrowserStates.test.tsx.snap +++ b/packages/cli/src/ui/components/SessionBrowser/__snapshots__/SessionBrowserStates.test.tsx.snap @@ -6,6 +6,12 @@ exports[`SessionBrowser UI States > SessionBrowserEmpty renders correctly 1`] = " `; +exports[`SessionBrowser UI States > SessionBrowserEmpty renders correctly 2`] = ` +" No auto-saved conversations found. + Press q to exit +" +`; + exports[`SessionBrowser UI States > SessionBrowserError renders correctly 1`] = ` " Error: Test error message Press q to exit diff --git a/packages/cli/src/ui/components/StatsDisplay.test.tsx b/packages/cli/src/ui/components/StatsDisplay.test.tsx index cd98ed400dc..b0d25773379 100644 --- a/packages/cli/src/ui/components/StatsDisplay.test.tsx +++ b/packages/cli/src/ui/components/StatsDisplay.test.tsx @@ -131,6 +131,33 @@ describe('', () => { expect(output).toMatchSnapshot(); }); + it('resolves gemini-3-flash to gemini-3.5-flash in the model usage table', async () => { + const metrics = createTestMetrics({ + models: { + 'gemini-3-flash': { + api: { totalRequests: 5, totalErrors: 0, totalLatencyMs: 3000 }, + tokens: { + input: 1000, + prompt: 2000, + candidates: 3000, + total: 5000, + cached: 500, + thoughts: 100, + tool: 50, + }, + roles: {}, + }, + }, + }); + + const { lastFrame } = await renderWithMockedStats(metrics); + const output = lastFrame(); + + expect(output).toContain('gemini-3.5-flash'); + expect(output).not.toContain('gemini-3-flash\u0020'); // Avoid matching parts of substrings if not intended + expect(output).toMatchSnapshot(); + }); + it('renders role breakdown correctly under models', async () => { const metrics = createTestMetrics({ models: { diff --git a/packages/cli/src/ui/components/StatsDisplay.tsx b/packages/cli/src/ui/components/StatsDisplay.tsx index 233e9f3ed45..1d2e2e437ce 100644 --- a/packages/cli/src/ui/components/StatsDisplay.tsx +++ b/packages/cli/src/ui/components/StatsDisplay.tsx @@ -24,7 +24,7 @@ import { import { computeSessionStats } from '../utils/computeStats.js'; import { useSettings } from '../contexts/SettingsContext.js'; import type { QuotaStats } from '../types.js'; -import { LlmRole } from '@google/gemini-cli-core'; +import { LlmRole, getDisplayString } from '@google/gemini-cli-core'; // A more flexible and powerful StatRow component interface StatRowProps { @@ -101,7 +101,7 @@ const ModelUsageTable: React.FC = ({ models }) => { Object.entries(models).forEach(([name, metrics]) => { rows.push({ name, - displayName: name, + displayName: getDisplayString(name), requests: metrics.api.totalRequests, cachedTokens: metrics.tokens.cached.toLocaleString(), inputTokens: metrics.tokens.prompt.toLocaleString(), diff --git a/packages/cli/src/ui/components/__snapshots__/AlternateBufferQuittingDisplay.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/AlternateBufferQuittingDisplay.test.tsx.snap index 26a8b0a8e75..f335f3d640d 100644 --- a/packages/cli/src/ui/components/__snapshots__/AlternateBufferQuittingDisplay.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/AlternateBufferQuittingDisplay.test.tsx.snap @@ -84,6 +84,33 @@ exports[`AlternateBufferQuittingDisplay > renders with history but no pending it +Tips for getting started: +1. Create GEMINI.md files to customize your interactions +2. /help for more information +3. Ask coding questions, edit code or run commands +4. Be specific for the best results +╭──────────────────────────────────────────────────────────────────────────╮ +│ ✓ tool1 Description for tool 1 │ +│ │ +╰──────────────────────────────────────────────────────────────────────────╯ +╭──────────────────────────────────────────────────────────────────────────╮ +│ ✓ tool2 Description for tool 2 │ +│ │ +╰──────────────────────────────────────────────────────────────────────────╯ +" +`; + +exports[`AlternateBufferQuittingDisplay > renders with pending items but no history > with_history_no_pending 1`] = ` +" + ▝▜▄ ▗█▀▀▜▙▝█▛▀▀▌▜██▖▟██▘▜█▘▜██▖▝█▛▝█▛ + ▝▜▄ █▌ █▙▟ ▐█▝█▛▐█ ▐█ ▐█▝█▖█▌ █▌ + ▗▟▀ ▜▙ ▝█▛ █▌▝ ▖▐█ ▐█ ▐█ ▐█ ▝██▌ █▌ + ▝▀ ▀▀▀▀▘▝▀▀▀▀▘▀▀▘ ▀▀▘▀▀▘▀▀▘ ▝▀▀▝▀▀ + + Gemini CLI v0.10.0 + + + Tips for getting started: 1. Create GEMINI.md files to customize your interactions 2. /help for more information @@ -123,6 +150,29 @@ Tips for getting started: " `; +exports[`AlternateBufferQuittingDisplay > renders with user and gemini messages > with_confirming_tool 1`] = ` +" + ▝▜▄ ▗█▀▀▜▙▝█▛▀▀▌▜██▖▟██▘▜█▘▜██▖▝█▛▝█▛ + ▝▜▄ █▌ █▙▟ ▐█▝█▛▐█ ▐█ ▐█▝█▖█▌ █▌ + ▗▟▀ ▜▙ ▝█▛ █▌▝ ▖▐█ ▐█ ▐█ ▐█ ▝██▌ █▌ + ▝▀ ▀▀▀▀▘▝▀▀▀▀▘▀▀▘ ▀▀▘▀▀▘▀▀▘ ▝▀▀▝▀▀ + + Gemini CLI v0.10.0 + + + +Tips for getting started: +1. Create GEMINI.md files to customize your interactions +2. /help for more information +3. Ask coding questions, edit code or run commands +4. Be specific for the best results + +Action Required (was prompted): + +? confirming_tool Confirming tool description +" +`; + exports[`AlternateBufferQuittingDisplay > renders with user and gemini messages > with_user_gemini_messages 1`] = ` " ▝▜▄ ▗█▀▀▜▙▝█▛▀▀▌▜██▖▟██▘▜█▘▜██▖▝█▛▝█▛ diff --git a/packages/cli/src/ui/components/__snapshots__/Banner-Banner-handles-newlines-in-text-2.snap.svg b/packages/cli/src/ui/components/__snapshots__/Banner-Banner-handles-newlines-in-text-2.snap.svg new file mode 100644 index 00000000000..a6272e0fa90 --- /dev/null +++ b/packages/cli/src/ui/components/__snapshots__/Banner-Banner-handles-newlines-in-text-2.snap.svg @@ -0,0 +1,20 @@ + + + + + ╭──────────────────────────────────────────────────────────────────────────────╮ + + L + i + n + e + 1 + + + Line 2 + + ╰──────────────────────────────────────────────────────────────────────────────╯ + + \ No newline at end of file diff --git a/packages/cli/src/ui/components/__snapshots__/Banner.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/Banner.test.tsx.snap index 6df246dede9..84e54366a47 100644 --- a/packages/cli/src/ui/components/__snapshots__/Banner.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/Banner.test.tsx.snap @@ -7,6 +7,13 @@ exports[`Banner > handles newlines in text 1`] = ` ╰──────────────────────────────────────────────────────────────────────────────╯" `; +exports[`Banner > handles newlines in text 2`] = ` +"╭──────────────────────────────────────────────────────────────────────────────╮ +│ Line 1 │ +│ Line 2 │ +╰──────────────────────────────────────────────────────────────────────────────╯" +`; + exports[`Banner > renders in info mode 1`] = ` "╭──────────────────────────────────────────────────────────────────────────────╮ │ Info Message │ diff --git a/packages/cli/src/ui/components/__snapshots__/Checklist.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/Checklist.test.tsx.snap index 94dff26bb2d..d7553195419 100644 --- a/packages/cli/src/ui/components/__snapshots__/Checklist.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/Checklist.test.tsx.snap @@ -11,6 +11,17 @@ exports[` > renders expanded view correctly 1`] = ` " `; +exports[` > renders expanded view correctly 2`] = ` +"──────────────────────────────────────────────────────────────────────────────────────────────────── + Test List 1/3 completed (toggle me) + + ✓ Task 1 + » Task 2 + ☐ Task 3 + ✗ Task 4 +" +`; + exports[` > renders summary view correctly (collapsed) 1`] = ` "──────────────────────────────────────────────────────────────────────────────────────────────────── Test List 1/3 completed (toggle me) » Task 2 diff --git a/packages/cli/src/ui/components/__snapshots__/ContextSummaryDisplay.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ContextSummaryDisplay.test.tsx.snap index 7330b89e4d0..1b4085504eb 100644 --- a/packages/cli/src/ui/components/__snapshots__/ContextSummaryDisplay.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/ContextSummaryDisplay.test.tsx.snap @@ -5,6 +5,11 @@ exports[` > should not render empty parts 1`] = ` " `; +exports[` > should not render empty parts 2`] = ` +" 1 open file (F4 to view) +" +`; + exports[` > should render on a single line on a wide screen 1`] = ` " 1 open file (F4 to view) · 1 GEMINI.md file · 1 MCP server · 1 skill " diff --git a/packages/cli/src/ui/components/__snapshots__/LoopDetectionConfirmation.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/LoopDetectionConfirmation.test.tsx.snap index e8914dceeb1..a36c321f09e 100644 --- a/packages/cli/src/ui/components/__snapshots__/LoopDetectionConfirmation.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/LoopDetectionConfirmation.test.tsx.snap @@ -1,5 +1,18 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`LoopDetectionConfirmation > contains the expected options 1`] = ` +" ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ ? A potential loop was detected │ + │ │ + │ This can happen due to repetitive tool calls or other model behavior. Do you want to keep loop │ + │ detection enabled or disable it for this session? │ + │ │ + │ ● 1. Keep loop detection enabled (esc) │ + │ 2. Disable loop detection for this session │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ +" +`; + exports[`LoopDetectionConfirmation > renders correctly 1`] = ` " ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ? A potential loop was detected │ diff --git a/packages/cli/src/ui/components/__snapshots__/ModelStatsDisplay.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ModelStatsDisplay.test.tsx.snap index 841c830a846..6830e10c2ab 100644 --- a/packages/cli/src/ui/components/__snapshots__/ModelStatsDisplay.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/ModelStatsDisplay.test.tsx.snap @@ -215,3 +215,26 @@ exports[` > should render "no API calls" message when there ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ " `; + +exports[` > should resolve gemini-3-flash to gemini-3.5-flash via getDisplayString 1`] = ` +"╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ │ +│ Model Stats For Nerds │ +│ │ +│ │ +│ Metric gemini-3.5-flash │ +│ ────────────────────────────────────────────────────────────────────────────────────────────── │ +│ API │ +│ Requests 1 │ +│ Errors 0 (0.0%) │ +│ Avg Latency 100ms │ +│ Tokens │ +│ Total 30 │ +│ ↳ Input 5 │ +│ ↳ Cache Reads 5 (50.0%) │ +│ ↳ Thoughts 2 │ +│ ↳ Tool 1 │ +│ ↳ Output 20 │ +╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ +" +`; diff --git a/packages/cli/src/ui/components/__snapshots__/ShortcutsHelp.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ShortcutsHelp.test.tsx.snap index f51dca08608..dd0f0b66fe5 100644 --- a/packages/cli/src/ui/components/__snapshots__/ShortcutsHelp.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/ShortcutsHelp.test.tsx.snap @@ -16,6 +16,22 @@ exports[`ShortcutsHelp > renders correctly in 'narrow' mode on 'linux' 1`] = ` " `; +exports[`ShortcutsHelp > renders correctly in 'narrow' mode on 'linux' 2`] = ` +"──────────────────────────────────────── + Shortcuts See /help for more + ! shell mode + @ select file or folder + Double Esc clear & rewind + Tab focus UI + Ctrl+Y YOLO mode + Shift+Tab cycle mode + Ctrl+V paste images + Alt+M raw markdown mode + Ctrl+R reverse-search history + Ctrl+G open external editor +" +`; + exports[`ShortcutsHelp > renders correctly in 'narrow' mode on 'mac' 1`] = ` "──────────────────────────────────────── Shortcuts See /help for more diff --git a/packages/cli/src/ui/components/__snapshots__/StatsDisplay.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/StatsDisplay.test.tsx.snap index 8a58ee34409..59a257144ab 100644 --- a/packages/cli/src/ui/components/__snapshots__/StatsDisplay.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/StatsDisplay.test.tsx.snap @@ -292,3 +292,30 @@ exports[` > renders role breakdown correctly under models 1`] = ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ " `; + +exports[` > resolves gemini-3-flash to gemini-3.5-flash in the model usage table 1`] = ` +"╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ │ +│ Session Stats │ +│ │ +│ Interaction Summary │ +│ Session ID: test-session-id │ +│ Tool Calls: 0 ( ✓ 0 x 0 ) │ +│ Success Rate: 0.0% │ +│ │ +│ Performance │ +│ Wall Time: 1s │ +│ Agent Active: 3.0s │ +│ » API Time: 3.0s (100.0%) │ +│ » Tool Time: 0s (0.0%) │ +│ │ +│ │ +│ Model Usage │ +│ Use /model to view model quota information │ +│ │ +│ Model Reqs Input Tokens Cache Reads Output Tokens │ +│ ────────────────────────────────────────────────────────────────────────────────────────────── │ +│ gemini-3.5-flash 5 2,000 500 3,000 │ +╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ +" +`; diff --git a/packages/cli/src/ui/components/__snapshots__/ThemeDialog.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ThemeDialog.test.tsx.snap index 37ed33585c3..953310dbd53 100644 --- a/packages/cli/src/ui/components/__snapshots__/ThemeDialog.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/ThemeDialog.test.tsx.snap @@ -25,6 +25,31 @@ exports[`Initial Theme Selection > should default to a dark theme when terminal " `; +exports[`Initial Theme Selection > should default to a dark theme when terminal background is dark and no theme is set 2`] = ` +"╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ │ +│ > Select Theme Preview │ +│ ▲ ┌─────────────────────────────────────────────────┐ │ +│ 1. ANSI Dark │ │ │ +│ 2. Atom One Dark │ 1 # function │ │ +│ 3. Ayu Dark │ 2 def fibonacci(n): │ │ +│ ● 4. Default Dark (Matches terminal) │ 3 a, b = 0, 1 │ │ +│ 5. Dracula Dark │ 4 for _ in range(n): │ │ +│ 6. GitHub Dark │ 5 a, b = b, a + b │ │ +│ 7. GitHub Dark Colorblind Dark │ 6 return a │ │ +│ 8. Holiday Dark │ │ │ +│ 9. Shades Of Purple Dark │ 1 - print("Hello, " + name) │ │ +│ 10. Solarized Dark │ 1 + print(f"Hello, {name}!") │ │ +│ 11. Tokyo Night Dark │ │ │ +│ 12. ANSI Light (Incompatible) └─────────────────────────────────────────────────┘ │ +│ ▼ │ +│ │ +│ (Use Enter to select, Tab to configure scope, Esc to close) │ +│ │ +╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ +" +`; + exports[`Initial Theme Selection > should default to a light theme when terminal background is light and no theme is set 1`] = ` "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ @@ -89,6 +114,20 @@ exports[`ThemeDialog Snapshots > should render correctly in scope selector mode " `; +exports[`ThemeDialog Snapshots > should render correctly in scope selector mode 2`] = ` +"╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ │ +│ > Apply To │ +│ ● 1. User Settings │ +│ 2. Workspace Settings │ +│ 3. System Settings │ +│ │ +│ (Use Enter to apply scope, Tab to select theme, Esc to close) │ +│ │ +╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ +" +`; + exports[`ThemeDialog Snapshots > should render correctly in theme selection mode (isDevelopment: false) 1`] = ` "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ diff --git a/packages/cli/src/ui/components/__snapshots__/Tips.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/Tips.test.tsx.snap index dbc60fcf4d1..7a421807906 100644 --- a/packages/cli/src/ui/components/__snapshots__/Tips.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/Tips.test.tsx.snap @@ -18,3 +18,12 @@ Tips for getting started: 3. Be specific for the best results " `; + +exports[`Tips > 'renders fewer tips when GEMINI.md exi…' 2`] = ` +" +Tips for getting started: +1. /help for more information +2. Ask coding questions, edit code or run commands +3. Be specific for the best results +" +`; diff --git a/packages/cli/src/ui/components/__snapshots__/ToolStatsDisplay.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ToolStatsDisplay.test.tsx.snap index 6b7b847f123..7673d1e2da7 100644 --- a/packages/cli/src/ui/components/__snapshots__/ToolStatsDisplay.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/ToolStatsDisplay.test.tsx.snap @@ -41,6 +41,27 @@ exports[` > should display stats for multiple tools correctl " `; +exports[` > should display stats for multiple tools correctly 2`] = ` +"╭────────────────────────────────────────────────────────────────────╮ +│ │ +│ Tool Stats For Nerds │ +│ │ +│ Tool Name Calls Success Rate Avg Duration │ +│ ──────────────────────────────────────────────────────────────── │ +│ tool-a 2 50.0% 100ms │ +│ tool-b 1 100.0% 100ms │ +│ │ +│ User Decision Summary │ +│ Total Reviewed Suggestions: 3 │ +│ » Accepted: 1 │ +│ » Rejected: 1 │ +│ » Modified: 1 │ +│ ──────────────────────────────────────────────────────────────── │ +│ Overall Agreement Rate: 33.3% │ +╰────────────────────────────────────────────────────────────────────╯ +" +`; + exports[` > should handle large values without wrapping or overlapping 1`] = ` "╭────────────────────────────────────────────────────────────────────╮ │ │ diff --git a/packages/cli/src/ui/components/messages/__snapshots__/ErrorMessage.test.tsx.snap b/packages/cli/src/ui/components/messages/__snapshots__/ErrorMessage.test.tsx.snap index 0f5c270ae47..9a29255f189 100644 --- a/packages/cli/src/ui/components/messages/__snapshots__/ErrorMessage.test.tsx.snap +++ b/packages/cli/src/ui/components/messages/__snapshots__/ErrorMessage.test.tsx.snap @@ -6,6 +6,12 @@ exports[`ErrorMessage > renders multiline error messages 1`] = ` " `; +exports[`ErrorMessage > renders multiline error messages 2`] = ` +"✕ Error line 1 + Error line 2 +" +`; + exports[`ErrorMessage > renders with the correct prefix and text 1`] = ` "✕ Something went wrong " diff --git a/packages/cli/src/ui/components/messages/__snapshots__/GeminiMessage.test.tsx.snap b/packages/cli/src/ui/components/messages/__snapshots__/GeminiMessage.test.tsx.snap index 6e624485e29..9d7734854f5 100644 --- a/packages/cli/src/ui/components/messages/__snapshots__/GeminiMessage.test.tsx.snap +++ b/packages/cli/src/ui/components/messages/__snapshots__/GeminiMessage.test.tsx.snap @@ -16,6 +16,13 @@ exports[` - Raw Markdown Display Snapshots > renders pending st " `; +exports[` - Raw Markdown Display Snapshots > renders pending state with renderMarkdown=true 2`] = ` +"✦ Test bold and code markdown + + 1 const x = 1; +" +`; + exports[` - Raw Markdown Display Snapshots > renders with renderMarkdown=false '(raw markdown with syntax highlightin…' 1`] = ` "✦ Test **bold** and \`code\` markdown @@ -40,3 +47,12 @@ exports[` - Raw Markdown Display Snapshots > wraps long lines c truncation " `; + +exports[` - Raw Markdown Display Snapshots > wraps long lines correctly in raw markdown mode 2`] = ` +"✦ This is a long + line that should + wrap correctly + without + truncation +" +`; diff --git a/packages/cli/src/ui/components/messages/__snapshots__/ToolGroupMessage.compact.test.tsx.snap b/packages/cli/src/ui/components/messages/__snapshots__/ToolGroupMessage.compact.test.tsx.snap index a60ac429c71..b42f8a5a1ae 100644 --- a/packages/cli/src/ui/components/messages/__snapshots__/ToolGroupMessage.compact.test.tsx.snap +++ b/packages/cli/src/ui/components/messages/__snapshots__/ToolGroupMessage.compact.test.tsx.snap @@ -26,6 +26,12 @@ exports[`ToolGroupMessage Compact Rendering > does not add an extra empty line i " `; +exports[`ToolGroupMessage Compact Rendering > does not add an extra empty line if a compact tool has a dense payload 2`] = ` +" ✓ ReadFolder Listing files → file1.txt + ✓ ReadFile Reading file → read file +" +`; + exports[`ToolGroupMessage Compact Rendering > renders consecutive compact tools without empty lines between them 1`] = ` " ✓ ReadFolder Listing files → file1.txt file2.txt ✓ ReadFolder Listing files → file3.txt diff --git a/packages/cli/src/ui/components/messages/__snapshots__/ToolMessageRawMarkdown.test.tsx.snap b/packages/cli/src/ui/components/messages/__snapshots__/ToolMessageRawMarkdown.test.tsx.snap index 43140c27d16..15ad761eed5 100644 --- a/packages/cli/src/ui/components/messages/__snapshots__/ToolMessageRawMarkdown.test.tsx.snap +++ b/packages/cli/src/ui/components/messages/__snapshots__/ToolMessageRawMarkdown.test.tsx.snap @@ -16,6 +16,14 @@ exports[` - Raw Markdown Display Snapshots > renders with renderM " `; +exports[` - Raw Markdown Display Snapshots > renders with renderMarkdown=false, useAlternateBuffer=true '(raw markdown, alternate buffer)' 2`] = ` +"╭──────────────────────────────────────────────────────────────────────────────╮ +│ ✓ test-tool A tool for testing │ +│ │ +│ Test **bold** and \`code\` markdown │ +" +`; + exports[` - Raw Markdown Display Snapshots > renders with renderMarkdown=true, useAlternateBuffer=false '(constrained height, regular buffer -…' 1`] = ` "╭──────────────────────────────────────────────────────────────────────────────╮ │ ✓ test-tool A tool for testing │ diff --git a/packages/cli/src/ui/components/messages/__snapshots__/UserMessage.test.tsx.snap b/packages/cli/src/ui/components/messages/__snapshots__/UserMessage.test.tsx.snap index 0459cae90e5..c86b1b13e21 100644 --- a/packages/cli/src/ui/components/messages/__snapshots__/UserMessage.test.tsx.snap +++ b/packages/cli/src/ui/components/messages/__snapshots__/UserMessage.test.tsx.snap @@ -8,6 +8,14 @@ exports[`UserMessage > renders multiline user message 1`] = ` " `; +exports[`UserMessage > renders multiline user message 2`] = ` +"▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + > Line 1 + Line 2 +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +" +`; + exports[`UserMessage > renders normal user message with correct prefix 1`] = ` "▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ > Hello Gemini diff --git a/packages/cli/src/ui/components/messages/__snapshots__/WarningMessage.test.tsx.snap b/packages/cli/src/ui/components/messages/__snapshots__/WarningMessage.test.tsx.snap index f7f4b403975..7049a6899d0 100644 --- a/packages/cli/src/ui/components/messages/__snapshots__/WarningMessage.test.tsx.snap +++ b/packages/cli/src/ui/components/messages/__snapshots__/WarningMessage.test.tsx.snap @@ -7,6 +7,13 @@ exports[`WarningMessage > renders multiline warning messages 1`] = ` " `; +exports[`WarningMessage > renders multiline warning messages 2`] = ` +" +⚠ Warning line 1 + Warning line 2 +" +`; + exports[`WarningMessage > renders with the correct prefix and text 1`] = ` " ⚠ Watch out! diff --git a/packages/cli/src/ui/components/views/__snapshots__/ChatList.test.tsx.snap b/packages/cli/src/ui/components/views/__snapshots__/ChatList.test.tsx.snap index b6c2c684e1f..1a47cfa1a0c 100644 --- a/packages/cli/src/ui/components/views/__snapshots__/ChatList.test.tsx.snap +++ b/packages/cli/src/ui/components/views/__snapshots__/ChatList.test.tsx.snap @@ -9,6 +9,15 @@ Note: Newest last, oldest first " `; +exports[` > handles invalid date formats gracefully 2`] = ` +"List of saved conversations: + + - bad-date-chat (Invalid Date) + +Note: Newest last, oldest first +" +`; + exports[` > renders correctly with a list of chats 1`] = ` "List of saved conversations: diff --git a/packages/cli/src/ui/layouts/__snapshots__/DefaultAppLayout.test.tsx.snap b/packages/cli/src/ui/layouts/__snapshots__/DefaultAppLayout.test.tsx.snap index 48cb662534a..0ff6e082166 100644 --- a/packages/cli/src/ui/layouts/__snapshots__/DefaultAppLayout.test.tsx.snap +++ b/packages/cli/src/ui/layouts/__snapshots__/DefaultAppLayout.test.tsx.snap @@ -30,6 +30,20 @@ BackgroundTaskDisplay +Notifications +CopyModeWarning +Composer +ExitWarning +" +`; + +exports[` > shows BackgroundTaskDisplay when StreamingState is NOT WaitingForConfirmation 2`] = ` +"MainContent +BackgroundTaskDisplay + + + + Notifications CopyModeWarning Composer diff --git a/packages/core/src/availability/fallbackIntegration.test.ts b/packages/core/src/availability/fallbackIntegration.test.ts index 6c49938ed91..1ee53da37e1 100644 --- a/packages/core/src/availability/fallbackIntegration.test.ts +++ b/packages/core/src/availability/fallbackIntegration.test.ts @@ -28,6 +28,7 @@ describe('Fallback Integration', () => { getActiveModel: () => PREVIEW_GEMINI_MODEL_AUTO, setActiveModel: vi.fn(), getUserTier: () => undefined, + getHasAccessToPreviewModel: () => true, getModelAvailabilityService: () => availabilityService, modelConfigService: undefined as unknown as ModelConfigService, } as unknown as Config; diff --git a/packages/core/src/availability/policyCatalog.test.ts b/packages/core/src/availability/policyCatalog.test.ts index 04e35018d5c..9aa605abd43 100644 --- a/packages/core/src/availability/policyCatalog.test.ts +++ b/packages/core/src/availability/policyCatalog.test.ts @@ -28,7 +28,6 @@ describe('policyCatalog', () => { const chain = getModelPolicyChain({ previewEnabled: true, useGemini31: true, - useGemini31FlashLite: false, }); expect(chain[0]?.model).toBe(PREVIEW_GEMINI_3_1_MODEL); expect(chain).toHaveLength(2); @@ -39,7 +38,6 @@ describe('policyCatalog', () => { const chain = getModelPolicyChain({ previewEnabled: true, useGemini31: true, - useGemini31FlashLite: false, useCustomToolModel: true, }); expect(chain[0]?.model).toBe(PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL); diff --git a/packages/core/src/availability/policyCatalog.ts b/packages/core/src/availability/policyCatalog.ts index a5694e94b80..e2d1df075ea 100644 --- a/packages/core/src/availability/policyCatalog.ts +++ b/packages/core/src/availability/policyCatalog.ts @@ -33,6 +33,7 @@ export interface ModelPolicyOptions { useGemini31?: boolean; useGemini31FlashLite?: boolean; useCustomToolModel?: boolean; + useGemini3_5Flash?: boolean; } const DEFAULT_ACTIONS: ModelPolicyActionMap = { @@ -93,8 +94,10 @@ export function getModelPolicyChain( const proModel = resolveModel( PREVIEW_GEMINI_MODEL, options.useGemini31, - options.useGemini31FlashLite, options.useCustomToolModel, + true, + undefined, + options.useGemini3_5Flash, ); return [ definePolicy({ diff --git a/packages/core/src/availability/policyHelpers.test.ts b/packages/core/src/availability/policyHelpers.test.ts index 7db99bb1aa5..0d4a25e8c49 100644 --- a/packages/core/src/availability/policyHelpers.test.ts +++ b/packages/core/src/availability/policyHelpers.test.ts @@ -30,14 +30,17 @@ const createMockConfig = (overrides: Partial = {}): Config => { getUserTier: () => undefined, getModel: () => 'gemini-2.5-pro', getGemini31LaunchedSync: () => false, - getGemini31FlashLiteLaunchedSync: () => false, getUseCustomToolModelSync: () => { const useGemini31 = config.getGemini31LaunchedSync(); const authType = config.getContentGeneratorConfig().authType; return useGemini31 && authType === AuthType.USE_GEMINI; }, getContentGeneratorConfig: () => ({ authType: undefined }), + getHasAccessToPreviewModel: () => true, getMaxAttemptsPerTurn: () => 3, + getExperimentalDynamicModelConfiguration: () => false, + getReleaseChannel: () => 'preview', + modelConfigService: new ModelConfigService(DEFAULT_MODEL_CONFIGS), ...overrides, } as unknown as Config; return config; @@ -110,7 +113,7 @@ describe('policyHelpers', () => { }); const chain = resolvePolicyChain(config, DEFAULT_GEMINI_FLASH_LITE_MODEL); expect(chain).toHaveLength(3); - expect(chain[0]?.model).toBe('gemini-2.5-flash-lite'); + expect(chain[0]?.model).toBe('gemini-3.1-flash-lite'); expect(chain[1]?.model).toBe('gemini-2.5-flash'); expect(chain[2]?.model).toBe('gemini-2.5-pro'); }); @@ -121,7 +124,7 @@ describe('policyHelpers', () => { }); const chain = resolvePolicyChain(config); expect(chain).toHaveLength(3); - expect(chain[0]?.model).toBe('gemini-2.5-flash-lite'); + expect(chain[0]?.model).toBe('gemini-3.1-flash-lite'); expect(chain[1]?.model).toBe('gemini-2.5-flash'); expect(chain[2]?.model).toBe('gemini-2.5-pro'); }); @@ -187,6 +190,7 @@ describe('policyHelpers', () => { const testCases = [ { name: 'Default Auto', model: DEFAULT_GEMINI_MODEL_AUTO }, { name: 'Gemini 3 Auto', model: 'auto-gemini-3' }, + { name: 'Unified Auto', model: 'auto' }, { name: 'Flash Lite', model: DEFAULT_GEMINI_FLASH_LITE_MODEL }, { name: 'Gemini 3 Auto (3.1 Enabled)', @@ -222,9 +226,9 @@ describe('policyHelpers', () => { getExperimentalDynamicModelConfiguration: () => dynamic, getModel: () => model, getGemini31LaunchedSync: () => useGemini31 ?? false, - getGemini31FlashLiteLaunchedSync: () => false, getHasAccessToPreviewModel: () => hasAccess ?? true, getContentGeneratorConfig: () => ({ authType }), + getReleaseChannel: () => 'preview', modelConfigService: new ModelConfigService(DEFAULT_MODEL_CONFIGS), }); diff --git a/packages/core/src/availability/policyHelpers.ts b/packages/core/src/availability/policyHelpers.ts index 28447bd8367..71b8240120d 100644 --- a/packages/core/src/availability/policyHelpers.ts +++ b/packages/core/src/availability/policyHelpers.ts @@ -52,19 +52,21 @@ export function resolvePolicyChain( let chain: ModelPolicyChain | undefined; const useGemini31 = config.getGemini31LaunchedSync?.() ?? false; - const useGemini31FlashLite = - config.getGemini31FlashLiteLaunchedSync?.() ?? false; const useCustomToolModel = config.getUseCustomToolModelSync?.() ?? false; - const hasAccessToPreview = config.getHasAccessToPreviewModel?.() ?? true; + const hasAccessToPreview = config.getHasAccessToPreviewModel?.() ?? false; + const useGemini3_5Flash = config.hasGemini35FlashGAAccess?.() ?? false; + + // Capture the original family intent before any normalization or early downgrade. + const isOriginallyGemini3 = isGemini3Model(modelFromConfig, config); const resolvedModel = normalizeModelId( resolveModel( modelFromConfig, useGemini31, - useGemini31FlashLite, useCustomToolModel, hasAccessToPreview, config, + useGemini3_5Flash, ), ); const isAutoPreferred = normalizedPreferredModel @@ -75,26 +77,19 @@ export function resolvePolicyChain( // We always wrap around for Gemini 3 chains to ensure maximum availability // between models in the same family (e.g. fallback to Pro if Flash is exhausted). const effectiveWrapsAround = - wrapsAround || - isAutoPreferred || - isAutoConfigured || - isGemini3Model(resolvedModel, config); + wrapsAround || isAutoPreferred || isAutoConfigured || isOriginallyGemini3; // --- DYNAMIC PATH --- if (config.getExperimentalDynamicModelConfiguration?.() === true) { const context = { useGemini3_1: useGemini31, - useGemini3_1FlashLite: useGemini31FlashLite, useCustomTools: useCustomToolModel, + useGemini3_5Flash, }; if (resolvedModel === DEFAULT_GEMINI_FLASH_LITE_MODEL) { chain = config.modelConfigService.resolveChain('lite', context); - } else if ( - isGemini3Model(normalizeModelId(resolvedModel), config) || - isAutoPreferred || - isAutoConfigured - ) { + } else if (isOriginallyGemini3 || isAutoPreferred || isAutoConfigured) { // 1. Try to find a chain specifically for the current configured alias if ( isAutoConfigured && @@ -131,15 +126,11 @@ export function resolvePolicyChain( if (resolvedModel === DEFAULT_GEMINI_FLASH_LITE_MODEL) { chain = getFlashLitePolicyChain(); - } else if ( - isGemini3Model(resolvedModel, config) || - isAutoPreferred || - isAutoConfigured - ) { + } else if (isOriginallyGemini3 || isAutoPreferred || isAutoConfigured) { const isAutoSelection = isAutoPreferred || isAutoConfigured; if (hasAccessToPreview) { const previewEnabled = - isGemini3Model(resolvedModel, config) || + isOriginallyGemini3 || normalizedPreferredModel === PREVIEW_GEMINI_MODEL_AUTO || configuredModel === PREVIEW_GEMINI_MODEL_AUTO; chain = getModelPolicyChain({ @@ -147,8 +138,8 @@ export function resolvePolicyChain( isAutoSelection, userTier: config.getUserTier(), useGemini31, - useGemini31FlashLite, useCustomToolModel, + useGemini3_5Flash, }); } else { // User requested Gemini 3 but has no access. Proactively downgrade @@ -158,8 +149,8 @@ export function resolvePolicyChain( isAutoSelection, userTier: config.getUserTier(), useGemini31, - useGemini31FlashLite, useCustomToolModel, + useGemini3_5Flash, }); } } else { diff --git a/packages/core/src/code_assist/experiments/flagNames.ts b/packages/core/src/code_assist/experiments/flagNames.ts index 125ff005a97..ceb9b2e0f41 100644 --- a/packages/core/src/code_assist/experiments/flagNames.ts +++ b/packages/core/src/code_assist/experiments/flagNames.ts @@ -18,8 +18,8 @@ export const ExperimentFlags = { MASKING_PROTECT_LATEST_TURN: 45758819, GEMINI_3_1_PRO_LAUNCHED: 45760185, PRO_MODEL_NO_ACCESS: 45768879, - GEMINI_3_1_FLASH_LITE_LAUNCHED: 45771641, DEFAULT_REQUEST_TIMEOUT: 45773134, + GEMINI_3_5_FLASH_GA_LAUNCHED: 45780819, } as const; export type ExperimentFlagName = diff --git a/packages/core/src/config/config.test.ts b/packages/core/src/config/config.test.ts index 66965411070..64cf25f7683 100644 --- a/packages/core/src/config/config.test.ts +++ b/packages/core/src/config/config.test.ts @@ -69,6 +69,7 @@ import { DEFAULT_GEMINI_MODEL_AUTO, PREVIEW_GEMINI_MODEL_AUTO, PREVIEW_GEMINI_FLASH_MODEL, + DEFAULT_GEMINI_FLASH_MODEL, } from './models.js'; import { Storage } from './storage.js'; import type { AgentLoopContext } from './agent-loop-context.js'; @@ -702,20 +703,6 @@ describe('Server Config (config.ts)', () => { }); }); - describe('getGemini31FlashLiteLaunchedSync', () => { - it.each([AuthType.USE_GEMINI, AuthType.USE_VERTEX_AI, AuthType.GATEWAY])( - 'should return true for %s', - async (authType) => { - const config = new Config(baseParams); - vi.mocked(createContentGeneratorConfig).mockResolvedValue({ - authType, - }); - await config.refreshAuth(authType); - expect(config.getGemini31FlashLiteLaunchedSync()).toBe(true); - }, - ); - }); - describe('getProModelNoAccessSync', () => { it('should return experiment value for AuthType.LOGIN_WITH_GOOGLE', async () => { vi.mocked(getExperiments).mockResolvedValue({ @@ -4331,3 +4318,57 @@ describe('ADKSettings', () => { expect(config.getAgentSessionNoninteractiveEnabled()).toBe(true); }); }); + +describe('hasGemini35FlashGAAccess model setting', () => { + const baseParams: ConfigParameters = { + sessionId: 'test', + targetDir: '.', + debugMode: false, + model: 'test-model', + cwd: '.', + }; + + it('should set DEFAULT_GEMINI_FLASH_MODEL to gemini-3.5-flash and PREVIEW_GEMINI_FLASH_MODEL to gemini-3-flash-preview if hasGemini35FlashGAAccess returns true and authType is USE_GEMINI', () => { + const config = new Config(baseParams); + config['contentGeneratorConfig'] = { authType: AuthType.USE_GEMINI }; + + // Set experiment to return true for GEMINI_3_5_FLASH_GA_LAUNCHED + config.setExperiments({ + experimentIds: [], + flags: { + [ExperimentFlags.GEMINI_3_5_FLASH_GA_LAUNCHED]: { + boolValue: true, + }, + }, + }); + + // Call the method + const result = config.hasGemini35FlashGAAccess(); + expect(result).toBe(true); + + expect(DEFAULT_GEMINI_FLASH_MODEL).toBe('gemini-3.5-flash'); + expect(PREVIEW_GEMINI_FLASH_MODEL).toBe('gemini-3-flash-preview'); + }); + + it('should set DEFAULT_GEMINI_FLASH_MODEL and PREVIEW_GEMINI_FLASH_MODEL to gemini-3-flash if hasGemini35FlashGAAccess returns true and authType is not USE_GEMINI', () => { + const config = new Config(baseParams); + config['contentGeneratorConfig'] = { authType: AuthType.LOGIN_WITH_GOOGLE }; + + // Set experiment to return true for GEMINI_3_5_FLASH_GA_LAUNCHED + config.setExperiments({ + experimentIds: [], + flags: { + [ExperimentFlags.GEMINI_3_5_FLASH_GA_LAUNCHED]: { + boolValue: true, + }, + }, + }); + + // Call the method + const result = config.hasGemini35FlashGAAccess(); + expect(result).toBe(true); + + expect(DEFAULT_GEMINI_FLASH_MODEL).toBe('gemini-3-flash'); + expect(PREVIEW_GEMINI_FLASH_MODEL).toBe('gemini-3-flash'); + }); +}); diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index b81737b0ea4..fb78430f8ac 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -81,15 +81,13 @@ import { tokenLimit } from '../core/tokenLimits.js'; import { DEFAULT_GEMINI_EMBEDDING_MODEL, DEFAULT_GEMINI_FLASH_MODEL, - DEFAULT_GEMINI_MODEL, DEFAULT_GEMINI_MODEL_AUTO, isAutoModel, isPreviewModel, isGemini2Model, PREVIEW_GEMINI_FLASH_MODEL, - PREVIEW_GEMINI_MODEL, - PREVIEW_GEMINI_MODEL_AUTO, resolveModel, + setFlashModels, } from './models.js'; import { shouldAttemptBrowserLaunch } from '../utils/browser.js'; import type { MCPOAuthConfig } from '../mcp/oauth-provider.js'; @@ -184,6 +182,7 @@ import { InjectionService } from './injectionService.js'; import { ExecutionLifecycleService } from '../services/executionLifecycleService.js'; import { WORKSPACE_POLICY_TIER } from '../policy/config.js'; import { loadPoliciesFromToml } from '../policy/toml-loader.js'; +import { getChannelFromVersion } from '../utils/channel.js'; import { CheckerRunner } from '../safety/checker-runner.js'; import { ContextBuilder } from '../safety/context-builder.js'; @@ -762,7 +761,7 @@ export class Config implements McpContext, AgentLoopContext { private skillManager!: SkillManager; private _sessionId: string; private readonly clientName: string | undefined; - private clientVersion: string; + private _clientVersion: string; private fileSystemService: FileSystemService; private trackerService?: TrackerService; readonly topicState = new TopicState(); @@ -982,7 +981,7 @@ export class Config implements McpContext, AgentLoopContext { constructor(params: ConfigParameters) { this._sessionId = params.sessionId; this.clientName = params.clientName; - this.clientVersion = params.clientVersion ?? 'unknown'; + this._clientVersion = params.clientVersion ?? 'unknown'; this.approvedPlanPath = undefined; this.embeddingModel = params.embeddingModel ?? DEFAULT_GEMINI_EMBEDDING_MODEL; @@ -2013,10 +2012,17 @@ export class Config implements McpContext, AgentLoopContext { return {}; } - const isPreview = - model === PREVIEW_GEMINI_MODEL_AUTO || - isPreviewModel(this.getActiveModel(), this); - const proModel = isPreview ? PREVIEW_GEMINI_MODEL : DEFAULT_GEMINI_MODEL; + const primaryModel = resolveModel( + model, + this.getGemini31LaunchedSync(), + this.getUseCustomToolModelSync(), + this.getHasAccessToPreviewModel(), + this, + this.hasGemini35FlashGAAccess(), + ); + + const isPreview = isPreviewModel(primaryModel, this); + const proModel = primaryModel; const flashModel = isPreview ? PREVIEW_GEMINI_FLASH_MODEL : DEFAULT_GEMINI_FLASH_MODEL; @@ -2049,10 +2055,10 @@ export class Config implements McpContext, AgentLoopContext { const primaryModel = resolveModel( this.getModel(), this.getGemini31LaunchedSync(), - this.getGemini31FlashLiteLaunchedSync(), this.getUseCustomToolModelSync(), this.getHasAccessToPreviewModel(), this, + this.hasGemini35FlashGAAccess(), ); return this.modelQuotas.get(primaryModel)?.remaining; } @@ -2065,10 +2071,10 @@ export class Config implements McpContext, AgentLoopContext { const primaryModel = resolveModel( this.getModel(), this.getGemini31LaunchedSync(), - this.getGemini31FlashLiteLaunchedSync(), this.getUseCustomToolModelSync(), this.getHasAccessToPreviewModel(), this, + this.hasGemini35FlashGAAccess(), ); return this.modelQuotas.get(primaryModel)?.limit; } @@ -2081,10 +2087,10 @@ export class Config implements McpContext, AgentLoopContext { const primaryModel = resolveModel( this.getModel(), this.getGemini31LaunchedSync(), - this.getGemini31FlashLiteLaunchedSync(), this.getUseCustomToolModelSync(), this.getHasAccessToPreviewModel(), this, + this.hasGemini35FlashGAAccess(), ); return this.modelQuotas.get(primaryModel)?.resetTime; } @@ -3441,15 +3447,6 @@ export class Config implements McpContext, AgentLoopContext { return this.getGemini31LaunchedSync(); } - /** - * Returns whether Gemini 3.1 Flash Lite has been launched. - * This method is async and ensures that experiments are loaded before returning the result. - */ - async getGemini31FlashLiteLaunched(): Promise { - await this.ensureExperimentsLoaded(); - return this.getGemini31FlashLiteLaunchedSync(); - } - /** * Returns whether the custom tool model should be used. */ @@ -3478,6 +3475,42 @@ export class Config implements McpContext, AgentLoopContext { ); } + getReleaseChannel(): string { + return getChannelFromVersion(this._clientVersion); + } + + /** + * Returns whether Gemini 3.5 Flash GA has been launched. + * + * Note: This method should only be called after startup, once experiments have been loaded. + */ + hasGemini35FlashGAAccess(): boolean { + const authType = this.contentGeneratorConfig?.authType; + const hasAccess = (() => { + if (this.isGemini31LaunchedForAuthType(authType)) { + return true; + } + return ( + this.experiments?.flags[ExperimentFlags.GEMINI_3_5_FLASH_GA_LAUNCHED] + ?.boolValue ?? false + ); + })(); + // Used to set default flash models based on access + // TODO: Remove once the experiment for 3_5 flash rollut can be cleaned up. + if (hasAccess) { + // Gemini API key users should have the ability to manually select the + // old preview flash model. + if (authType === AuthType.USE_GEMINI) { + setFlashModels('gemini-3-flash-preview', 'gemini-3.5-flash'); + } else { + setFlashModels('gemini-3-flash', 'gemini-3-flash'); + } + } else { + setFlashModels('gemini-3-flash-preview', 'gemini-2.5-flash'); + } + return hasAccess; + } + /** * Returns whether Gemini 3.1 has been launched. * @@ -3512,21 +3545,10 @@ export class Config implements McpContext, AgentLoopContext { } /** - * Returns whether Gemini 3.1 Flash Lite has been launched. - * - * Note: This method should only be called after startup, once experiments have been loaded. - * If you need to call this during startup or from an async context, use - * getGemini31FlashLiteLaunched instead. + * Returns the client version. */ - getGemini31FlashLiteLaunchedSync(): boolean { - const authType = this.contentGeneratorConfig?.authType; - if (this.isGemini31LaunchedForAuthType(authType)) { - return true; - } - return ( - this.experiments?.flags[ExperimentFlags.GEMINI_3_1_FLASH_LITE_LAUNCHED] - ?.boolValue ?? false - ); + get clientVersion(): string { + return this._clientVersion; } private async ensureExperimentsLoaded(): Promise { diff --git a/packages/core/src/config/defaultModelConfigs.ts b/packages/core/src/config/defaultModelConfigs.ts index 396e3d50941..056b91b351d 100644 --- a/packages/core/src/config/defaultModelConfigs.ts +++ b/packages/core/src/config/defaultModelConfigs.ts @@ -71,6 +71,24 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { model: 'gemini-3-flash-preview', }, }, + 'gemini-3.1-pro-preview': { + extends: 'chat-base-3', + modelConfig: { + model: 'gemini-3.1-pro-preview', + }, + }, + 'gemini-3.1-pro-preview-customtools': { + extends: 'chat-base-3', + modelConfig: { + model: 'gemini-3.1-pro-preview-customtools', + }, + }, + 'gemini-3.1-flash-lite-preview': { + extends: 'chat-base-3', + modelConfig: { + model: 'gemini-3.1-flash-lite-preview', + }, + }, 'gemini-2.5-pro': { extends: 'chat-base-2.5', modelConfig: { @@ -89,6 +107,18 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { model: 'gemini-2.5-flash-lite', }, }, + 'gemini-3.1-flash-lite': { + extends: 'chat-base-3', + modelConfig: { + model: 'gemini-3.1-flash-lite', + }, + }, + 'gemini-3.5-flash': { + extends: 'chat-base-3', + modelConfig: { + model: 'gemini-3.5-flash', + }, + }, 'gemma-4-31b-it': { extends: 'chat-base-3', modelConfig: { @@ -115,10 +145,16 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { model: 'gemini-3-flash-preview', }, }, + 'gemini-3.5-flash-base': { + extends: 'base', + modelConfig: { + model: 'gemini-3.5-flash', + }, + }, classifier: { extends: 'base', modelConfig: { - model: 'gemini-2.5-flash-lite', + model: 'flash-lite', generateContentConfig: { maxOutputTokens: 1024, thinkingConfig: { @@ -130,7 +166,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { 'prompt-completion': { extends: 'base', modelConfig: { - model: 'gemini-2.5-flash-lite', + model: 'flash-lite', generateContentConfig: { temperature: 0.3, maxOutputTokens: 16000, @@ -143,7 +179,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { 'fast-ack-helper': { extends: 'base', modelConfig: { - model: 'gemini-2.5-flash-lite', + model: 'flash-lite', generateContentConfig: { temperature: 0.2, maxOutputTokens: 120, @@ -156,7 +192,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { 'edit-corrector': { extends: 'base', modelConfig: { - model: 'gemini-2.5-flash-lite', + model: 'flash-lite', generateContentConfig: { thinkingConfig: { thinkingBudget: 0, @@ -167,7 +203,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { 'summarizer-default': { extends: 'base', modelConfig: { - model: 'gemini-2.5-flash-lite', + model: 'flash-lite', generateContentConfig: { maxOutputTokens: 2000, }, @@ -176,7 +212,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { 'summarizer-shell': { extends: 'base', modelConfig: { - model: 'gemini-2.5-flash-lite', + model: 'flash-lite', generateContentConfig: { maxOutputTokens: 2000, }, @@ -246,7 +282,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { }, 'chat-compression-3.1-flash-lite': { modelConfig: { - model: 'gemini-3.1-flash-lite-preview', + model: 'gemini-3.1-flash-lite', }, }, 'chat-compression-2.5-pro': { @@ -287,10 +323,10 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { ], modelDefinitions: { // Concrete Models - 'gemini-3.1-flash-lite-preview': { + 'gemini-3.1-flash-lite': { tier: 'flash-lite', family: 'gemini-3', - isPreview: true, + isPreview: false, isVisible: true, features: { thinking: false, multimodalToolUse: true }, }, @@ -322,6 +358,13 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { isVisible: true, features: { thinking: false, multimodalToolUse: true }, }, + 'gemini-3.5-flash': { + tier: 'flash', + family: 'gemini-3', + isPreview: false, + isVisible: true, + features: { thinking: false, multimodalToolUse: true }, + }, 'gemini-2.5-pro': { tier: 'pro', family: 'gemini-2.5', @@ -362,9 +405,10 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { // Aliases auto: { + displayName: 'Auto', tier: 'auto', isPreview: true, - isVisible: false, + isVisible: true, features: { thinking: true, multimodalToolUse: false }, }, pro: { @@ -386,22 +430,16 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { features: { thinking: false, multimodalToolUse: false }, }, 'auto-gemini-3': { - displayName: 'Auto (Gemini 3)', tier: 'auto', + family: 'gemini-3', isPreview: true, - isVisible: true, - dialogDescription: - 'Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash', - features: { thinking: true, multimodalToolUse: false }, + isVisible: false, }, 'auto-gemini-2.5': { - displayName: 'Auto (Gemini 2.5)', tier: 'auto', + family: 'gemini-2.5', isPreview: false, - isVisible: true, - dialogDescription: - 'Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash', - features: { thinking: false, multimodalToolUse: false }, + isVisible: false, }, }, modelIdResolutions: { @@ -432,26 +470,35 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { default: 'gemini-3-flash-preview', contexts: [ { - condition: { hasAccessToPreview: false }, + condition: { hasAccessToPreview: false, useGemini3_5Flash: true }, + target: 'gemini-3.5-flash', + }, + { + condition: { hasAccessToPreview: false, useGemini3_5Flash: false }, target: 'gemini-2.5-flash', }, ], }, - 'gemini-3-pro-preview': { - default: 'gemini-3-pro-preview', + 'gemini-3.5-flash': { + default: 'gemini-3.5-flash', contexts: [ - { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-pro' }, { - condition: { useGemini3_1: true, useCustomTools: true }, - target: 'gemini-3.1-pro-preview-customtools', + condition: { useGemini3_5Flash: false, hasAccessToPreview: false }, + target: 'gemini-2.5-flash', }, { - condition: { useGemini3_1: true }, - target: 'gemini-3.1-pro-preview', + condition: { useGemini3_5Flash: false }, + target: 'gemini-3-flash-preview', }, ], }, - 'auto-gemini-3': { + 'gemini-2.5-flash': { + default: 'gemini-2.5-flash', + contexts: [ + { condition: { useGemini3_5Flash: true }, target: 'gemini-3.5-flash' }, + ], + }, + 'gemini-3-pro-preview': { default: 'gemini-3-pro-preview', contexts: [ { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-pro' }, @@ -493,21 +540,13 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { }, ], }, - 'auto-gemini-2.5': { - default: 'gemini-2.5-pro', - }, - 'gemini-3.1-flash-lite-preview': { - default: 'gemini-3.1-flash-lite-preview', - contexts: [ - { - condition: { useGemini3_1FlashLite: false }, - target: 'gemini-2.5-flash-lite', - }, - ], + 'gemini-3.1-flash-lite': { + default: 'gemini-3.1-flash-lite', }, flash: { default: 'gemini-3-flash-preview', contexts: [ + { condition: { useGemini3_5Flash: true }, target: 'gemini-3.5-flash' }, { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-flash', @@ -515,28 +554,38 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { ], }, 'flash-lite': { - default: 'gemini-2.5-flash-lite', + default: 'gemini-3.1-flash-lite', + }, + 'auto-gemini-3': { + default: 'gemini-3-pro-preview', contexts: [ + { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-pro' }, { - condition: { useGemini3_1FlashLite: true }, - target: 'gemini-3.1-flash-lite-preview', + condition: { useGemini3_1: true, useCustomTools: true }, + target: 'gemini-3.1-pro-preview-customtools', + }, + { + condition: { useGemini3_1: true }, + target: 'gemini-3.1-pro-preview', }, ], }, + 'auto-gemini-2.5': { + default: 'gemini-2.5-pro', + }, }, classifierIdResolutions: { flash: { default: 'gemini-3-flash-preview', contexts: [ + { condition: { useGemini3_5Flash: true }, target: 'gemini-3.5-flash' }, { - condition: { requestedModels: ['auto-gemini-2.5', 'gemini-2.5-pro'] }, + condition: { hasAccessToPreview: false }, target: 'gemini-2.5-flash', }, { - condition: { - requestedModels: ['auto-gemini-3', 'gemini-3-pro-preview'], - }, - target: 'gemini-3-flash-preview', + condition: { requestedModels: ['gemini-2.5-pro', 'auto-gemini-2.5'] }, + target: 'gemini-2.5-flash', }, ], }, @@ -544,7 +593,11 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { default: 'gemini-3-pro-preview', contexts: [ { - condition: { requestedModels: ['auto-gemini-2.5', 'gemini-2.5-pro'] }, + condition: { hasAccessToPreview: false }, + target: 'gemini-2.5-pro', + }, + { + condition: { requestedModels: ['gemini-2.5-pro', 'auto-gemini-2.5'] }, target: 'gemini-2.5-pro', }, { @@ -699,7 +752,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { ], lite: [ { - model: 'gemini-2.5-flash-lite', + model: 'flash-lite', actions: { terminal: 'silent', transient: 'silent', diff --git a/packages/core/src/config/models.test.ts b/packages/core/src/config/models.test.ts index d49f3305c26..fe6799e7c88 100644 --- a/packages/core/src/config/models.test.ts +++ b/packages/core/src/config/models.test.ts @@ -14,9 +14,11 @@ import { supportsModernFeatures, isAutoModel, getDisplayString, + getAutoModelDescription, DEFAULT_GEMINI_MODEL, PREVIEW_GEMINI_MODEL, DEFAULT_GEMINI_FLASH_MODEL, + DEFAULT_GEMINI_3_5_FLASH_MODEL, DEFAULT_GEMINI_FLASH_LITE_MODEL, supportsMultimodalFunctionResponse, GEMINI_MODEL_ALIAS_PRO, @@ -28,7 +30,7 @@ import { DEFAULT_GEMINI_MODEL_AUTO, isActiveModel, PREVIEW_GEMINI_3_1_MODEL, - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, + PREVIEW_GEMINI_FLASH_LITE_MODEL, PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, isPreviewModel, isProModel, @@ -66,22 +68,14 @@ describe('Dynamic Configuration Parity', () => { const flagCombos = [ { useGemini3_1: false, - useGemini3_1FlashLite: false, useCustomToolModel: false, }, { useGemini3_1: true, - useGemini3_1FlashLite: false, useCustomToolModel: false, }, { useGemini3_1: true, - useGemini3_1FlashLite: true, - useCustomToolModel: false, - }, - { - useGemini3_1: true, - useGemini3_1FlashLite: true, useCustomToolModel: true, }, ]; @@ -104,7 +98,6 @@ describe('Dynamic Configuration Parity', () => { const legacy = resolveModel( model, flags.useGemini3_1, - flags.useGemini3_1FlashLite, flags.useCustomToolModel, hasAccess, mockLegacyConfig, @@ -112,7 +105,6 @@ describe('Dynamic Configuration Parity', () => { const dynamic = resolveModel( model, flags.useGemini3_1, - flags.useGemini3_1FlashLite, flags.useCustomToolModel, hasAccess, mockDynamicConfig, @@ -151,7 +143,6 @@ describe('Dynamic Configuration Parity', () => { anchor, tier, flags.useGemini3_1, - flags.useGemini3_1FlashLite, flags.useCustomToolModel, hasAccess, mockLegacyConfig, @@ -160,7 +151,6 @@ describe('Dynamic Configuration Parity', () => { anchor, tier, flags.useGemini3_1, - flags.useGemini3_1FlashLite, flags.useCustomToolModel, hasAccess, mockDynamicConfig, @@ -228,12 +218,29 @@ describe('Dynamic Configuration Parity', () => { }); describe('isPreviewModel', () => { - it('should return true for preview models', () => { - expect(isPreviewModel(PREVIEW_GEMINI_MODEL)).toBe(true); - expect(isPreviewModel(PREVIEW_GEMINI_3_1_MODEL)).toBe(true); - expect(isPreviewModel(PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL)).toBe(true); - expect(isPreviewModel(PREVIEW_GEMINI_FLASH_MODEL)).toBe(true); + const PREVIEW_MODELS = [ + PREVIEW_GEMINI_MODEL, + PREVIEW_GEMINI_3_1_MODEL, + PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, + PREVIEW_GEMINI_FLASH_MODEL, + PREVIEW_GEMINI_FLASH_LITE_MODEL, + ]; + + it('should return true for active preview models', () => { + for (const model of PREVIEW_MODELS) { + if (model !== 'none') { + expect(isPreviewModel(model)).toBe(true); + } + } expect(isPreviewModel(PREVIEW_GEMINI_MODEL_AUTO)).toBe(true); + expect(isPreviewModel(GEMINI_MODEL_ALIAS_AUTO)).toBe(true); + }); + + it('should return false if a preview model is retired (set to none)', () => { + const retiredModels = PREVIEW_MODELS.filter((m) => m === 'none'); + for (const model of retiredModels) { + expect(isPreviewModel(model)).toBe(false); + } }); it('should return false for non-preview models', () => { @@ -357,9 +364,9 @@ describe('getDisplayString', () => { ); }); - it('should return PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL for PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL', () => { - expect(getDisplayString(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL)).toBe( - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, + it('should return PREVIEW_GEMINI_FLASH_LITE_MODEL for PREVIEW_GEMINI_FLASH_LITE_MODEL', () => { + expect(getDisplayString(PREVIEW_GEMINI_FLASH_LITE_MODEL)).toBe( + PREVIEW_GEMINI_FLASH_LITE_MODEL, ); }); @@ -404,7 +411,7 @@ describe('resolveModel', () => { }); it('should return Gemini 3.1 Pro Custom Tools when auto-gemini-3 is requested, useGemini3_1 is true, and useCustomToolModel is true', () => { - const model = resolveModel(PREVIEW_GEMINI_MODEL_AUTO, true, false, true); + const model = resolveModel(PREVIEW_GEMINI_MODEL_AUTO, true, true); expect(model).toBe(PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL); }); @@ -418,9 +425,9 @@ describe('resolveModel', () => { expect(model).toBe(DEFAULT_GEMINI_FLASH_LITE_MODEL); }); - it('should return the Preview Flash-Lite model when flash-lite is requested and useGemini3_1FlashLite is true', () => { - const model = resolveModel(GEMINI_MODEL_ALIAS_FLASH_LITE, false, true); - expect(model).toBe(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL); + it('should return the Flash-Lite model when flash-lite is requested', () => { + const model = resolveModel(GEMINI_MODEL_ALIAS_FLASH_LITE, false); + expect(model).toBe(DEFAULT_GEMINI_FLASH_LITE_MODEL); }); it('should return the requested model as-is for explicit specific models', () => { @@ -451,45 +458,39 @@ describe('resolveModel', () => { describe('hasAccessToPreview logic', () => { it('should return default model when access to preview is false and preview model is requested', () => { - expect( - resolveModel(PREVIEW_GEMINI_MODEL, false, false, false, false), - ).toBe(DEFAULT_GEMINI_MODEL); + expect(resolveModel(PREVIEW_GEMINI_MODEL, false, false, false)).toBe( + DEFAULT_GEMINI_MODEL, + ); }); it('should return default flash model when access to preview is false and preview flash model is requested', () => { expect( - resolveModel(PREVIEW_GEMINI_FLASH_MODEL, false, false, false, false), + resolveModel(PREVIEW_GEMINI_FLASH_MODEL, false, false, false), ).toBe(DEFAULT_GEMINI_FLASH_MODEL); }); it('should return default flash lite model when access to preview is false and preview flash lite model is requested', () => { expect( - resolveModel( - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, - false, - false, - false, - false, - ), + resolveModel(PREVIEW_GEMINI_FLASH_LITE_MODEL, false, false, false), ).toBe(DEFAULT_GEMINI_FLASH_LITE_MODEL); }); it('should return default model when access to preview is false and auto-gemini-3 is requested', () => { - expect( - resolveModel(PREVIEW_GEMINI_MODEL_AUTO, false, false, false, false), - ).toBe(DEFAULT_GEMINI_MODEL); + expect(resolveModel(PREVIEW_GEMINI_MODEL_AUTO, false, false, false)).toBe( + DEFAULT_GEMINI_MODEL, + ); }); it('should return default model when access to preview is false and Gemini 3.1 is requested', () => { - expect( - resolveModel(PREVIEW_GEMINI_MODEL_AUTO, true, false, false, false), - ).toBe(DEFAULT_GEMINI_MODEL); + expect(resolveModel(PREVIEW_GEMINI_MODEL_AUTO, true, false, false)).toBe( + DEFAULT_GEMINI_MODEL, + ); }); it('should still return default model when access to preview is false and auto-gemini-2.5 is requested', () => { - expect( - resolveModel(DEFAULT_GEMINI_MODEL_AUTO, false, false, false, false), - ).toBe(DEFAULT_GEMINI_MODEL); + expect(resolveModel(DEFAULT_GEMINI_MODEL_AUTO, false, false, false)).toBe( + DEFAULT_GEMINI_MODEL, + ); }); }); }); @@ -581,7 +582,6 @@ describe('resolveClassifierModel', () => { PREVIEW_GEMINI_MODEL_AUTO, GEMINI_MODEL_ALIAS_PRO, true, - false, true, ), ).toBe(PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL); @@ -598,17 +598,14 @@ describe('isActiveModel', () => { it('should return true for Gemma 4 models when experimentalGemma is not provided (defaults to true)', () => { expect(isActiveModel(GEMMA_4_31B_IT_MODEL)).toBe(true); expect(isActiveModel(GEMMA_4_26B_A4B_IT_MODEL)).toBe(true); - expect(isActiveModel(GEMMA_4_31B_IT_MODEL, false, false, false, true)).toBe( + expect(isActiveModel(GEMMA_4_31B_IT_MODEL, false, false, true)).toBe(true); + expect(isActiveModel(GEMMA_4_26B_A4B_IT_MODEL, false, false, true)).toBe( true, ); - expect( - isActiveModel(GEMMA_4_26B_A4B_IT_MODEL, false, false, false, true), - ).toBe(true); }); it('should return false for Gemini 3.1 models when Gemini 3.1 is not launched', () => { expect(isActiveModel(PREVIEW_GEMINI_3_1_MODEL)).toBe(false); - expect(isActiveModel(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL)).toBe(false); }); it('should return true for unknown models and aliases', () => { @@ -624,37 +621,48 @@ describe('isActiveModel', () => { expect(isActiveModel(DEFAULT_GEMINI_MODEL, true)).toBe(true); }); - it('should return true for PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL only when useGemini3_1FlashLite is true', () => { - expect( - isActiveModel(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, false, true), - ).toBe(true); - expect(isActiveModel(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, true, true)).toBe( + it('should handle PREVIEW_GEMINI_FLASH_LITE_MODEL activity correctly based on retirement status', () => { + if (PREVIEW_GEMINI_FLASH_LITE_MODEL === 'none') { + expect(isActiveModel(PREVIEW_GEMINI_FLASH_LITE_MODEL, false, true)).toBe( + false, + ); + expect(isActiveModel(PREVIEW_GEMINI_FLASH_LITE_MODEL, true, true)).toBe( + false, + ); + } else { + expect(isActiveModel(PREVIEW_GEMINI_FLASH_LITE_MODEL, false, true)).toBe( + true, + ); + expect(isActiveModel(PREVIEW_GEMINI_FLASH_LITE_MODEL, true, true)).toBe( + true, + ); + } + expect(isActiveModel(DEFAULT_GEMINI_FLASH_LITE_MODEL, false, false)).toBe( + true, + ); + expect(isActiveModel(DEFAULT_GEMINI_FLASH_LITE_MODEL, true, true)).toBe( + true, + ); + expect(isActiveModel(DEFAULT_GEMINI_FLASH_LITE_MODEL, true, false)).toBe( true, ); - expect( - isActiveModel(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, true, false), - ).toBe(false); }); it('should correctly filter Gemini 3.1 models based on useCustomToolModel when useGemini3_1 is true', () => { // When custom tools are preferred, standard 3.1 should be inactive - expect(isActiveModel(PREVIEW_GEMINI_3_1_MODEL, true, false, true)).toBe( - false, - ); + expect(isActiveModel(PREVIEW_GEMINI_3_1_MODEL, true, true)).toBe(false); expect( - isActiveModel(PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, true, false, true), + isActiveModel(PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, true, true), ).toBe(true); // When custom tools are NOT preferred, custom tools 3.1 should be inactive - expect(isActiveModel(PREVIEW_GEMINI_3_1_MODEL, true, false, false)).toBe( - true, - ); + expect(isActiveModel(PREVIEW_GEMINI_3_1_MODEL, true, false)).toBe(true); expect( - isActiveModel(PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, true, false, false), + isActiveModel(PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, true, false), ).toBe(false); }); - it('should return false for Gemini 3.1 models when useGemini3_1 and useGemini3_1FlashLite are false', () => { + it('should return false for Gemini 3.1 preview models when useGemini3_1 is false', () => { expect(isActiveModel(PREVIEW_GEMINI_3_1_MODEL, false, false, true)).toBe( false, ); @@ -667,8 +675,378 @@ describe('isActiveModel', () => { expect( isActiveModel(PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, false, false, false), ).toBe(false); + if (PREVIEW_GEMINI_FLASH_LITE_MODEL !== 'none') { + expect(isActiveModel(PREVIEW_GEMINI_FLASH_LITE_MODEL, false, false)).toBe( + false, + ); + } + expect(isActiveModel(DEFAULT_GEMINI_FLASH_LITE_MODEL, false, false)).toBe( + true, + ); + }); +}); + +describe('Gemini 3.1 Config Resolution', () => { + it('PREVIEW_GEMINI_3_1_MODEL should resolve to chat-base-3 config (including thinkingLevel)', () => { + const resolved = modelConfigService.getResolvedConfig({ + model: PREVIEW_GEMINI_3_1_MODEL, + isChatModel: true, + }); expect( - isActiveModel(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, false, false), - ).toBe(false); + resolved.generateContentConfig?.thinkingConfig?.thinkingLevel, + ).toBeDefined(); + }); + + it('PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL should resolve to chat-base-3 config (including thinkingLevel)', () => { + const resolved = modelConfigService.getResolvedConfig({ + model: PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, + isChatModel: true, + }); + expect( + resolved.generateContentConfig?.thinkingConfig?.thinkingLevel, + ).toBeDefined(); + }); + + it('PREVIEW_GEMINI_FLASH_LITE_MODEL should resolve to appropriate config based on retirement status', () => { + if (PREVIEW_GEMINI_FLASH_LITE_MODEL === 'none') { + // If none, it falls back to chat-base which may not have thinkingLevel + const resolved = modelConfigService.getResolvedConfig({ + model: PREVIEW_GEMINI_FLASH_LITE_MODEL, + isChatModel: true, + }); + expect(resolved.model).toBe(PREVIEW_GEMINI_FLASH_LITE_MODEL); + } else { + const resolved = modelConfigService.getResolvedConfig({ + model: PREVIEW_GEMINI_FLASH_LITE_MODEL, + isChatModel: true, + }); + expect( + resolved.generateContentConfig?.thinkingConfig?.thinkingLevel, + ).toBeDefined(); + } + }); +}); + +describe('getAutoModelDescription', () => { + it('should return Gemini 2.5 description when hasAccessToPreview is false', () => { + const desc = getAutoModelDescription(false, false); + expect(desc).toContain('gemini-2.5-pro'); + expect(desc).toContain('gemini-2.5-flash'); + }); + + it('should return Gemini 3.0 description when hasAccessToPreview is true', () => { + const desc = getAutoModelDescription(true, false); + expect(desc).toContain('gemini-3-pro-preview'); + expect(desc).toContain('gemini-3-flash-preview'); + }); + + it('should return Gemini 3.1 description when hasAccessToPreview and useGemini3_1 are true', () => { + const desc = getAutoModelDescription(true, true); + expect(desc).toContain('gemini-3.1-pro-preview'); + expect(desc).toContain('gemini-3-flash-preview'); + }); + + it('should return Gemini 3.5 Flash description when hasAccessToPreview and useGemini3_5Flash are true', () => { + const desc = getAutoModelDescription(true, true, true); + expect(desc).toContain('gemini-3.1-pro-preview'); + expect(desc).toContain(DEFAULT_GEMINI_3_5_FLASH_MODEL); + }); +}); + +describe('resolveModel Gemini 3.5 Flash GA', () => { + it('should resolve all but preview flash models to DEFAULT_GEMINI_FLASH_MODEL when useGemini3_5Flash is true (legacy)', () => { + expect( + resolveModel( + GEMINI_MODEL_ALIAS_FLASH, + false, + false, + true, + undefined, + true, + ), + ).toBe(DEFAULT_GEMINI_FLASH_MODEL); + expect( + resolveModel( + DEFAULT_GEMINI_FLASH_MODEL, + false, + false, + true, + undefined, + true, + ), + ).toBe(DEFAULT_GEMINI_FLASH_MODEL); + expect( + resolveModel( + PREVIEW_GEMINI_FLASH_MODEL, + false, + false, + true, + undefined, + true, + ), + ).toBe(PREVIEW_GEMINI_FLASH_MODEL); + }); + + it('should resolve all but preview flash models to gemini-3.5-flash when useGemini3_5Flash is true (dynamic)', () => { + const mockDynamicConfig = { + getExperimentalDynamicModelConfiguration: () => true, + modelConfigService, + } as unknown as Config; + + expect( + resolveModel( + GEMINI_MODEL_ALIAS_FLASH, + false, + false, + true, + mockDynamicConfig, + true, + ), + ).toBe('gemini-3.5-flash'); + expect( + resolveModel( + DEFAULT_GEMINI_FLASH_MODEL, + false, + false, + true, + mockDynamicConfig, + true, + ), + ).toBe('gemini-3.5-flash'); + expect( + resolveModel( + PREVIEW_GEMINI_FLASH_MODEL, + false, + false, + true, + mockDynamicConfig, + true, + ), + ).toBe(PREVIEW_GEMINI_FLASH_MODEL); + }); + + it('should NOT resolve flash models to DEFAULT_GEMINI_FLASH_MODEL when useGemini3_5Flash is false', () => { + expect( + resolveModel( + GEMINI_MODEL_ALIAS_FLASH, + false, + false, + true, + undefined, + false, + ), + ).toBe(PREVIEW_GEMINI_FLASH_MODEL); + expect( + resolveModel( + DEFAULT_GEMINI_FLASH_MODEL, + false, + false, + true, + undefined, + false, + ), + ).toBe(DEFAULT_GEMINI_FLASH_MODEL); + expect( + resolveModel( + PREVIEW_GEMINI_FLASH_MODEL, + false, + false, + true, + undefined, + false, + ), + ).toBe(PREVIEW_GEMINI_FLASH_MODEL); + }); + + it('should resolve to DEFAULT_GEMINI_FLASH_MODEL when GA is false AND preview access is false (dynamic)', () => { + const mockDynamicConfig = { + getExperimentalDynamicModelConfiguration: () => true, + modelConfigService, + } as unknown as Config; + + expect( + resolveModel( + DEFAULT_GEMINI_FLASH_MODEL, + false, + false, + false, // No preview access + mockDynamicConfig, + false, // GA false + ), + ).toBe('gemini-2.5-flash'); + }); + + it('should resolve auto to DEFAULT_GEMINI_FLASH_MODEL when useGemini3_5Flash is true and classifier selects flash', () => { + expect( + resolveClassifierModel( + GEMINI_MODEL_ALIAS_AUTO, + GEMINI_MODEL_ALIAS_FLASH, + false, + false, + true, + undefined, + true, + ), + ).toBe(DEFAULT_GEMINI_FLASH_MODEL); + }); + + it('should resolve auto to gemini-3.5-flash when useGemini3_5Flash is true and classifier selects flash (dynamic)', () => { + const mockDynamicConfig = { + getExperimentalDynamicModelConfiguration: () => true, + modelConfigService, + } as unknown as Config; + + expect( + resolveClassifierModel( + GEMINI_MODEL_ALIAS_AUTO, + GEMINI_MODEL_ALIAS_FLASH, + false, + false, + true, + mockDynamicConfig, + true, + ), + ).toBe('gemini-3.5-flash'); + }); + + describe('Flash model promotion and manual override routing logic', () => { + it('should resolve flash alias to DEFAULT_GEMINI_FLASH_MODEL when useGemini3_5Flash is true (static)', () => { + expect( + resolveModel( + GEMINI_MODEL_ALIAS_FLASH, + false, + false, + true, + undefined, + true, + ), + ).toBe(DEFAULT_GEMINI_FLASH_MODEL); + }); + + it('should resolve flash alias to gemini-3.5-flash when useGemini3_5Flash is true (dynamic)', () => { + const mockDynamicConfig = { + getExperimentalDynamicModelConfiguration: () => true, + modelConfigService, + } as unknown as Config; + + expect( + resolveModel( + GEMINI_MODEL_ALIAS_FLASH, + false, + false, + true, + mockDynamicConfig, + true, + ), + ).toBe('gemini-3.5-flash'); + }); + + it('should resolve manual selection of gemini-3-flash-preview to gemini-3-flash-preview when useGemini3_5Flash is true and has preview access (static)', () => { + expect( + resolveModel( + PREVIEW_GEMINI_FLASH_MODEL, + false, + false, + true, + undefined, + true, + ), + ).toBe('gemini-3-flash-preview'); + }); + + it('should resolve manual selection of gemini-3-flash-preview to gemini-3-flash-preview when useGemini3_5Flash is true and has preview access (dynamic)', () => { + const mockDynamicConfig = { + getExperimentalDynamicModelConfiguration: () => true, + modelConfigService, + } as unknown as Config; + + expect( + resolveModel( + PREVIEW_GEMINI_FLASH_MODEL, + false, + false, + true, + mockDynamicConfig, + true, + ), + ).toBe('gemini-3-flash-preview'); + }); + + it('should resolve manual selection of gemini-3-flash-preview to DEFAULT_GEMINI_FLASH_MODEL when useGemini3_5Flash is true but lacks preview access (static)', () => { + expect( + resolveModel( + PREVIEW_GEMINI_FLASH_MODEL, + false, + false, + false, + undefined, + true, + ), + ).toBe(DEFAULT_GEMINI_FLASH_MODEL); + }); + + it('should resolve manual selection of gemini-3-flash-preview to gemini-3.5-flash when useGemini3_5Flash is true but lacks preview access (dynamic)', () => { + const mockDynamicConfig = { + getExperimentalDynamicModelConfiguration: () => true, + modelConfigService, + } as unknown as Config; + + expect( + resolveModel( + PREVIEW_GEMINI_FLASH_MODEL, + false, + false, + false, + mockDynamicConfig, + true, + ), + ).toBe('gemini-3.5-flash'); + }); + + it('should resolve classifier-selected flash alias to DEFAULT_GEMINI_FLASH_MODEL when useGemini3_5Flash is true (static)', () => { + expect( + resolveClassifierModel( + GEMINI_MODEL_ALIAS_AUTO, + GEMINI_MODEL_ALIAS_FLASH, + false, + false, + true, + undefined, + true, + ), + ).toBe(DEFAULT_GEMINI_FLASH_MODEL); + }); + + it('should resolve classifier-selected flash alias to gemini-3.5-flash when useGemini3_5Flash is true (dynamic)', () => { + const mockDynamicConfig = { + getExperimentalDynamicModelConfiguration: () => true, + modelConfigService, + } as unknown as Config; + + expect( + resolveClassifierModel( + GEMINI_MODEL_ALIAS_AUTO, + GEMINI_MODEL_ALIAS_FLASH, + false, + false, + true, + mockDynamicConfig, + true, + ), + ).toBe('gemini-3.5-flash'); + }); + + it('should resolve auto to PREVIEW_GEMINI_MODEL when useGemini3_5Flash is true and has preview access', () => { + expect( + resolveModel( + GEMINI_MODEL_ALIAS_AUTO, + false, + false, + true, // hasAccessToPreview + undefined, + true, // useGemini3_5Flash + ), + ).toBe(PREVIEW_GEMINI_MODEL); + }); }); }); diff --git a/packages/core/src/config/models.ts b/packages/core/src/config/models.ts index 684ded959ef..1fd8047f02d 100644 --- a/packages/core/src/config/models.ts +++ b/packages/core/src/config/models.ts @@ -6,10 +6,11 @@ export interface ModelResolutionContext { useGemini3_1?: boolean; - useGemini3_1FlashLite?: boolean; + useGemini3_5Flash?: boolean; useCustomTools?: boolean; hasAccessToPreview?: boolean; requestedModel?: string; + releaseChannel?: string; } /** @@ -54,12 +55,32 @@ export const PREVIEW_GEMINI_MODEL = 'gemini-3-pro-preview'; export const PREVIEW_GEMINI_3_1_MODEL = 'gemini-3.1-pro-preview'; export const PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL = 'gemini-3.1-pro-preview-customtools'; -export const PREVIEW_GEMINI_FLASH_MODEL = 'gemini-3-flash-preview'; -export const PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL = - 'gemini-3.1-flash-lite-preview'; +// TODO: set to none and const once the experiment for 3_5 flash rollut can be +// cleaned up. +export let PREVIEW_GEMINI_FLASH_MODEL = 'gemini-3-flash-preview'; export const DEFAULT_GEMINI_MODEL = 'gemini-2.5-pro'; -export const DEFAULT_GEMINI_FLASH_MODEL = 'gemini-2.5-flash'; -export const DEFAULT_GEMINI_FLASH_LITE_MODEL = 'gemini-2.5-flash-lite'; +// TODO: Set to const and update to 'gemini-3.5-flash' once the experiment for +// 3_5 flash rollut can be cleaned up. +// This is set to either the same as the DEFAULT_GEMINI_3_5_FLASH_MODEL const +// OR the SECONDARY_GEMINI_3_5_FLASH_MODEL depending on which is needed for +// the user's backend as determined by hasGemini35FlashGAAccess in +// packages/core/src/config/config.ts +export let DEFAULT_GEMINI_FLASH_MODEL = 'gemini-2.5-flash'; +export const DEFAULT_GEMINI_3_5_FLASH_MODEL = 'gemini-3.5-flash'; +// This is resolved to 3.5 flash in backends where it is used, +// however those backends do not expect to see the string gemini-3.5-flash +// so we need to provide this model as an alternative name in certain instances. +export const SECONDARY_GEMINI_3_5_FLASH_MODEL = 'gemini-3-flash'; + +// Used to set default flash models based on access +// TODO: Cleanup once the experiment for 3_5 flash rollut can be cleaned up. +export function setFlashModels(preview: string, defaultFlash: string) { + PREVIEW_GEMINI_FLASH_MODEL = preview; + DEFAULT_GEMINI_FLASH_MODEL = defaultFlash; +} +export const DEFAULT_GEMINI_FLASH_LITE_MODEL = 'gemini-3.1-flash-lite'; +/** @deprecated Gemini 3.1 Flash Lite is now GA. Use DEFAULT_GEMINI_FLASH_LITE_MODEL. */ +export const PREVIEW_GEMINI_FLASH_LITE_MODEL = 'none'; export const GEMMA_4_31B_IT_MODEL = 'gemma-4-31b-it'; export const GEMMA_4_26B_A4B_IT_MODEL = 'gemma-4-26b-a4b-it'; @@ -69,16 +90,20 @@ export const VALID_GEMINI_MODELS = new Set([ PREVIEW_GEMINI_3_1_MODEL, PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, PREVIEW_GEMINI_FLASH_MODEL, - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, + PREVIEW_GEMINI_FLASH_LITE_MODEL, DEFAULT_GEMINI_MODEL, DEFAULT_GEMINI_FLASH_MODEL, + DEFAULT_GEMINI_3_5_FLASH_MODEL, + SECONDARY_GEMINI_3_5_FLASH_MODEL, DEFAULT_GEMINI_FLASH_LITE_MODEL, GEMMA_4_31B_IT_MODEL, GEMMA_4_26B_A4B_IT_MODEL, ]); +/** @deprecated Use GEMINI_MODEL_ALIAS_AUTO instead. */ export const PREVIEW_GEMINI_MODEL_AUTO = 'auto-gemini-3'; +/** @deprecated Use GEMINI_MODEL_ALIAS_AUTO instead. */ export const DEFAULT_GEMINI_MODEL_AUTO = 'auto-gemini-2.5'; // Model aliases for user convenience. @@ -92,22 +117,41 @@ export const DEFAULT_GEMINI_EMBEDDING_MODEL = 'gemini-embedding-001'; // Cap the thinking at 8192 to prevent run-away thinking loops. export const DEFAULT_THINKING_MODE = 8192; +export function getAutoModelDescription( + hasAccessToPreview: boolean, + useGemini3_1: boolean = false, + useGemini3_5Flash: boolean = false, +) { + const proModel = hasAccessToPreview + ? useGemini3_1 + ? PREVIEW_GEMINI_3_1_MODEL + : PREVIEW_GEMINI_MODEL + : DEFAULT_GEMINI_MODEL; + const flashModel = hasAccessToPreview + ? useGemini3_5Flash + ? DEFAULT_GEMINI_3_5_FLASH_MODEL + : PREVIEW_GEMINI_FLASH_MODEL + : DEFAULT_GEMINI_FLASH_MODEL; + return `Let Gemini CLI decide the best model for the task: ${getDisplayString(proModel)}, ${getDisplayString(flashModel)}`; +} + /** - * Resolves the requested model alias (e.g., 'auto-gemini-3', 'pro', 'flash', 'flash-lite') + * Resolves the requested model alias (e.g., 'auto', 'pro', 'flash', 'flash-lite') * to a concrete model name. * * @param requestedModel The model alias or concrete model name requested by the user. * @param useGemini3_1 Whether to use Gemini 3.1 Pro Preview for auto/pro aliases. + * @param useGemini3_5Flash Whether to use Gemini 3.5 Flash GA. * @param hasAccessToPreview Whether the user has access to preview models. * @returns The resolved concrete model name. */ export function resolveModel( requestedModel: string, useGemini3_1: boolean = false, - useGemini3_1FlashLite: boolean = false, useCustomToolModel: boolean = false, hasAccessToPreview: boolean = true, config?: ModelCapabilityContext, + useGemini3_5Flash: boolean = false, ): string { // Defensive check against non-string inputs at runtime const normalizedModel = Array.isArray(requestedModel) @@ -119,9 +163,9 @@ export function resolveModel( if (config?.getExperimentalDynamicModelConfiguration?.() === true) { const resolved = config.modelConfigService.resolveModelId(normalizedModel, { useGemini3_1, - useGemini3_1FlashLite, useCustomTools: useCustomToolModel, hasAccessToPreview, + useGemini3_5Flash, }); if (!hasAccessToPreview && isPreviewModel(resolved, config)) { @@ -140,10 +184,16 @@ export function resolveModel( let resolved: string; switch (normalizedModel) { - case PREVIEW_GEMINI_MODEL: - case PREVIEW_GEMINI_MODEL_AUTO: case GEMINI_MODEL_ALIAS_AUTO: case GEMINI_MODEL_ALIAS_PRO: { + if (!hasAccessToPreview) { + resolved = DEFAULT_GEMINI_MODEL; + break; + } + // fallthrough + } + case PREVIEW_GEMINI_MODEL: + case PREVIEW_GEMINI_MODEL_AUTO: { if (useGemini3_1) { resolved = useCustomToolModel ? PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL @@ -158,13 +208,13 @@ export function resolveModel( break; } case GEMINI_MODEL_ALIAS_FLASH: { - resolved = PREVIEW_GEMINI_FLASH_MODEL; + resolved = useGemini3_5Flash + ? DEFAULT_GEMINI_FLASH_MODEL + : PREVIEW_GEMINI_FLASH_MODEL; break; } case GEMINI_MODEL_ALIAS_FLASH_LITE: { - resolved = useGemini3_1FlashLite - ? PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL - : DEFAULT_GEMINI_FLASH_LITE_MODEL; + resolved = DEFAULT_GEMINI_FLASH_LITE_MODEL; break; } default: { @@ -173,13 +223,23 @@ export function resolveModel( } } + if (resolved === 'none') { + return DEFAULT_GEMINI_FLASH_LITE_MODEL; + } + + if ( + useGemini3_5Flash && + isFlashModel(resolved) && + normalizedModel !== PREVIEW_GEMINI_FLASH_MODEL + ) { + return DEFAULT_GEMINI_FLASH_MODEL; + } + if (!hasAccessToPreview && isPreviewModel(resolved)) { // Downgrade to stable models if user lacks preview access. switch (resolved) { case PREVIEW_GEMINI_FLASH_MODEL: return DEFAULT_GEMINI_FLASH_MODEL; - case PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL: - return DEFAULT_GEMINI_FLASH_LITE_MODEL; case PREVIEW_GEMINI_MODEL: case PREVIEW_GEMINI_3_1_MODEL: case PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL: @@ -199,10 +259,21 @@ export function resolveModel( return resolved; } +function isFlashModel(model: string): boolean { + return ( + model === DEFAULT_GEMINI_FLASH_MODEL || + model === PREVIEW_GEMINI_FLASH_MODEL || + model === DEFAULT_GEMINI_3_5_FLASH_MODEL || + model === SECONDARY_GEMINI_3_5_FLASH_MODEL || + model === 'flash' || + model.endsWith('flash') + ); +} + /** * Resolves the appropriate model based on the classifier's decision. * - * @param requestedModel The current requested model (e.g. auto-gemini-2.5). + * @param requestedModel The current requested model (e.g. auto). * @param modelAlias The alias selected by the classifier ('flash' or 'pro'). * @param useGemini3_1 Whether to use Gemini 3.1 Pro Preview. * @param useCustomToolModel Whether to use the custom tool model. @@ -213,10 +284,10 @@ export function resolveClassifierModel( requestedModel: string, modelAlias: string, useGemini3_1: boolean = false, - useGemini3_1FlashLite: boolean = false, useCustomToolModel: boolean = false, hasAccessToPreview: boolean = true, config?: ModelCapabilityContext, + useGemini3_5Flash: boolean = false, ): string { if (config?.getExperimentalDynamicModelConfiguration?.() === true) { return config.modelConfigService.resolveClassifierModelId( @@ -224,9 +295,9 @@ export function resolveClassifierModel( requestedModel, { useGemini3_1, - useGemini3_1FlashLite, useCustomTools: useCustomToolModel, hasAccessToPreview, + useGemini3_5Flash, }, ); } @@ -240,17 +311,32 @@ export function resolveClassifierModel( } if ( requestedModel === PREVIEW_GEMINI_MODEL_AUTO || - requestedModel === PREVIEW_GEMINI_MODEL + requestedModel === PREVIEW_GEMINI_MODEL || + requestedModel === GEMINI_MODEL_ALIAS_AUTO ) { - return PREVIEW_GEMINI_FLASH_MODEL; + if (useGemini3_5Flash) { + return DEFAULT_GEMINI_FLASH_MODEL; + } + return hasAccessToPreview + ? PREVIEW_GEMINI_FLASH_MODEL + : DEFAULT_GEMINI_FLASH_MODEL; } - return resolveModel(GEMINI_MODEL_ALIAS_FLASH); + return resolveModel( + GEMINI_MODEL_ALIAS_FLASH, + false, + false, + hasAccessToPreview, + config, + useGemini3_5Flash, + ); } return resolveModel( requestedModel, useGemini3_1, - useGemini3_1FlashLite, useCustomToolModel, + hasAccessToPreview, + config, + useGemini3_5Flash, ); } @@ -266,6 +352,10 @@ export function getDisplayString( } switch (model) { + case 'gemini-3-flash': + return DEFAULT_GEMINI_3_5_FLASH_MODEL; + case GEMINI_MODEL_ALIAS_AUTO: + return 'Auto'; case PREVIEW_GEMINI_MODEL_AUTO: return 'Auto (Gemini 3)'; case DEFAULT_GEMINI_MODEL_AUTO: @@ -280,8 +370,8 @@ export function getDisplayString( return PREVIEW_GEMINI_FLASH_MODEL; case PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL: return PREVIEW_GEMINI_3_1_MODEL; - case PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL: - return PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL; + case PREVIEW_GEMINI_FLASH_LITE_MODEL: + return PREVIEW_GEMINI_FLASH_LITE_MODEL; default: return model; } @@ -298,6 +388,9 @@ export function isPreviewModel( model: string, config?: ModelCapabilityContext, ): boolean { + if (model === 'none') { + return false; + } if (config?.getExperimentalDynamicModelConfiguration?.() === true) { return ( config.modelConfigService.getModelDefinition(model)?.isPreview === true @@ -311,7 +404,7 @@ export function isPreviewModel( model === PREVIEW_GEMINI_FLASH_MODEL || model === PREVIEW_GEMINI_MODEL_AUTO || model === GEMINI_MODEL_ALIAS_AUTO || - model === PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL + model === PREVIEW_GEMINI_FLASH_LITE_MODEL ); } @@ -345,7 +438,7 @@ export function isGemini3Model( ): boolean { if (config?.getExperimentalDynamicModelConfiguration?.() === true) { // Legacy behavior resolves the model first. - const resolved = resolveModel(model, false, false, false, true, config); + const resolved = resolveModel(model, false, false, true, config); return ( config.modelConfigService.getModelDefinition(resolved)?.family === 'gemini-3' @@ -380,7 +473,7 @@ export function isCustomModel( config?: ModelCapabilityContext, ): boolean { if (config?.getExperimentalDynamicModelConfiguration?.() === true) { - const resolved = resolveModel(model, false, false, false, true, config); + const resolved = resolveModel(model, false, false, true, config); return ( config.modelConfigService.getModelDefinition(resolved)?.tier === 'custom' || !resolved.startsWith('gemini-') @@ -453,18 +546,17 @@ export function supportsMultimodalFunctionResponse( export function isActiveModel( model: string, useGemini3_1: boolean = false, - useGemini3_1FlashLite: boolean = false, useCustomToolModel: boolean = false, experimentalGemma: boolean = true, ): boolean { - if (!VALID_GEMINI_MODELS.has(model)) { + if (!VALID_GEMINI_MODELS.has(model) || model === 'none') { return false; } if (model === GEMMA_4_31B_IT_MODEL || model === GEMMA_4_26B_A4B_IT_MODEL) { return experimentalGemma; } - if (model === PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL) { - return useGemini3_1FlashLite; + if (model === PREVIEW_GEMINI_FLASH_LITE_MODEL) { + return false; } if (useGemini3_1) { if (model === PREVIEW_GEMINI_MODEL) { diff --git a/packages/core/src/context/chatCompressionService.ts b/packages/core/src/context/chatCompressionService.ts index 992ca67cf94..b60e96064be 100644 --- a/packages/core/src/context/chatCompressionService.ts +++ b/packages/core/src/context/chatCompressionService.ts @@ -30,7 +30,7 @@ import { PREVIEW_GEMINI_MODEL, PREVIEW_GEMINI_FLASH_MODEL, PREVIEW_GEMINI_3_1_MODEL, - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, + PREVIEW_GEMINI_FLASH_LITE_MODEL, } from '../config/models.js'; import { PreCompressTrigger } from '../hooks/types.js'; @@ -106,14 +106,16 @@ export function modelStringToModelConfigAlias(model: string): string { return 'chat-compression-3-pro'; case PREVIEW_GEMINI_FLASH_MODEL: return 'chat-compression-3-flash'; - case PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL: + case PREVIEW_GEMINI_FLASH_LITE_MODEL: + // fallthrough + case DEFAULT_GEMINI_FLASH_LITE_MODEL: return 'chat-compression-3.1-flash-lite'; + case 'gemini-2.5-flash-lite': + return 'chat-compression-2.5-flash-lite'; case DEFAULT_GEMINI_MODEL: return 'chat-compression-2.5-pro'; case DEFAULT_GEMINI_FLASH_MODEL: return 'chat-compression-2.5-flash'; - case DEFAULT_GEMINI_FLASH_LITE_MODEL: - return 'chat-compression-2.5-flash-lite'; default: return 'chat-compression-default'; } diff --git a/packages/core/src/core/client.ts b/packages/core/src/core/client.ts index 302b89d7f09..198daec45ba 100644 --- a/packages/core/src/core/client.ts +++ b/packages/core/src/core/client.ts @@ -604,10 +604,10 @@ export class GeminiClient { return resolveModel( this.config.getActiveModel(), this.config.getGemini31LaunchedSync?.() ?? false, - this.config.getGemini31FlashLiteLaunchedSync?.() ?? false, false, this.config.getHasAccessToPreviewModel?.() ?? true, this.config, + this.config.hasGemini35FlashGAAccess?.() ?? false, ); } diff --git a/packages/core/src/core/contentGenerator.ts b/packages/core/src/core/contentGenerator.ts index bcee8cfef4b..f2fa19a7871 100644 --- a/packages/core/src/core/contentGenerator.ts +++ b/packages/core/src/core/contentGenerator.ts @@ -205,12 +205,10 @@ export async function createContentGenerator( config.authType === AuthType.USE_GEMINI || config.authType === AuthType.USE_VERTEX_AI || ((await gcConfig.getGemini31Launched?.()) ?? false), - config.authType === AuthType.USE_GEMINI || - config.authType === AuthType.USE_VERTEX_AI || - ((await gcConfig.getGemini31FlashLiteLaunched?.()) ?? false), false, gcConfig.getHasAccessToPreviewModel?.() ?? true, gcConfig, + gcConfig.hasGemini35FlashGAAccess?.() ?? false, ); const customHeadersEnv = process.env['GEMINI_CLI_CUSTOM_HEADERS'] || undefined; diff --git a/packages/core/src/core/geminiChat.test.ts b/packages/core/src/core/geminiChat.test.ts index 05a27f8bbcc..267ead184c8 100644 --- a/packages/core/src/core/geminiChat.test.ts +++ b/packages/core/src/core/geminiChat.test.ts @@ -157,6 +157,7 @@ describe('GeminiChat', () => { getTelemetryLogPromptsEnabled: () => true, getTelemetryTracesEnabled: () => false, getUsageStatisticsEnabled: () => true, + hasGemini35FlashGAAccess: vi.fn().mockReturnValue(false), getDebugMode: () => false, getContentGeneratorConfig: vi.fn().mockImplementation(() => ({ authType: 'oauth-personal', diff --git a/packages/core/src/core/geminiChat.ts b/packages/core/src/core/geminiChat.ts index 6a728884a59..97c5b80116a 100644 --- a/packages/core/src/core/geminiChat.ts +++ b/packages/core/src/core/geminiChat.ts @@ -604,19 +604,16 @@ export class GeminiChat { const apiCall = async () => { const useGemini3_1 = (await this.context.config.getGemini31Launched?.()) ?? false; - const useGemini3_1FlashLite = - (await this.context.config.getGemini31FlashLiteLaunched?.()) ?? false; const hasAccessToPreview = this.context.config.getHasAccessToPreviewModel?.() ?? true; - // Default to the last used model (which respects arguments/availability selection) let modelToUse = resolveModel( lastModelToUse, useGemini3_1, - useGemini3_1FlashLite, false, hasAccessToPreview, this.context.config, + this.context.config.hasGemini35FlashGAAccess?.() ?? false, ); // If the active model has changed (e.g. due to a fallback updating the config), @@ -625,10 +622,10 @@ export class GeminiChat { modelToUse = resolveModel( this.context.config.getActiveModel(), useGemini3_1, - useGemini3_1FlashLite, false, hasAccessToPreview, this.context.config, + this.context.config.hasGemini35FlashGAAccess?.() ?? false, ); } @@ -688,10 +685,10 @@ export class GeminiChat { modelToUse = resolveModel( beforeModelResult.modifiedModel, useGemini3_1, - useGemini3_1FlashLite, false, hasAccessToPreview, this.context.config, + this.context.config.hasGemini35FlashGAAccess?.() ?? false, ); lastModelToUse = modelToUse; // Re-evaluate contentsToUse based on the new model's feature support diff --git a/packages/core/src/core/geminiChat_network_retry.test.ts b/packages/core/src/core/geminiChat_network_retry.test.ts index a2b2ee6e9ff..5db803b2e3f 100644 --- a/packages/core/src/core/geminiChat_network_retry.test.ts +++ b/packages/core/src/core/geminiChat_network_retry.test.ts @@ -98,6 +98,7 @@ describe('GeminiChat Network Retries', () => { getTelemetryLogPromptsEnabled: () => true, getTelemetryTracesEnabled: () => false, getUsageStatisticsEnabled: () => true, + hasGemini35FlashGAAccess: vi.fn().mockReturnValue(false), getDebugMode: () => false, getContentGeneratorConfig: vi.fn().mockReturnValue({ authType: 'oauth-personal', diff --git a/packages/core/src/core/prompts.test.ts b/packages/core/src/core/prompts.test.ts index 5937ed4900a..4072040e83c 100644 --- a/packages/core/src/core/prompts.test.ts +++ b/packages/core/src/core/prompts.test.ts @@ -22,7 +22,6 @@ import { PREVIEW_GEMINI_FLASH_MODEL, DEFAULT_GEMINI_MODEL_AUTO, DEFAULT_GEMINI_MODEL, - DEFAULT_GEMINI_FLASH_LITE_MODEL, } from '../config/models.js'; import { ApprovalMode } from '../policy/types.js'; import { DiscoveredMCPTool } from '../tools/mcp-tool.js'; @@ -250,9 +249,7 @@ describe('Core System Prompt (prompts.ts)', () => { }); it('should use legacy system prompt for non-preview model', () => { - vi.mocked(mockConfig.getActiveModel).mockReturnValue( - DEFAULT_GEMINI_FLASH_LITE_MODEL, - ); + vi.mocked(mockConfig.getActiveModel).mockReturnValue(DEFAULT_GEMINI_MODEL); const prompt = getCoreSystemPrompt(mockConfig); expect(prompt).toContain( 'You are an interactive CLI agent specializing in software engineering tasks.', @@ -267,9 +264,7 @@ describe('Core System Prompt (prompts.ts)', () => { }); it('should include the TASK MANAGEMENT PROTOCOL in legacy prompt when task tracker is enabled', () => { - vi.mocked(mockConfig.getActiveModel).mockReturnValue( - DEFAULT_GEMINI_FLASH_LITE_MODEL, - ); + vi.mocked(mockConfig.getActiveModel).mockReturnValue(DEFAULT_GEMINI_MODEL); vi.mocked(mockConfig.isTrackerEnabled).mockReturnValue(true); const prompt = getCoreSystemPrompt(mockConfig); expect(prompt).toContain('# TASK MANAGEMENT PROTOCOL'); @@ -662,7 +657,7 @@ describe('Core System Prompt (prompts.ts)', () => { it('should include Windows-specific shell efficiency commands on win32', () => { mockPlatform('win32'); vi.mocked(mockConfig.getActiveModel).mockReturnValue( - DEFAULT_GEMINI_FLASH_LITE_MODEL, + DEFAULT_GEMINI_MODEL, ); const prompt = getCoreSystemPrompt(mockConfig); expect(prompt).toContain( @@ -676,7 +671,7 @@ describe('Core System Prompt (prompts.ts)', () => { it('should include generic shell efficiency commands on non-Windows', () => { mockPlatform('linux'); vi.mocked(mockConfig.getActiveModel).mockReturnValue( - DEFAULT_GEMINI_FLASH_LITE_MODEL, + DEFAULT_GEMINI_MODEL, ); const prompt = getCoreSystemPrompt(mockConfig); expect(prompt).toContain("using commands like 'grep', 'tail', 'head'"); diff --git a/packages/core/src/fallback/handler.test.ts b/packages/core/src/fallback/handler.test.ts index 698a5d7cfbf..2f962345b9f 100644 --- a/packages/core/src/fallback/handler.test.ts +++ b/packages/core/src/fallback/handler.test.ts @@ -77,6 +77,7 @@ const createMockConfig = (overrides: Partial = {}): Config => getModel: vi.fn(() => MOCK_PRO_MODEL), getUserTier: vi.fn(() => undefined), isInteractive: vi.fn(() => false), + getHasAccessToPreviewModel: vi.fn(() => true), ...overrides, }) as unknown as Config; diff --git a/packages/core/src/prompts/promptProvider.ts b/packages/core/src/prompts/promptProvider.ts index 2c1f9e86529..2d8593dce5c 100644 --- a/packages/core/src/prompts/promptProvider.ts +++ b/packages/core/src/prompts/promptProvider.ts @@ -73,10 +73,10 @@ export class PromptProvider { const desiredModel = resolveModel( context.config.getActiveModel(), context.config.getGemini31LaunchedSync?.() ?? false, - context.config.getGemini31FlashLiteLaunchedSync?.() ?? false, false, context.config.getHasAccessToPreviewModel?.() ?? true, context.config, + context.config.hasGemini35FlashGAAccess?.() ?? false, ); const isModernModel = supportsModernFeatures(desiredModel); const activeSnippets = isModernModel ? snippets : legacySnippets; @@ -300,10 +300,10 @@ export class PromptProvider { const desiredModel = resolveModel( context.config.getActiveModel(), context.config.getGemini31LaunchedSync?.() ?? false, - context.config.getGemini31FlashLiteLaunchedSync?.() ?? false, false, context.config.getHasAccessToPreviewModel?.() ?? true, context.config, + context.config.hasGemini35FlashGAAccess?.() ?? false, ); const isModernModel = supportsModernFeatures(desiredModel); const activeSnippets = isModernModel ? snippets : legacySnippets; diff --git a/packages/core/src/routing/strategies/approvalModeStrategy.test.ts b/packages/core/src/routing/strategies/approvalModeStrategy.test.ts index 670c5c543e8..a92c8332d33 100644 --- a/packages/core/src/routing/strategies/approvalModeStrategy.test.ts +++ b/packages/core/src/routing/strategies/approvalModeStrategy.test.ts @@ -43,7 +43,6 @@ describe('ApprovalModeStrategy', () => { getApprovedPlanPath: vi.fn().mockReturnValue(undefined), getPlanModeRoutingEnabled: vi.fn().mockResolvedValue(true), getGemini31Launched: vi.fn().mockResolvedValue(false), - getGemini31FlashLiteLaunched: vi.fn().mockResolvedValue(false), getHasAccessToPreviewModel: vi.fn().mockReturnValue(true), getUseCustomToolModel: vi.fn().mockImplementation(async () => { const launched = await mockConfig.getGemini31Launched(); @@ -243,4 +242,22 @@ describe('ApprovalModeStrategy', () => { // Should resolve to Preview Flash (3.0) because resolveClassifierModel uses preview variants for Gemini 3 expect(decision?.model).toBe(PREVIEW_GEMINI_FLASH_MODEL); }); + + it('should route to DEFAULT_GEMINI_FLASH_MODEL when hasGemini35FlashGAAccess is true and plan is approved', async () => { + vi.mocked(mockConfig.getModel).mockReturnValue(GEMINI_MODEL_ALIAS_AUTO); + mockConfig.hasGemini35FlashGAAccess = vi.fn().mockReturnValue(true); + + vi.mocked(mockConfig.getApprovalMode).mockReturnValue(ApprovalMode.DEFAULT); + vi.mocked(mockConfig.getApprovedPlanPath).mockReturnValue( + '/path/to/plan.md', + ); + + const decision = await strategy.route( + mockContext, + mockConfig, + mockBaseLlmClient, + ); + + expect(decision?.model).toBe(DEFAULT_GEMINI_FLASH_MODEL); + }); }); diff --git a/packages/core/src/routing/strategies/approvalModeStrategy.ts b/packages/core/src/routing/strategies/approvalModeStrategy.ts index 8538aed054a..0d1b14a9ac2 100644 --- a/packages/core/src/routing/strategies/approvalModeStrategy.ts +++ b/packages/core/src/routing/strategies/approvalModeStrategy.ts @@ -48,17 +48,13 @@ export class ApprovalModeStrategy implements RoutingStrategy { const approvalMode = config.getApprovalMode(); const approvedPlanPath = config.getApprovedPlanPath(); - const [ - useGemini3_1, - useGemini3_1FlashLite, - useCustomToolModel, - hasAccessToPreview, - ] = await Promise.all([ - config.getGemini31Launched(), - config.getGemini31FlashLiteLaunched(), - config.getUseCustomToolModel(), - config.getHasAccessToPreviewModel(), - ]); + const [useGemini3_1, useCustomToolModel, hasAccessToPreview] = + await Promise.all([ + config.getGemini31Launched(), + config.getUseCustomToolModel(), + config.getHasAccessToPreviewModel(), + ]); + const useGemini3_5Flash = config.hasGemini35FlashGAAccess?.() ?? false; // 1. Planning Phase: If ApprovalMode === PLAN, explicitly route to the Pro model. if (approvalMode === ApprovalMode.PLAN) { @@ -66,10 +62,10 @@ export class ApprovalModeStrategy implements RoutingStrategy { model, GEMINI_MODEL_ALIAS_PRO, useGemini3_1, - useGemini3_1FlashLite, useCustomToolModel, hasAccessToPreview, config, + useGemini3_5Flash, ); return { model: proModel, @@ -85,10 +81,10 @@ export class ApprovalModeStrategy implements RoutingStrategy { model, GEMINI_MODEL_ALIAS_FLASH, useGemini3_1, - useGemini3_1FlashLite, useCustomToolModel, hasAccessToPreview, config, + useGemini3_5Flash, ); return { model: flashModel, diff --git a/packages/core/src/routing/strategies/classifierStrategy.test.ts b/packages/core/src/routing/strategies/classifierStrategy.test.ts index a81cd53de36..4a1e463e6a7 100644 --- a/packages/core/src/routing/strategies/classifierStrategy.test.ts +++ b/packages/core/src/routing/strategies/classifierStrategy.test.ts @@ -60,7 +60,6 @@ describe('ClassifierStrategy', () => { getModel: vi.fn().mockReturnValue(DEFAULT_GEMINI_MODEL_AUTO), getNumericalRoutingEnabled: vi.fn().mockResolvedValue(false), getGemini31Launched: vi.fn().mockResolvedValue(false), - getGemini31FlashLiteLaunched: vi.fn().mockResolvedValue(false), getUseCustomToolModel: vi.fn().mockImplementation(async () => { const launched = await mockConfig.getGemini31Launched(); const authType = mockConfig.getContentGeneratorConfig().authType; @@ -432,5 +431,27 @@ describe('ClassifierStrategy', () => { expect(decision?.model).toBe(PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL); }); + + it('should route to DEFAULT_GEMINI_FLASH_MODEL when hasGemini35FlashGAAccess is true', async () => { + mockConfig.hasGemini35FlashGAAccess = vi.fn().mockReturnValue(true); + vi.mocked(mockConfig.getModel).mockReturnValue(PREVIEW_GEMINI_MODEL_AUTO); + + const mockApiResponse = { + reasoning: 'Simple task', + model_choice: 'flash', + }; + vi.mocked(mockBaseLlmClient.generateJson).mockResolvedValue( + mockApiResponse, + ); + + const decision = await strategy.route( + mockContext, + mockConfig, + mockBaseLlmClient, + mockLocalLiteRtLmClient, + ); + + expect(decision?.model).toBe(DEFAULT_GEMINI_FLASH_MODEL); + }); }); }); diff --git a/packages/core/src/routing/strategies/classifierStrategy.ts b/packages/core/src/routing/strategies/classifierStrategy.ts index dda0f496655..30c16ea213b 100644 --- a/packages/core/src/routing/strategies/classifierStrategy.ts +++ b/packages/core/src/routing/strategies/classifierStrategy.ts @@ -172,21 +172,20 @@ export class ClassifierStrategy implements RoutingStrategy { const reasoning = routerResponse.reasoning; const latencyMs = Date.now() - startTime; - const [useGemini3_1, useGemini3_1FlashLite, useCustomToolModel] = - await Promise.all([ - config.getGemini31Launched(), - config.getGemini31FlashLiteLaunched(), - config.getUseCustomToolModel(), - ]); + const [useGemini3_1, useCustomToolModel] = await Promise.all([ + config.getGemini31Launched(), + config.getUseCustomToolModel(), + ]); + const useGemini3_5Flash = config.hasGemini35FlashGAAccess?.() ?? false; const selectedModel = normalizeModelId( resolveClassifierModel( normalizeModelId(model), routerResponse.model_choice, useGemini3_1, - useGemini3_1FlashLite, useCustomToolModel, config.getHasAccessToPreviewModel?.() ?? true, config, + useGemini3_5Flash, ), ); diff --git a/packages/core/src/routing/strategies/defaultStrategy.ts b/packages/core/src/routing/strategies/defaultStrategy.ts index c43e013ae8f..2eccedba262 100644 --- a/packages/core/src/routing/strategies/defaultStrategy.ts +++ b/packages/core/src/routing/strategies/defaultStrategy.ts @@ -26,10 +26,10 @@ export class DefaultStrategy implements TerminalStrategy { const defaultModel = resolveModel( config.getModel(), config.getGemini31LaunchedSync?.() ?? false, - config.getGemini31FlashLiteLaunchedSync?.() ?? false, false, config.getHasAccessToPreviewModel?.() ?? true, config, + config.hasGemini35FlashGAAccess?.() ?? false, ); return { model: defaultModel, diff --git a/packages/core/src/routing/strategies/fallbackStrategy.ts b/packages/core/src/routing/strategies/fallbackStrategy.ts index c911fb859ec..5b152ec409a 100644 --- a/packages/core/src/routing/strategies/fallbackStrategy.ts +++ b/packages/core/src/routing/strategies/fallbackStrategy.ts @@ -28,10 +28,10 @@ export class FallbackStrategy implements RoutingStrategy { const resolvedModel = resolveModel( requestedModel, config.getGemini31LaunchedSync?.() ?? false, - config.getGemini31FlashLiteLaunchedSync?.() ?? false, false, config.getHasAccessToPreviewModel?.() ?? true, config, + config.hasGemini35FlashGAAccess?.() ?? false, ); const service = config.getModelAvailabilityService(); const snapshot = service.snapshot(resolvedModel); diff --git a/packages/core/src/routing/strategies/gemmaClassifierStrategy.test.ts b/packages/core/src/routing/strategies/gemmaClassifierStrategy.test.ts index c66112c4064..c07b2188d25 100644 --- a/packages/core/src/routing/strategies/gemmaClassifierStrategy.test.ts +++ b/packages/core/src/routing/strategies/gemmaClassifierStrategy.test.ts @@ -12,6 +12,7 @@ import type { BaseLlmClient } from '../../core/baseLlmClient.js'; import { DEFAULT_GEMINI_FLASH_MODEL, DEFAULT_GEMINI_MODEL, + PREVIEW_GEMINI_MODEL_AUTO, } from '../../config/models.js'; import type { Content } from '@google/genai'; import { debugLogger } from '../../utils/debugLogger.js'; @@ -39,7 +40,6 @@ describe('GemmaClassifierStrategy', () => { getModel: () => DEFAULT_GEMINI_MODEL, getPreviewFeatures: () => false, getGemini31Launched: vi.fn().mockResolvedValue(false), - getGemini31FlashLiteLaunched: vi.fn().mockResolvedValue(false), getUseCustomToolModel: vi.fn().mockResolvedValue(false), getHasAccessToPreviewModel: vi.fn().mockReturnValue(true), } as unknown as Config; @@ -324,4 +324,24 @@ second message expect(lastTurn!.parts!.at(0)!.text).toEqual(expectedLastTurn); }); + + it('should route to DEFAULT_GEMINI_FLASH_MODEL when hasGemini35FlashGAAccess is true', async () => { + mockConfig.hasGemini35FlashGAAccess = vi.fn().mockReturnValue(true); + mockConfig.getModel = () => PREVIEW_GEMINI_MODEL_AUTO; + + const mockApiResponse = { + reasoning: 'Simple task', + model_choice: 'flash', + }; + mockGenerateJson.mockResolvedValue(mockApiResponse); + + const decision = await strategy.route( + mockContext, + mockConfig, + mockBaseLlmClient, + mockLocalLiteRtLmClient, + ); + + expect(decision?.model).toBe(DEFAULT_GEMINI_FLASH_MODEL); + }); }); diff --git a/packages/core/src/routing/strategies/gemmaClassifierStrategy.ts b/packages/core/src/routing/strategies/gemmaClassifierStrategy.ts index bf1c1b1b438..84ecce2e94e 100644 --- a/packages/core/src/routing/strategies/gemmaClassifierStrategy.ts +++ b/packages/core/src/routing/strategies/gemmaClassifierStrategy.ts @@ -210,26 +210,22 @@ ${formattedHistory} const reasoning = routerResponse.reasoning; const latencyMs = Date.now() - startTime; - const [ - useGemini3_1, - useGemini3_1FlashLite, - useCustomToolModel, - hasAccessToPreview, - ] = await Promise.all([ - config.getGemini31Launched(), - config.getGemini31FlashLiteLaunched(), - config.getUseCustomToolModel(), - config.getHasAccessToPreviewModel?.() ?? true, - ]); + const [useGemini3_1, useCustomToolModel, hasAccessToPreview] = + await Promise.all([ + config.getGemini31Launched(), + config.getUseCustomToolModel(), + config.getHasAccessToPreviewModel(), + ]); + const useGemini3_5Flash = config.hasGemini35FlashGAAccess?.() ?? false; const selectedModel = resolveClassifierModel( context.requestedModel ?? config.getModel(), routerResponse.model_choice, useGemini3_1, - useGemini3_1FlashLite, useCustomToolModel, hasAccessToPreview, config, + useGemini3_5Flash, ); return { diff --git a/packages/core/src/routing/strategies/numericalClassifierStrategy.test.ts b/packages/core/src/routing/strategies/numericalClassifierStrategy.test.ts index fccd1c53eba..c7efc95280c 100644 --- a/packages/core/src/routing/strategies/numericalClassifierStrategy.test.ts +++ b/packages/core/src/routing/strategies/numericalClassifierStrategy.test.ts @@ -20,6 +20,7 @@ import { PREVIEW_GEMINI_MODEL_AUTO, DEFAULT_GEMINI_MODEL_AUTO, DEFAULT_GEMINI_MODEL, + DEFAULT_GEMINI_FLASH_MODEL, } from '../../config/models.js'; import { promptIdContext } from '../../utils/promptIdContext.js'; import type { Content } from '@google/genai'; @@ -63,7 +64,6 @@ describe('NumericalClassifierStrategy', () => { getResolvedClassifierThreshold: vi.fn().mockResolvedValue(90), getClassifierThreshold: vi.fn().mockResolvedValue(undefined), getGemini31Launched: vi.fn().mockResolvedValue(false), - getGemini31FlashLiteLaunched: vi.fn().mockResolvedValue(false), getUseCustomToolModel: vi.fn().mockImplementation(async () => { const launched = await mockConfig.getGemini31Launched(); const authType = mockConfig.getContentGeneratorConfig().authType; @@ -796,5 +796,27 @@ describe('NumericalClassifierStrategy', () => { expect(decision?.model).toBe(PREVIEW_GEMINI_3_1_MODEL); }); + + it('should route to DEFAULT_GEMINI_FLASH_MODEL when hasGemini35FlashGAAccess is true', async () => { + mockConfig.hasGemini35FlashGAAccess = vi.fn().mockReturnValue(true); + vi.mocked(mockConfig.getModel).mockReturnValue(PREVIEW_GEMINI_MODEL_AUTO); + + const mockApiResponse = { + complexity_reasoning: 'Simple task', + complexity_score: 10, + }; + vi.mocked(mockBaseLlmClient.generateJson).mockResolvedValue( + mockApiResponse, + ); + + const decision = await strategy.route( + mockContext, + mockConfig, + mockBaseLlmClient, + mockLocalLiteRtLmClient, + ); + + expect(decision?.model).toBe(DEFAULT_GEMINI_FLASH_MODEL); + }); }); }); diff --git a/packages/core/src/routing/strategies/numericalClassifierStrategy.ts b/packages/core/src/routing/strategies/numericalClassifierStrategy.ts index a4906014360..96f03d924fc 100644 --- a/packages/core/src/routing/strategies/numericalClassifierStrategy.ts +++ b/packages/core/src/routing/strategies/numericalClassifierStrategy.ts @@ -167,21 +167,20 @@ export class NumericalClassifierStrategy implements RoutingStrategy { const { threshold, groupLabel, modelAlias } = await this.getRoutingDecision(score, config); - const [useGemini3_1, useGemini3_1FlashLite, useCustomToolModel] = - await Promise.all([ - config.getGemini31Launched(), - config.getGemini31FlashLiteLaunched(), - config.getUseCustomToolModel(), - ]); + const [useGemini3_1, useCustomToolModel] = await Promise.all([ + config.getGemini31Launched(), + config.getUseCustomToolModel(), + ]); + const useGemini3_5Flash = config.hasGemini35FlashGAAccess?.() ?? false; const selectedModel = normalizeModelId( resolveClassifierModel( normalizeModelId(model), modelAlias, useGemini3_1, - useGemini3_1FlashLite, useCustomToolModel, config.getHasAccessToPreviewModel?.() ?? true, config, + useGemini3_5Flash, ), ); diff --git a/packages/core/src/routing/strategies/overrideStrategy.ts b/packages/core/src/routing/strategies/overrideStrategy.ts index e93c0870ef0..e01bda48795 100644 --- a/packages/core/src/routing/strategies/overrideStrategy.ts +++ b/packages/core/src/routing/strategies/overrideStrategy.ts @@ -38,10 +38,10 @@ export class OverrideStrategy implements RoutingStrategy { model: resolveModel( overrideModel, config.getGemini31LaunchedSync?.() ?? false, - config.getGemini31FlashLiteLaunchedSync?.() ?? false, false, config.getHasAccessToPreviewModel?.() ?? true, config, + config.hasGemini35FlashGAAccess?.() ?? false, ), metadata: { source: this.name, diff --git a/packages/core/src/services/modelConfigService.test.ts b/packages/core/src/services/modelConfigService.test.ts index 70df1aa7b03..76da7a2642d 100644 --- a/packages/core/src/services/modelConfigService.test.ts +++ b/packages/core/src/services/modelConfigService.test.ts @@ -1019,6 +1019,79 @@ describe('ModelConfigService', () => { }); }); + // Resolves a model ID to a concrete model ID based on the provided context. + describe('resolveModelId', () => { + it('should resolve based on useGemini3_5Flash condition', () => { + const config: ModelConfigServiceConfig = { + modelIdResolutions: { + flash: { + default: 'gemini-2.0-flash', + contexts: [ + { + condition: { useGemini3_5Flash: true }, + target: 'gemini-3.5-flash', + }, + ], + }, + }, + }; + const service = new ModelConfigService(config); + + expect(service.resolveModelId('flash', { useGemini3_5Flash: true })).toBe( + 'gemini-3.5-flash', + ); + expect( + service.resolveModelId('flash', { useGemini3_5Flash: false }), + ).toBe('gemini-2.0-flash'); + expect(service.resolveModelId('flash', {})).toBe('gemini-2.0-flash'); + }); + + it('should resolve based on complex conditions including useGemini3_5Flash', () => { + const config: ModelConfigServiceConfig = { + modelIdResolutions: { + 'gemini-flash': { + default: 'gemini-3-flash-preview', + contexts: [ + { + condition: { + useGemini3_5Flash: false, + hasAccessToPreview: false, + }, + target: 'gemini-2.5-flash', + }, + { + condition: { useGemini3_5Flash: true }, + target: 'gemini-3.5-flash', + }, + ], + }, + }, + }; + const service = new ModelConfigService(config); + + // Case 1: GA Access granted + expect( + service.resolveModelId('gemini-flash', { useGemini3_5Flash: true }), + ).toBe('gemini-3.5-flash'); + + // Case 2: GA Access denied, but has preview access + expect( + service.resolveModelId('gemini-flash', { + useGemini3_5Flash: false, + hasAccessToPreview: true, + }), + ).toBe('gemini-3-flash-preview'); + + // Case 3: GA Access denied AND no preview access + expect( + service.resolveModelId('gemini-flash', { + useGemini3_5Flash: false, + hasAccessToPreview: false, + }), + ).toBe('gemini-2.5-flash'); + }); + }); + describe('getAvailableModelOptions', () => { it('should filter out Pro models when hasAccessToProModel is false', () => { const config: ModelConfigServiceConfig = { diff --git a/packages/core/src/services/modelConfigService.ts b/packages/core/src/services/modelConfigService.ts index a6d59365d7f..f82f9267d1d 100644 --- a/packages/core/src/services/modelConfigService.ts +++ b/packages/core/src/services/modelConfigService.ts @@ -9,8 +9,8 @@ import type { ModelPolicy } from '../availability/modelPolicy.js'; import { getDisplayString, PREVIEW_GEMINI_3_1_MODEL, - PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, isProModel, + getAutoModelDescription, } from '../config/models.js'; // The primary key for the ModelConfig is the model string. However, we also @@ -97,6 +97,7 @@ export interface ModelResolution { export interface ResolutionContext { useGemini3_1?: boolean; useGemini3_1FlashLite?: boolean; + useGemini3_5Flash?: boolean; useCustomTools?: boolean; hasAccessToPreview?: boolean; hasAccessToProModel?: boolean; @@ -107,6 +108,7 @@ export interface ResolutionContext { export interface ResolutionCondition { useGemini3_1?: boolean; useGemini3_1FlashLite?: boolean; + useGemini3_5Flash?: boolean; useCustomTools?: boolean; hasAccessToPreview?: boolean; /** Matches if the current model is in this list. */ @@ -155,7 +157,7 @@ export class ModelConfigService { const definitions = this.config.modelDefinitions ?? {}; const shouldShowPreviewModels = context.hasAccessToPreview ?? false; const useGemini31 = context.useGemini3_1 ?? false; - const useGemini31FlashLite = context.useGemini3_1FlashLite ?? false; + const useGemini3_5Flash = context.useGemini3_5Flash ?? false; const mainOptions = Object.entries(definitions) .filter(([_, m]) => { @@ -164,18 +166,25 @@ export class ModelConfigService { if (m.tier !== 'auto') return false; return true; }) - .map(([id, m]) => ({ - modelId: id, - name: m.displayName ?? getDisplayString(id), - description: - id === 'auto-gemini-3' && useGemini31 - ? (m.dialogDescription ?? '').replace( - 'gemini-3-pro', - 'gemini-3.1-pro', - ) - : (m.dialogDescription ?? ''), - tier: m.tier ?? 'auto', - })); + .map(([id, m]) => { + let description = m.dialogDescription ?? ''; + if (id === 'auto') { + description = getAutoModelDescription( + shouldShowPreviewModels, + useGemini31, + useGemini3_5Flash, + ); + } else if (id === 'auto-gemini-3' && useGemini31) { + description = description.replace('gemini-3-pro', 'gemini-3.1-pro'); + } + + return { + modelId: id, + name: m.displayName ?? getDisplayString(id), + description, + tier: m.tier ?? 'auto', + }; + }); const manualOptions = Object.entries(definitions) .filter(([id, m]) => { @@ -185,15 +194,12 @@ export class ModelConfigService { if (context.hasAccessToProModel === false && isProModel(id)) return false; if (id === PREVIEW_GEMINI_3_1_MODEL && !useGemini31) return false; - if (id === PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL && !useGemini31FlashLite) - return false; return true; }) .map(([id, m]) => { const resolvedId = this.resolveModelId(id, context); const titleId = this.resolveModelId(id, { useGemini3_1: useGemini31, - useGemini3_1FlashLite: useGemini31FlashLite, }); return { modelId: resolvedId, @@ -248,6 +254,8 @@ export class ModelConfigService { return value === context.useGemini3_1; case 'useGemini3_1FlashLite': return value === context.useGemini3_1FlashLite; + case 'useGemini3_5Flash': + return value === context.useGemini3_5Flash; case 'useCustomTools': return value === context.useCustomTools; case 'hasAccessToPreview': @@ -337,6 +345,10 @@ export class ModelConfigService { this.runtimeOverrides.push(override); } + clearRuntimeOverrides(): void { + this.runtimeOverrides.length = 0; + } + /** * Resolves a model configuration by merging settings from aliases and applying overrides. * diff --git a/packages/core/src/services/test-data/resolved-aliases-retry.golden.json b/packages/core/src/services/test-data/resolved-aliases-retry.golden.json index bab67caedd4..aa470d45fef 100644 --- a/packages/core/src/services/test-data/resolved-aliases-retry.golden.json +++ b/packages/core/src/services/test-data/resolved-aliases-retry.golden.json @@ -61,6 +61,42 @@ "topK": 64 } }, + "gemini-3.1-pro-preview": { + "model": "gemini-3.1-pro-preview", + "generateContentConfig": { + "temperature": 1, + "topP": 0.95, + "thinkingConfig": { + "includeThoughts": true, + "thinkingLevel": "HIGH" + }, + "topK": 64 + } + }, + "gemini-3.1-pro-preview-customtools": { + "model": "gemini-3.1-pro-preview-customtools", + "generateContentConfig": { + "temperature": 1, + "topP": 0.95, + "thinkingConfig": { + "includeThoughts": true, + "thinkingLevel": "HIGH" + }, + "topK": 64 + } + }, + "gemini-3.1-flash-lite-preview": { + "model": "gemini-3.1-flash-lite-preview", + "generateContentConfig": { + "temperature": 1, + "topP": 0.95, + "thinkingConfig": { + "includeThoughts": true, + "thinkingLevel": "HIGH" + }, + "topK": 64 + } + }, "gemini-2.5-pro": { "model": "gemini-2.5-pro", "generateContentConfig": { @@ -97,6 +133,30 @@ "topK": 64 } }, + "gemini-3.1-flash-lite": { + "model": "gemini-3.1-flash-lite", + "generateContentConfig": { + "temperature": 1, + "topP": 0.95, + "thinkingConfig": { + "includeThoughts": true, + "thinkingLevel": "HIGH" + }, + "topK": 64 + } + }, + "gemini-3.5-flash": { + "model": "gemini-3.5-flash", + "generateContentConfig": { + "temperature": 1, + "topP": 0.95, + "thinkingConfig": { + "includeThoughts": true, + "thinkingLevel": "HIGH" + }, + "topK": 64 + } + }, "gemma-4-31b-it": { "model": "gemma-4-31b-it", "generateContentConfig": { @@ -135,8 +195,15 @@ "topP": 1 } }, + "gemini-3.5-flash-base": { + "model": "gemini-3.5-flash", + "generateContentConfig": { + "temperature": 0, + "topP": 1 + } + }, "classifier": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0, "topP": 1, @@ -147,7 +214,7 @@ } }, "prompt-completion": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0.3, "topP": 1, @@ -158,7 +225,7 @@ } }, "fast-ack-helper": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0.2, "topP": 1, @@ -169,7 +236,7 @@ } }, "edit-corrector": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0, "topP": 1, @@ -179,7 +246,7 @@ } }, "summarizer-default": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0, "topP": 1, @@ -187,7 +254,7 @@ } }, "summarizer-shell": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0, "topP": 1, @@ -273,7 +340,7 @@ "generateContentConfig": {} }, "chat-compression-3.1-flash-lite": { - "model": "gemini-3.1-flash-lite-preview", + "model": "gemini-3.1-flash-lite", "generateContentConfig": {} }, "chat-compression-2.5-pro": { diff --git a/packages/core/src/services/test-data/resolved-aliases.golden.json b/packages/core/src/services/test-data/resolved-aliases.golden.json index bab67caedd4..aa470d45fef 100644 --- a/packages/core/src/services/test-data/resolved-aliases.golden.json +++ b/packages/core/src/services/test-data/resolved-aliases.golden.json @@ -61,6 +61,42 @@ "topK": 64 } }, + "gemini-3.1-pro-preview": { + "model": "gemini-3.1-pro-preview", + "generateContentConfig": { + "temperature": 1, + "topP": 0.95, + "thinkingConfig": { + "includeThoughts": true, + "thinkingLevel": "HIGH" + }, + "topK": 64 + } + }, + "gemini-3.1-pro-preview-customtools": { + "model": "gemini-3.1-pro-preview-customtools", + "generateContentConfig": { + "temperature": 1, + "topP": 0.95, + "thinkingConfig": { + "includeThoughts": true, + "thinkingLevel": "HIGH" + }, + "topK": 64 + } + }, + "gemini-3.1-flash-lite-preview": { + "model": "gemini-3.1-flash-lite-preview", + "generateContentConfig": { + "temperature": 1, + "topP": 0.95, + "thinkingConfig": { + "includeThoughts": true, + "thinkingLevel": "HIGH" + }, + "topK": 64 + } + }, "gemini-2.5-pro": { "model": "gemini-2.5-pro", "generateContentConfig": { @@ -97,6 +133,30 @@ "topK": 64 } }, + "gemini-3.1-flash-lite": { + "model": "gemini-3.1-flash-lite", + "generateContentConfig": { + "temperature": 1, + "topP": 0.95, + "thinkingConfig": { + "includeThoughts": true, + "thinkingLevel": "HIGH" + }, + "topK": 64 + } + }, + "gemini-3.5-flash": { + "model": "gemini-3.5-flash", + "generateContentConfig": { + "temperature": 1, + "topP": 0.95, + "thinkingConfig": { + "includeThoughts": true, + "thinkingLevel": "HIGH" + }, + "topK": 64 + } + }, "gemma-4-31b-it": { "model": "gemma-4-31b-it", "generateContentConfig": { @@ -135,8 +195,15 @@ "topP": 1 } }, + "gemini-3.5-flash-base": { + "model": "gemini-3.5-flash", + "generateContentConfig": { + "temperature": 0, + "topP": 1 + } + }, "classifier": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0, "topP": 1, @@ -147,7 +214,7 @@ } }, "prompt-completion": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0.3, "topP": 1, @@ -158,7 +225,7 @@ } }, "fast-ack-helper": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0.2, "topP": 1, @@ -169,7 +236,7 @@ } }, "edit-corrector": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0, "topP": 1, @@ -179,7 +246,7 @@ } }, "summarizer-default": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0, "topP": 1, @@ -187,7 +254,7 @@ } }, "summarizer-shell": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0, "topP": 1, @@ -273,7 +340,7 @@ "generateContentConfig": {} }, "chat-compression-3.1-flash-lite": { - "model": "gemini-3.1-flash-lite-preview", + "model": "gemini-3.1-flash-lite", "generateContentConfig": {} }, "chat-compression-2.5-pro": { diff --git a/packages/core/src/tools/shell.ts b/packages/core/src/tools/shell.ts index 4c695ab5ee8..555155fcd85 100644 --- a/packages/core/src/tools/shell.ts +++ b/packages/core/src/tools/shell.ts @@ -968,18 +968,24 @@ export class ShellToolInvocation extends BaseToolInvocation< if (timeoutTimer) clearTimeout(timeoutTimer); signal.removeEventListener('abort', onAbort); timeoutController.signal.removeEventListener('abort', onAbort); - if (tempFilePath) { - try { - await fsPromises.unlink(tempFilePath); - } catch { - // Ignore errors during unlink + + // Only clean up if NOT running in background. + // Background processes need the temp directory and PID file to remain + // available until they exit. + if (!this.params.is_background) { + if (tempFilePath) { + try { + await fsPromises.unlink(tempFilePath); + } catch { + // Ignore errors during unlink + } } - } - if (tempDir) { - try { - await fsPromises.rm(tempDir, { recursive: true, force: true }); - } catch { - // Ignore errors during rm + if (tempDir) { + try { + await fsPromises.rm(tempDir, { recursive: true, force: true }); + } catch { + // Ignore errors during rm + } } } } diff --git a/packages/core/test-setup.ts b/packages/core/test-setup.ts index d7303695780..dc1d7ac932d 100644 --- a/packages/core/test-setup.ts +++ b/packages/core/test-setup.ts @@ -55,5 +55,9 @@ vi.mock('./src/config/storage.js', async (importOriginal) => { (actual.Storage.prototype as any).getProjectIdentifier = vi.fn( () => 'project-slug', ); + actual.Storage.getUserPoliciesDir = vi.fn(() => '/tmp/mock-user-policies'); + actual.Storage.getSystemPoliciesDir = vi.fn( + () => '/tmp/mock-system-policies', + ); return actual; }); diff --git a/schemas/settings.schema.json b/schemas/settings.schema.json index f4c89db862b..f78ee6b924d 100644 --- a/schemas/settings.schema.json +++ b/schemas/settings.schema.json @@ -51,9 +51,34 @@ "properties": { "preferredEditor": { "title": "Preferred Editor", - "description": "The preferred editor to open files in.", - "markdownDescription": "The preferred editor to open files in.\n\n- Category: `General`\n- Requires restart: `no`", - "type": "string" + "description": "The preferred editor to open files in. Must be one of the built-in supported identifiers. Use /editor in the CLI to pick interactively, or leave unset to use $VISUAL/$EDITOR.", + "markdownDescription": "The preferred editor to open files in. Must be one of the built-in supported identifiers. Use /editor in the CLI to pick interactively, or leave unset to use $VISUAL/$EDITOR.\n\n- Category: `General`\n- Requires restart: `no`", + "type": "string", + "enum": [ + "vscode", + "vscodium", + "windsurf", + "cursor", + "zed", + "antigravity", + "sublimetext", + "lapce", + "nova", + "bbedit", + "vim", + "neovim", + "emacs", + "hx", + "emacsclient", + "micro" + ] + }, + "openEditorInNewWindow": { + "title": "Open Editor in New Window", + "description": "Open VS Code-family editors in a new window when editing files.", + "markdownDescription": "Open VS Code-family editors in a new window when editing files.\n\n- Category: `General`\n- Requires restart: `no`\n- Default: `false`", + "default": false, + "type": "boolean" }, "vimMode": { "title": "Vim Mode", @@ -216,6 +241,13 @@ "markdownDescription": "Enable the Topic & Update communication model for reduced chattiness and structured progress reporting.\n\n- Category: `General`\n- Requires restart: `no`\n- Default: `true`", "default": true, "type": "boolean" + }, + "logRagSnippets": { + "title": "Log RAG Snippets", + "description": "Log full Code Customization (RAG) retrieved snippets to a local file for debugging.", + "markdownDescription": "Log full Code Customization (RAG) retrieved snippets to a local file for debugging.\n\n- Category: `General`\n- Requires restart: `no`\n- Default: `false`", + "default": false, + "type": "boolean" } }, "additionalProperties": false @@ -709,7 +741,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 \"gemma-4-31b-it\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemma-4-31b-it\"\n }\n },\n \"gemma-4-26b-a4b-it\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemma-4-26b-a4b-it\"\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 \"context-snapshotter\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingLevel\": \"HIGH\"\n },\n \"temperature\": 1,\n \"topP\": 0.95,\n \"topK\": 64\n }\n }\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-3.1-flash-lite\": {\n \"modelConfig\": {\n \"model\": \"gemini-3.1-flash-lite-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 \"agent-history-provider-summarizer\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-flash-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 \"gemma-4-31b-it\": {\n \"displayName\": \"gemma-4-31b-it\",\n \"tier\": \"custom\",\n \"family\": \"gemma-4\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"gemma-4-26b-a4b-it\": {\n \"displayName\": \"gemma-4-26b-a4b-it\",\n \"tier\": \"custom\",\n \"family\": \"gemma-4\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\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 \"gemma-4-31b-it\": {\n \"default\": \"gemma-4-31b-it\"\n },\n \"gemma-4-26b-a4b-it\": {\n \"default\": \"gemma-4-26b-a4b-it\"\n },\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 \"condition\": {\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\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 \"gemini-3.1-flash-lite-preview\": {\n \"default\": \"gemini-3.1-flash-lite-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_1FlashLite\": false\n },\n \"target\": \"gemini-2.5-flash-lite\"\n }\n ]\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 \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_1FlashLite\": true\n },\n \"target\": \"gemini-3.1-flash-lite-preview\"\n }\n ]\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 \"maxAttempts\": 10,\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 \"auto-preview\": [\n {\n \"model\": \"gemini-3-pro-preview\",\n \"maxAttempts\": 3,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"silent\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-3-flash-preview\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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 \"auto-default\": [\n {\n \"model\": \"gemini-2.5-pro\",\n \"maxAttempts\": 3,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"silent\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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}`", + "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-3.1-pro-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3.1-pro-preview\"\n }\n },\n \"gemini-3.1-pro-preview-customtools\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3.1-pro-preview-customtools\"\n }\n },\n \"gemini-3.1-flash-lite-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3.1-flash-lite-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-3.1-flash-lite\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3.1-flash-lite\"\n }\n },\n \"gemini-3.5-flash\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3.5-flash\"\n }\n },\n \"gemma-4-31b-it\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemma-4-31b-it\"\n }\n },\n \"gemma-4-26b-a4b-it\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemma-4-26b-a4b-it\"\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 \"gemini-3.5-flash-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-3.5-flash\"\n }\n },\n \"classifier\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"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\": \"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\": \"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\": \"flash-lite\",\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"summarizer-default\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"summarizer-shell\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"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 \"context-snapshotter\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingLevel\": \"HIGH\"\n },\n \"temperature\": 1,\n \"topP\": 0.95,\n \"topK\": 64\n }\n }\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-3.1-flash-lite\": {\n \"modelConfig\": {\n \"model\": \"gemini-3.1-flash-lite\"\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 \"agent-history-provider-summarizer\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-flash-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\": {\n \"tier\": \"flash-lite\",\n \"family\": \"gemini-3\",\n \"isPreview\": false,\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-3.5-flash\": {\n \"tier\": \"flash\",\n \"family\": \"gemini-3\",\n \"isPreview\": false,\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 \"gemma-4-31b-it\": {\n \"displayName\": \"gemma-4-31b-it\",\n \"tier\": \"custom\",\n \"family\": \"gemma-4\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"gemma-4-26b-a4b-it\": {\n \"displayName\": \"gemma-4-26b-a4b-it\",\n \"tier\": \"custom\",\n \"family\": \"gemma-4\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"auto\": {\n \"displayName\": \"Auto\",\n \"tier\": \"auto\",\n \"isPreview\": true,\n \"isVisible\": true,\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 \"tier\": \"auto\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": false\n },\n \"auto-gemini-2.5\": {\n \"tier\": \"auto\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": false\n }\n },\n \"modelIdResolutions\": {\n \"gemma-4-31b-it\": {\n \"default\": \"gemma-4-31b-it\"\n },\n \"gemma-4-26b-a4b-it\": {\n \"default\": \"gemma-4-26b-a4b-it\"\n },\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 \"condition\": {\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\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 \"useGemini3_5Flash\": true\n },\n \"target\": \"gemini-3.5-flash\"\n },\n {\n \"condition\": {\n \"hasAccessToPreview\": false,\n \"useGemini3_5Flash\": false\n },\n \"target\": \"gemini-2.5-flash\"\n }\n ]\n },\n \"gemini-3.5-flash\": {\n \"default\": \"gemini-3.5-flash\",\n \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_5Flash\": false,\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n },\n {\n \"condition\": {\n \"useGemini3_5Flash\": false\n },\n \"target\": \"gemini-3-flash-preview\"\n }\n ]\n },\n \"gemini-2.5-flash\": {\n \"default\": \"gemini-2.5-flash\",\n \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_5Flash\": true\n },\n \"target\": \"gemini-3.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\": {\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 \"gemini-3.1-flash-lite\": {\n \"default\": \"gemini-3.1-flash-lite\"\n },\n \"flash\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_5Flash\": true\n },\n \"target\": \"gemini-3.5-flash\"\n },\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n }\n ]\n },\n \"flash-lite\": {\n \"default\": \"gemini-3.1-flash-lite\"\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-gemini-2.5\": {\n \"default\": \"gemini-2.5-pro\"\n }\n },\n \"classifierIdResolutions\": {\n \"flash\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_5Flash\": true\n },\n \"target\": \"gemini-3.5-flash\"\n },\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n },\n {\n \"condition\": {\n \"requestedModels\": [\n \"gemini-2.5-pro\",\n \"auto-gemini-2.5\"\n ]\n },\n \"target\": \"gemini-2.5-flash\"\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 \"requestedModels\": [\n \"gemini-2.5-pro\",\n \"auto-gemini-2.5\"\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 \"maxAttempts\": 10,\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 \"auto-preview\": [\n {\n \"model\": \"gemini-3-pro-preview\",\n \"maxAttempts\": 3,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"silent\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-3-flash-preview\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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 \"auto-default\": [\n {\n \"model\": \"gemini-2.5-pro\",\n \"maxAttempts\": 3,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"silent\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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\": \"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": { @@ -765,6 +797,24 @@ "model": "gemini-3-flash-preview" } }, + "gemini-3.1-pro-preview": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-pro-preview" + } + }, + "gemini-3.1-pro-preview-customtools": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-pro-preview-customtools" + } + }, + "gemini-3.1-flash-lite-preview": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-flash-lite-preview" + } + }, "gemini-2.5-pro": { "extends": "chat-base-2.5", "modelConfig": { @@ -783,6 +833,18 @@ "model": "gemini-2.5-flash-lite" } }, + "gemini-3.1-flash-lite": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-flash-lite" + } + }, + "gemini-3.5-flash": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.5-flash" + } + }, "gemma-4-31b-it": { "extends": "chat-base-3", "modelConfig": { @@ -807,10 +869,16 @@ "model": "gemini-3-flash-preview" } }, + "gemini-3.5-flash-base": { + "extends": "base", + "modelConfig": { + "model": "gemini-3.5-flash" + } + }, "classifier": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "maxOutputTokens": 1024, "thinkingConfig": { @@ -822,7 +890,7 @@ "prompt-completion": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0.3, "maxOutputTokens": 16000, @@ -835,7 +903,7 @@ "fast-ack-helper": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0.2, "maxOutputTokens": 120, @@ -848,7 +916,7 @@ "edit-corrector": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "thinkingConfig": { "thinkingBudget": 0 @@ -859,7 +927,7 @@ "summarizer-default": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "maxOutputTokens": 2000 } @@ -868,7 +936,7 @@ "summarizer-shell": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "maxOutputTokens": 2000 } @@ -945,7 +1013,7 @@ }, "chat-compression-3.1-flash-lite": { "modelConfig": { - "model": "gemini-3.1-flash-lite-preview" + "model": "gemini-3.1-flash-lite" } }, "chat-compression-2.5-pro": { @@ -988,10 +1056,10 @@ } ], "modelDefinitions": { - "gemini-3.1-flash-lite-preview": { + "gemini-3.1-flash-lite": { "tier": "flash-lite", "family": "gemini-3", - "isPreview": true, + "isPreview": false, "isVisible": true, "features": { "thinking": false, @@ -1038,6 +1106,16 @@ "multimodalToolUse": true } }, + "gemini-3.5-flash": { + "tier": "flash", + "family": "gemini-3", + "isPreview": false, + "isVisible": true, + "features": { + "thinking": false, + "multimodalToolUse": true + } + }, "gemini-2.5-pro": { "tier": "pro", "family": "gemini-2.5", @@ -1091,9 +1169,10 @@ } }, "auto": { + "displayName": "Auto", "tier": "auto", "isPreview": true, - "isVisible": false, + "isVisible": true, "features": { "thinking": true, "multimodalToolUse": false @@ -1127,26 +1206,16 @@ } }, "auto-gemini-3": { - "displayName": "Auto (Gemini 3)", "tier": "auto", + "family": "gemini-3", "isPreview": true, - "isVisible": true, - "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash", - "features": { - "thinking": true, - "multimodalToolUse": false - } + "isVisible": false }, "auto-gemini-2.5": { - "displayName": "Auto (Gemini 2.5)", "tier": "auto", + "family": "gemini-2.5", "isPreview": false, - "isVisible": true, - "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash", - "features": { - "thinking": false, - "multimodalToolUse": false - } + "isVisible": false } }, "modelIdResolutions": { @@ -1189,37 +1258,50 @@ "contexts": [ { "condition": { - "hasAccessToPreview": false + "hasAccessToPreview": false, + "useGemini3_5Flash": true + }, + "target": "gemini-3.5-flash" + }, + { + "condition": { + "hasAccessToPreview": false, + "useGemini3_5Flash": false }, "target": "gemini-2.5-flash" } ] }, - "gemini-3-pro-preview": { - "default": "gemini-3-pro-preview", + "gemini-3.5-flash": { + "default": "gemini-3.5-flash", "contexts": [ { "condition": { + "useGemini3_5Flash": false, "hasAccessToPreview": false }, - "target": "gemini-2.5-pro" + "target": "gemini-2.5-flash" }, { "condition": { - "useGemini3_1": true, - "useCustomTools": true + "useGemini3_5Flash": false }, - "target": "gemini-3.1-pro-preview-customtools" - }, + "target": "gemini-3-flash-preview" + } + ] + }, + "gemini-2.5-flash": { + "default": "gemini-2.5-flash", + "contexts": [ { "condition": { - "useGemini3_1": true + "useGemini3_5Flash": true }, - "target": "gemini-3.1-pro-preview" + "target": "gemini-3.5-flash" } ] }, - "auto-gemini-3": { + "gemini-3-pro-preview": { "default": "gemini-3-pro-preview", "contexts": [ { @@ -1291,23 +1373,18 @@ } ] }, - "auto-gemini-2.5": { - "default": "gemini-2.5-pro" + "gemini-3.1-flash-lite": { + "default": "gemini-3.1-flash-lite" }, - "gemini-3.1-flash-lite-preview": { - "default": "gemini-3.1-flash-lite-preview", + "flash": { + "default": "gemini-3-flash-preview", "contexts": [ { "condition": { - "useGemini3_1FlashLite": false + "useGemini3_5Flash": true }, - "target": "gemini-2.5-flash-lite" - } - ] - }, - "flash": { - "default": "gemini-3-flash-preview", - "contexts": [ + "target": "gemini-3.5-flash" + }, { "condition": { "hasAccessToPreview": false @@ -1317,15 +1394,34 @@ ] }, "flash-lite": { - "default": "gemini-2.5-flash-lite", + "default": "gemini-3.1-flash-lite" + }, + "auto-gemini-3": { + "default": "gemini-3-pro-preview", "contexts": [ { "condition": { - "useGemini3_1FlashLite": true + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + }, + { + "condition": { + "useGemini3_1": true, + "useCustomTools": true }, - "target": "gemini-3.1-flash-lite-preview" + "target": "gemini-3.1-pro-preview-customtools" + }, + { + "condition": { + "useGemini3_1": true + }, + "target": "gemini-3.1-pro-preview" } ] + }, + "auto-gemini-2.5": { + "default": "gemini-2.5-pro" } }, "classifierIdResolutions": { @@ -1334,15 +1430,21 @@ "contexts": [ { "condition": { - "requestedModels": ["auto-gemini-2.5", "gemini-2.5-pro"] + "useGemini3_5Flash": true + }, + "target": "gemini-3.5-flash" + }, + { + "condition": { + "hasAccessToPreview": false }, "target": "gemini-2.5-flash" }, { "condition": { - "requestedModels": ["auto-gemini-3", "gemini-3-pro-preview"] + "requestedModels": ["gemini-2.5-pro", "auto-gemini-2.5"] }, - "target": "gemini-3-flash-preview" + "target": "gemini-2.5-flash" } ] }, @@ -1351,7 +1453,13 @@ "contexts": [ { "condition": { - "requestedModels": ["auto-gemini-2.5", "gemini-2.5-pro"] + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + }, + { + "condition": { + "requestedModels": ["gemini-2.5-pro", "auto-gemini-2.5"] }, "target": "gemini-2.5-pro" }, @@ -1512,7 +1620,7 @@ ], "lite": [ { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "actions": { "terminal": "silent", "transient": "silent", @@ -1565,7 +1673,7 @@ "aliases": { "title": "Model Config Aliases", "description": "Named presets for model configs. Can be used in place of a model name and can inherit from other aliases using an `extends` property.", - "markdownDescription": "Named presets for model configs. Can be used in place of a model name and can inherit from other aliases using an `extends` property.\n\n- Category: `Model`\n- Requires restart: `no`\n- Default: `{\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 \"gemma-4-31b-it\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemma-4-31b-it\"\n }\n },\n \"gemma-4-26b-a4b-it\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemma-4-26b-a4b-it\"\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 \"context-snapshotter\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingLevel\": \"HIGH\"\n },\n \"temperature\": 1,\n \"topP\": 0.95,\n \"topK\": 64\n }\n }\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-3.1-flash-lite\": {\n \"modelConfig\": {\n \"model\": \"gemini-3.1-flash-lite-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 \"agent-history-provider-summarizer\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-flash-preview\"\n }\n }\n}`", + "markdownDescription": "Named presets for model configs. Can be used in place of a model name and can inherit from other aliases using an `extends` property.\n\n- Category: `Model`\n- Requires restart: `no`\n- Default: `{\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-3.1-pro-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3.1-pro-preview\"\n }\n },\n \"gemini-3.1-pro-preview-customtools\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3.1-pro-preview-customtools\"\n }\n },\n \"gemini-3.1-flash-lite-preview\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3.1-flash-lite-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-3.1-flash-lite\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3.1-flash-lite\"\n }\n },\n \"gemini-3.5-flash\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemini-3.5-flash\"\n }\n },\n \"gemma-4-31b-it\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemma-4-31b-it\"\n }\n },\n \"gemma-4-26b-a4b-it\": {\n \"extends\": \"chat-base-3\",\n \"modelConfig\": {\n \"model\": \"gemma-4-26b-a4b-it\"\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 \"gemini-3.5-flash-base\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"gemini-3.5-flash\"\n }\n },\n \"classifier\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"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\": \"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\": \"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\": \"flash-lite\",\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingBudget\": 0\n }\n }\n }\n },\n \"summarizer-default\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"flash-lite\",\n \"generateContentConfig\": {\n \"maxOutputTokens\": 2000\n }\n }\n },\n \"summarizer-shell\": {\n \"extends\": \"base\",\n \"modelConfig\": {\n \"model\": \"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 \"context-snapshotter\": {\n \"extends\": \"gemini-3-flash-base\",\n \"modelConfig\": {\n \"generateContentConfig\": {\n \"thinkingConfig\": {\n \"thinkingLevel\": \"HIGH\"\n },\n \"temperature\": 1,\n \"topP\": 0.95,\n \"topK\": 64\n }\n }\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-3.1-flash-lite\": {\n \"modelConfig\": {\n \"model\": \"gemini-3.1-flash-lite\"\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 \"agent-history-provider-summarizer\": {\n \"modelConfig\": {\n \"model\": \"gemini-3-flash-preview\"\n }\n }\n}`", "default": { "base": { "modelConfig": { @@ -1620,6 +1728,24 @@ "model": "gemini-3-flash-preview" } }, + "gemini-3.1-pro-preview": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-pro-preview" + } + }, + "gemini-3.1-pro-preview-customtools": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-pro-preview-customtools" + } + }, + "gemini-3.1-flash-lite-preview": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-flash-lite-preview" + } + }, "gemini-2.5-pro": { "extends": "chat-base-2.5", "modelConfig": { @@ -1638,6 +1764,18 @@ "model": "gemini-2.5-flash-lite" } }, + "gemini-3.1-flash-lite": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.1-flash-lite" + } + }, + "gemini-3.5-flash": { + "extends": "chat-base-3", + "modelConfig": { + "model": "gemini-3.5-flash" + } + }, "gemma-4-31b-it": { "extends": "chat-base-3", "modelConfig": { @@ -1662,10 +1800,16 @@ "model": "gemini-3-flash-preview" } }, + "gemini-3.5-flash-base": { + "extends": "base", + "modelConfig": { + "model": "gemini-3.5-flash" + } + }, "classifier": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "maxOutputTokens": 1024, "thinkingConfig": { @@ -1677,7 +1821,7 @@ "prompt-completion": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0.3, "maxOutputTokens": 16000, @@ -1690,7 +1834,7 @@ "fast-ack-helper": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "temperature": 0.2, "maxOutputTokens": 120, @@ -1703,7 +1847,7 @@ "edit-corrector": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "thinkingConfig": { "thinkingBudget": 0 @@ -1714,7 +1858,7 @@ "summarizer-default": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "maxOutputTokens": 2000 } @@ -1723,7 +1867,7 @@ "summarizer-shell": { "extends": "base", "modelConfig": { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "generateContentConfig": { "maxOutputTokens": 2000 } @@ -1800,7 +1944,7 @@ }, "chat-compression-3.1-flash-lite": { "modelConfig": { - "model": "gemini-3.1-flash-lite-preview" + "model": "gemini-3.1-flash-lite" } }, "chat-compression-2.5-pro": { @@ -1859,12 +2003,12 @@ "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-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 \"gemma-4-31b-it\": {\n \"displayName\": \"gemma-4-31b-it\",\n \"tier\": \"custom\",\n \"family\": \"gemma-4\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"gemma-4-26b-a4b-it\": {\n \"displayName\": \"gemma-4-26b-a4b-it\",\n \"tier\": \"custom\",\n \"family\": \"gemma-4\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\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}`", + "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\": {\n \"tier\": \"flash-lite\",\n \"family\": \"gemini-3\",\n \"isPreview\": false,\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-3.5-flash\": {\n \"tier\": \"flash\",\n \"family\": \"gemini-3\",\n \"isPreview\": false,\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 \"gemma-4-31b-it\": {\n \"displayName\": \"gemma-4-31b-it\",\n \"tier\": \"custom\",\n \"family\": \"gemma-4\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"gemma-4-26b-a4b-it\": {\n \"displayName\": \"gemma-4-26b-a4b-it\",\n \"tier\": \"custom\",\n \"family\": \"gemma-4\",\n \"isPreview\": false,\n \"isVisible\": true,\n \"features\": {\n \"thinking\": true,\n \"multimodalToolUse\": false\n }\n },\n \"auto\": {\n \"displayName\": \"Auto\",\n \"tier\": \"auto\",\n \"isPreview\": true,\n \"isVisible\": true,\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 \"tier\": \"auto\",\n \"family\": \"gemini-3\",\n \"isPreview\": true,\n \"isVisible\": false\n },\n \"auto-gemini-2.5\": {\n \"tier\": \"auto\",\n \"family\": \"gemini-2.5\",\n \"isPreview\": false,\n \"isVisible\": false\n }\n}`", "default": { - "gemini-3.1-flash-lite-preview": { + "gemini-3.1-flash-lite": { "tier": "flash-lite", "family": "gemini-3", - "isPreview": true, + "isPreview": false, "isVisible": true, "features": { "thinking": false, @@ -1911,6 +2055,16 @@ "multimodalToolUse": true } }, + "gemini-3.5-flash": { + "tier": "flash", + "family": "gemini-3", + "isPreview": false, + "isVisible": true, + "features": { + "thinking": false, + "multimodalToolUse": true + } + }, "gemini-2.5-pro": { "tier": "pro", "family": "gemini-2.5", @@ -1964,9 +2118,10 @@ } }, "auto": { + "displayName": "Auto", "tier": "auto", "isPreview": true, - "isVisible": false, + "isVisible": true, "features": { "thinking": true, "multimodalToolUse": false @@ -2000,26 +2155,16 @@ } }, "auto-gemini-3": { - "displayName": "Auto (Gemini 3)", "tier": "auto", + "family": "gemini-3", "isPreview": true, - "isVisible": true, - "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash", - "features": { - "thinking": true, - "multimodalToolUse": false - } + "isVisible": false }, "auto-gemini-2.5": { - "displayName": "Auto (Gemini 2.5)", "tier": "auto", + "family": "gemini-2.5", "isPreview": false, - "isVisible": true, - "dialogDescription": "Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash", - "features": { - "thinking": false, - "multimodalToolUse": false - } + "isVisible": false } }, "type": "object", @@ -2030,7 +2175,7 @@ "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 \"gemma-4-31b-it\": {\n \"default\": \"gemma-4-31b-it\"\n },\n \"gemma-4-26b-a4b-it\": {\n \"default\": \"gemma-4-26b-a4b-it\"\n },\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 \"condition\": {\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\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 \"gemini-3.1-flash-lite-preview\": {\n \"default\": \"gemini-3.1-flash-lite-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_1FlashLite\": false\n },\n \"target\": \"gemini-2.5-flash-lite\"\n }\n ]\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 \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_1FlashLite\": true\n },\n \"target\": \"gemini-3.1-flash-lite-preview\"\n }\n ]\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 \"gemma-4-31b-it\": {\n \"default\": \"gemma-4-31b-it\"\n },\n \"gemma-4-26b-a4b-it\": {\n \"default\": \"gemma-4-26b-a4b-it\"\n },\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 \"condition\": {\n \"useCustomTools\": true\n },\n \"target\": \"gemini-3.1-pro-preview-customtools\"\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 \"useGemini3_5Flash\": true\n },\n \"target\": \"gemini-3.5-flash\"\n },\n {\n \"condition\": {\n \"hasAccessToPreview\": false,\n \"useGemini3_5Flash\": false\n },\n \"target\": \"gemini-2.5-flash\"\n }\n ]\n },\n \"gemini-3.5-flash\": {\n \"default\": \"gemini-3.5-flash\",\n \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_5Flash\": false,\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n },\n {\n \"condition\": {\n \"useGemini3_5Flash\": false\n },\n \"target\": \"gemini-3-flash-preview\"\n }\n ]\n },\n \"gemini-2.5-flash\": {\n \"default\": \"gemini-2.5-flash\",\n \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_5Flash\": true\n },\n \"target\": \"gemini-3.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\": {\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 \"gemini-3.1-flash-lite\": {\n \"default\": \"gemini-3.1-flash-lite\"\n },\n \"flash\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_5Flash\": true\n },\n \"target\": \"gemini-3.5-flash\"\n },\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n }\n ]\n },\n \"flash-lite\": {\n \"default\": \"gemini-3.1-flash-lite\"\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-gemini-2.5\": {\n \"default\": \"gemini-2.5-pro\"\n }\n}`", "default": { "gemma-4-31b-it": { "default": "gemma-4-31b-it" @@ -2071,37 +2216,50 @@ "contexts": [ { "condition": { - "hasAccessToPreview": false + "hasAccessToPreview": false, + "useGemini3_5Flash": true + }, + "target": "gemini-3.5-flash" + }, + { + "condition": { + "hasAccessToPreview": false, + "useGemini3_5Flash": false }, "target": "gemini-2.5-flash" } ] }, - "gemini-3-pro-preview": { - "default": "gemini-3-pro-preview", + "gemini-3.5-flash": { + "default": "gemini-3.5-flash", "contexts": [ { "condition": { + "useGemini3_5Flash": false, "hasAccessToPreview": false }, - "target": "gemini-2.5-pro" + "target": "gemini-2.5-flash" }, { "condition": { - "useGemini3_1": true, - "useCustomTools": true + "useGemini3_5Flash": false }, - "target": "gemini-3.1-pro-preview-customtools" - }, + "target": "gemini-3-flash-preview" + } + ] + }, + "gemini-2.5-flash": { + "default": "gemini-2.5-flash", + "contexts": [ { "condition": { - "useGemini3_1": true + "useGemini3_5Flash": true }, - "target": "gemini-3.1-pro-preview" + "target": "gemini-3.5-flash" } ] }, - "auto-gemini-3": { + "gemini-3-pro-preview": { "default": "gemini-3-pro-preview", "contexts": [ { @@ -2173,23 +2331,18 @@ } ] }, - "auto-gemini-2.5": { - "default": "gemini-2.5-pro" + "gemini-3.1-flash-lite": { + "default": "gemini-3.1-flash-lite" }, - "gemini-3.1-flash-lite-preview": { - "default": "gemini-3.1-flash-lite-preview", + "flash": { + "default": "gemini-3-flash-preview", "contexts": [ { "condition": { - "useGemini3_1FlashLite": false + "useGemini3_5Flash": true }, - "target": "gemini-2.5-flash-lite" - } - ] - }, - "flash": { - "default": "gemini-3-flash-preview", - "contexts": [ + "target": "gemini-3.5-flash" + }, { "condition": { "hasAccessToPreview": false @@ -2199,15 +2352,34 @@ ] }, "flash-lite": { - "default": "gemini-2.5-flash-lite", + "default": "gemini-3.1-flash-lite" + }, + "auto-gemini-3": { + "default": "gemini-3-pro-preview", "contexts": [ { "condition": { - "useGemini3_1FlashLite": true + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + }, + { + "condition": { + "useGemini3_1": true, + "useCustomTools": true + }, + "target": "gemini-3.1-pro-preview-customtools" + }, + { + "condition": { + "useGemini3_1": true }, - "target": "gemini-3.1-flash-lite-preview" + "target": "gemini-3.1-pro-preview" } ] + }, + "auto-gemini-2.5": { + "default": "gemini-2.5-pro" } }, "type": "object", @@ -2218,22 +2390,28 @@ "classifierIdResolutions": { "title": "Classifier ID Resolutions", "description": "Rules for resolving classifier tiers (flash, pro) to concrete model IDs.", - "markdownDescription": "Rules for resolving classifier tiers (flash, pro) to concrete model IDs.\n\n- Category: `Model`\n- Requires restart: `yes`\n- Default: `{\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}`", + "markdownDescription": "Rules for resolving classifier tiers (flash, pro) to concrete model IDs.\n\n- Category: `Model`\n- Requires restart: `yes`\n- Default: `{\n \"flash\": {\n \"default\": \"gemini-3-flash-preview\",\n \"contexts\": [\n {\n \"condition\": {\n \"useGemini3_5Flash\": true\n },\n \"target\": \"gemini-3.5-flash\"\n },\n {\n \"condition\": {\n \"hasAccessToPreview\": false\n },\n \"target\": \"gemini-2.5-flash\"\n },\n {\n \"condition\": {\n \"requestedModels\": [\n \"gemini-2.5-pro\",\n \"auto-gemini-2.5\"\n ]\n },\n \"target\": \"gemini-2.5-flash\"\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 \"requestedModels\": [\n \"gemini-2.5-pro\",\n \"auto-gemini-2.5\"\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}`", "default": { "flash": { "default": "gemini-3-flash-preview", "contexts": [ { "condition": { - "requestedModels": ["auto-gemini-2.5", "gemini-2.5-pro"] + "useGemini3_5Flash": true + }, + "target": "gemini-3.5-flash" + }, + { + "condition": { + "hasAccessToPreview": false }, "target": "gemini-2.5-flash" }, { "condition": { - "requestedModels": ["auto-gemini-3", "gemini-3-pro-preview"] + "requestedModels": ["gemini-2.5-pro", "auto-gemini-2.5"] }, - "target": "gemini-3-flash-preview" + "target": "gemini-2.5-flash" } ] }, @@ -2242,7 +2420,13 @@ "contexts": [ { "condition": { - "requestedModels": ["auto-gemini-2.5", "gemini-2.5-pro"] + "hasAccessToPreview": false + }, + "target": "gemini-2.5-pro" + }, + { + "condition": { + "requestedModels": ["gemini-2.5-pro", "auto-gemini-2.5"] }, "target": "gemini-2.5-pro" }, @@ -2270,7 +2454,7 @@ "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 \"maxAttempts\": 10,\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 \"auto-preview\": [\n {\n \"model\": \"gemini-3-pro-preview\",\n \"maxAttempts\": 3,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"silent\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-3-flash-preview\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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 \"auto-default\": [\n {\n \"model\": \"gemini-2.5-pro\",\n \"maxAttempts\": 3,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"silent\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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}`", + "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 \"maxAttempts\": 10,\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 \"auto-preview\": [\n {\n \"model\": \"gemini-3-pro-preview\",\n \"maxAttempts\": 3,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"silent\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-3-flash-preview\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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 \"auto-default\": [\n {\n \"model\": \"gemini-2.5-pro\",\n \"maxAttempts\": 3,\n \"actions\": {\n \"terminal\": \"prompt\",\n \"transient\": \"silent\",\n \"not_found\": \"prompt\",\n \"unknown\": \"prompt\"\n },\n \"stateTransitions\": {\n \"terminal\": \"terminal\",\n \"transient\": \"sticky_retry\",\n \"not_found\": \"terminal\",\n \"unknown\": \"terminal\"\n }\n },\n {\n \"model\": \"gemini-2.5-flash\",\n \"isLastResort\": true,\n \"maxAttempts\": 10,\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\": \"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": [ { @@ -2412,7 +2596,7 @@ ], "lite": [ { - "model": "gemini-2.5-flash-lite", + "model": "flash-lite", "actions": { "terminal": "silent", "transient": "silent", @@ -3160,6 +3344,13 @@ "markdownDescription": "Enable the agent session implementation for the interactive CLI.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `false`", "default": false, "type": "boolean" + }, + "agentSessionSubagentEnabled": { + "title": "Agent Session Subagent Enabled", + "description": "Route subagent invocations through the AgentSession protocol instead of legacy executors.", + "markdownDescription": "Route subagent invocations through the AgentSession protocol instead of legacy executors.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `false`", + "default": false, + "type": "boolean" } }, "additionalProperties": false @@ -3213,13 +3404,6 @@ "default": false, "type": "boolean" }, - "jitContext": { - "title": "JIT Context Loading", - "description": "Enable Just-In-Time (JIT) context loading. Defaults to true; set to false to opt out and load all GEMINI.md files into the system instruction up-front.", - "markdownDescription": "Enable Just-In-Time (JIT) context loading. Defaults to true; set to false to opt out and load all GEMINI.md files into the system instruction up-front.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `true`", - "default": true, - "type": "boolean" - }, "useOSC52Paste": { "title": "Use OSC 52 Paste", "description": "Use OSC 52 for pasting. This may be more robust than the default system when using remote terminal sessions (if your terminal is configured to allow it).", @@ -3317,13 +3501,6 @@ }, "additionalProperties": false }, - "memoryV2": { - "title": "Memory v2", - "description": "Disable the built-in save_memory tool and let the main agent persist project context by editing markdown files directly with edit/write_file. Route facts across four tiers: team-shared conventions go to project GEMINI.md files, project-specific personal notes go to the per-project private memory folder (MEMORY.md as index + sibling .md files for detail), and cross-project personal preferences go to the global ~/.gemini/GEMINI.md (the only file under ~/.gemini/ that the agent can edit — settings, credentials, etc. remain off-limits). Set to false to fall back to the legacy save_memory tool.", - "markdownDescription": "Disable the built-in save_memory tool and let the main agent persist project context by editing markdown files directly with edit/write_file. Route facts across four tiers: team-shared conventions go to project GEMINI.md files, project-specific personal notes go to the per-project private memory folder (MEMORY.md as index + sibling .md files for detail), and cross-project personal preferences go to the global ~/.gemini/GEMINI.md (the only file under ~/.gemini/ that the agent can edit — settings, credentials, etc. remain off-limits). Set to false to fall back to the legacy save_memory tool.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `true`", - "default": true, - "type": "boolean" - }, "stressTestProfile": { "title": "Use the stress test profile to aggressively trigger context management.", "description": "Significantly lowers token limits to force early garbage collection and distillation for testing purposes.", @@ -3345,6 +3522,13 @@ "default": false, "type": "boolean" }, + "powerUserProfile": { + "title": "Use the power user profile to manage agent contexts.", + "description": "Less cache friendly version of the generalist profile.", + "markdownDescription": "Less cache friendly version of the generalist profile.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `false`", + "default": false, + "type": "boolean" + }, "contextManagement": { "title": "Enable Context Management", "description": "Enable logic for context management.", @@ -4307,7 +4491,8 @@ "type": "boolean" }, "dialogDescription": { - "type": "string" + "type": "string", + "description": "A description of the model to display in the model selection dialog. For the 'auto' alias, this value is dynamically generated and any value provided here will be ignored." }, "features": { "type": "object",