diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 1568207936..bae1fe483e 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -2801,6 +2801,10 @@ export class Config implements McpContext, AgentLoopContext { return getChannelFromVersion(this._clientVersion); } + getAuthType(): string | undefined { + return this.contentGeneratorConfig.authType; + } + getPendingIncludeDirectories(): string[] { return this.pendingIncludeDirectories; } diff --git a/packages/core/src/config/defaultModelConfigs.ts b/packages/core/src/config/defaultModelConfigs.ts index cda791c808..61ede45289 100644 --- a/packages/core/src/config/defaultModelConfigs.ts +++ b/packages/core/src/config/defaultModelConfigs.ts @@ -467,6 +467,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { auto: { default: 'gemini-3-pro-preview', contexts: [ + { condition: { authType: 'oauth-personal' }, target: 'gemini-2.5-pro' }, { condition: { releaseChannel: 'stable' }, target: 'gemini-2.5-pro' }, { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-pro' }, { @@ -482,6 +483,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { pro: { default: 'gemini-3-pro-preview', contexts: [ + { condition: { authType: 'oauth-personal' }, target: 'gemini-2.5-pro' }, { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-pro' }, { condition: { useGemini3_1: true, useCustomTools: true }, @@ -496,6 +498,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { 'gemini-3.1-flash-lite-preview': { default: 'gemini-3.1-flash-lite-preview', contexts: [ + { condition: { authType: 'oauth-personal' }, target: 'gemini-2.5-flash-lite' }, { condition: { useGemini3_1FlashLite: false }, target: 'gemini-2.5-flash-lite', @@ -505,6 +508,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { flash: { default: 'gemini-3-flash-preview', contexts: [ + { condition: { authType: 'oauth-personal' }, target: 'gemini-2.5-flash' }, { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-flash', @@ -515,7 +519,11 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { default: 'gemini-2.5-flash-lite', contexts: [ { - condition: { useGemini3_1FlashLite: true }, + condition: { useGemini3_1FlashLite: true, authType: 'gemini-api-key' }, + target: 'gemini-3.1-flash-lite-preview', + }, + { + condition: { useGemini3_1FlashLite: true, authType: 'vertex-ai' }, target: 'gemini-3.1-flash-lite-preview', }, ], @@ -523,6 +531,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { 'auto-gemini-3': { default: 'gemini-3-pro-preview', contexts: [ + { condition: { authType: 'oauth-personal' }, target: 'gemini-2.5-pro' }, { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-pro' }, { condition: { useGemini3_1: true, useCustomTools: true }, @@ -542,6 +551,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { flash: { default: 'gemini-3-flash-preview', contexts: [ + { condition: { authType: 'oauth-personal' }, target: 'gemini-2.5-flash' }, { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-flash', @@ -555,6 +565,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { pro: { default: 'gemini-3-pro-preview', contexts: [ + { condition: { authType: 'oauth-personal' }, target: 'gemini-2.5-pro' }, { condition: { hasAccessToPreview: false }, target: 'gemini-2.5-pro', diff --git a/packages/core/src/config/models.ts b/packages/core/src/config/models.ts index 7360878ccd..764f749c57 100644 --- a/packages/core/src/config/models.ts +++ b/packages/core/src/config/models.ts @@ -11,6 +11,7 @@ export interface ModelResolutionContext { hasAccessToPreview?: boolean; requestedModel?: string; releaseChannel?: string; + authType?: string; } /** @@ -50,6 +51,7 @@ export interface ModelCapabilityContext { readonly modelConfigService: IModelConfigService; getExperimentalDynamicModelConfiguration(): boolean; getReleaseChannel?(): string; + getAuthType?(): string | undefined; } export const PREVIEW_GEMINI_MODEL = 'gemini-3-pro-preview'; @@ -127,6 +129,7 @@ export function resolveModel( hasAccessToPreview: boolean = true, config?: ModelCapabilityContext, releaseChannel?: string, + authType?: string, ): string { // Defensive check against non-string inputs at runtime const normalizedModel = Array.isArray(requestedModel) @@ -136,6 +139,7 @@ export function resolveModel( : requestedModel.trim() || ''; const currentReleaseChannel = releaseChannel ?? config?.getReleaseChannel?.(); + const currentAuthType = authType ?? config?.getAuthType?.(); if (config?.getExperimentalDynamicModelConfiguration?.() === true) { const resolved = config.modelConfigService.resolveModelId(normalizedModel, { @@ -144,6 +148,7 @@ export function resolveModel( useCustomTools: useCustomToolModel, hasAccessToPreview, releaseChannel: currentReleaseChannel, + authType: currentAuthType, }); if (!hasAccessToPreview && isPreviewModel(resolved, config)) { @@ -245,6 +250,7 @@ export function resolveClassifierModel( useCustomToolModel: boolean = false, hasAccessToPreview: boolean = true, config?: ModelCapabilityContext, + authType?: string, ): string { if (config?.getExperimentalDynamicModelConfiguration?.() === true) { return config.modelConfigService.resolveClassifierModelId( @@ -255,6 +261,7 @@ export function resolveClassifierModel( useGemini3_1FlashLite, useCustomTools: useCustomToolModel, hasAccessToPreview, + authType: authType ?? config?.getAuthType?.(), }, ); } @@ -281,6 +288,9 @@ export function resolveClassifierModel( false, false, hasAccessToPreview, + config, + undefined, + authType, ); } return resolveModel( @@ -289,6 +299,9 @@ export function resolveClassifierModel( useGemini3_1FlashLite, useCustomToolModel, hasAccessToPreview, + config, + undefined, + authType, ); } diff --git a/packages/core/src/config/models_auth.test.ts b/packages/core/src/config/models_auth.test.ts new file mode 100644 index 0000000000..68e01c839e --- /dev/null +++ b/packages/core/src/config/models_auth.test.ts @@ -0,0 +1,70 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { describe, it, expect } from 'vitest'; +import { + resolveModel, + PREVIEW_GEMINI_MODEL_AUTO, + PREVIEW_GEMINI_MODEL, + DEFAULT_GEMINI_MODEL, +} from './models.js'; +import { ModelConfigService } from '../services/modelConfigService.js'; +import { DEFAULT_MODEL_CONFIGS } from './defaultModelConfigs.js'; +import type { Config } from './config.js'; + +const modelConfigService = new ModelConfigService(DEFAULT_MODEL_CONFIGS); + +const dynamicConfig = { + getExperimentalDynamicModelConfiguration: () => true, + modelConfigService, +} as unknown as Config; + +describe('resolveModel with authType', () => { + it('should resolve auto-gemini-3 to gemini-3-pro-preview for non-personal auth', () => { + const model = resolveModel( + PREVIEW_GEMINI_MODEL_AUTO, + false, + false, + false, + true, + dynamicConfig, + 'stable', + 'gemini-api-key' + ); + expect(model).toBe(PREVIEW_GEMINI_MODEL); + }); + + it('should resolve auto-gemini-3 to gemini-2.5-pro for oauth-personal auth', () => { + const model = resolveModel( + PREVIEW_GEMINI_MODEL_AUTO, + false, + false, + false, + true, + dynamicConfig, + 'stable', + 'oauth-personal' + ); + expect(model).toBe(DEFAULT_GEMINI_MODEL); + }); + + it('should use authType from config if not passed explicitly', () => { + const configWithAuth = { + ...dynamicConfig, + getAuthType: () => 'oauth-personal', + } as unknown as Config; + + const model = resolveModel( + PREVIEW_GEMINI_MODEL_AUTO, + false, + false, + false, + true, + configWithAuth + ); + expect(model).toBe(DEFAULT_GEMINI_MODEL); + }); +}); diff --git a/packages/core/src/core/contentGenerator.ts b/packages/core/src/core/contentGenerator.ts index 4494a5e9ff..52434b5591 100644 --- a/packages/core/src/core/contentGenerator.ts +++ b/packages/core/src/core/contentGenerator.ts @@ -217,6 +217,8 @@ export async function createContentGenerator( false, gcConfig.getHasAccessToPreviewModel?.() ?? true, gcConfig, + undefined, + config.authType, ); const customHeadersEnv = process.env['GEMINI_CLI_CUSTOM_HEADERS'] || undefined; diff --git a/packages/core/src/services/modelConfigService.ts b/packages/core/src/services/modelConfigService.ts index 64ef291206..1d4e95c17b 100644 --- a/packages/core/src/services/modelConfigService.ts +++ b/packages/core/src/services/modelConfigService.ts @@ -103,6 +103,7 @@ export interface ResolutionContext { hasAccessToProModel?: boolean; requestedModel?: string; releaseChannel?: string; + authType?: string; } /** The requirements defined in the registry. */ @@ -114,6 +115,7 @@ export interface ResolutionCondition { /** Matches if the current model is in this list. */ requestedModels?: string[]; releaseChannel?: string; + authType?: string; } export interface ModelConfigServiceConfig { @@ -267,6 +269,8 @@ export class ModelConfigService { ); case 'releaseChannel': return value === context.releaseChannel; + case 'authType': + return value === context.authType; default: return false; } diff --git a/schemas/settings.schema.json b/schemas/settings.schema.json index 2bcde8bc6f..5d1e4a16a2 100644 --- a/schemas/settings.schema.json +++ b/schemas/settings.schema.json @@ -1238,6 +1238,12 @@ "auto": { "default": "gemini-3-pro-preview", "contexts": [ + { + "condition": { + "authType": "oauth-personal" + }, + "target": "gemini-2.5-pro" + }, { "condition": { "releaseChannel": "stable" @@ -1268,6 +1274,12 @@ "pro": { "default": "gemini-3-pro-preview", "contexts": [ + { + "condition": { + "authType": "oauth-personal" + }, + "target": "gemini-2.5-pro" + }, { "condition": { "hasAccessToPreview": false @@ -1292,6 +1304,12 @@ "gemini-3.1-flash-lite-preview": { "default": "gemini-3.1-flash-lite-preview", "contexts": [ + { + "condition": { + "authType": "oauth-personal" + }, + "target": "gemini-2.5-flash-lite" + }, { "condition": { "useGemini3_1FlashLite": false @@ -1303,6 +1321,12 @@ "flash": { "default": "gemini-3-flash-preview", "contexts": [ + { + "condition": { + "authType": "oauth-personal" + }, + "target": "gemini-2.5-flash" + }, { "condition": { "hasAccessToPreview": false @@ -1316,7 +1340,15 @@ "contexts": [ { "condition": { - "useGemini3_1FlashLite": true + "useGemini3_1FlashLite": true, + "authType": "gemini-api-key" + }, + "target": "gemini-3.1-flash-lite-preview" + }, + { + "condition": { + "useGemini3_1FlashLite": true, + "authType": "vertex-ai" }, "target": "gemini-3.1-flash-lite-preview" } @@ -1325,6 +1357,12 @@ "auto-gemini-3": { "default": "gemini-3-pro-preview", "contexts": [ + { + "condition": { + "authType": "oauth-personal" + }, + "target": "gemini-2.5-pro" + }, { "condition": { "hasAccessToPreview": false @@ -1354,6 +1392,12 @@ "flash": { "default": "gemini-3-flash-preview", "contexts": [ + { + "condition": { + "authType": "oauth-personal" + }, + "target": "gemini-2.5-flash" + }, { "condition": { "hasAccessToPreview": false @@ -1362,7 +1406,10 @@ }, { "condition": { - "requestedModels": ["gemini-2.5-pro", "auto-gemini-2.5"] + "requestedModels": [ + "gemini-2.5-pro", + "auto-gemini-2.5" + ] }, "target": "gemini-2.5-flash" } @@ -1371,6 +1418,12 @@ "pro": { "default": "gemini-3-pro-preview", "contexts": [ + { + "condition": { + "authType": "oauth-personal" + }, + "target": "gemini-2.5-pro" + }, { "condition": { "hasAccessToPreview": false @@ -1380,13 +1433,18 @@ { "condition": { "releaseChannel": "stable", - "requestedModels": ["auto"] + "requestedModels": [ + "auto" + ] }, "target": "gemini-2.5-pro" }, { "condition": { - "requestedModels": ["gemini-2.5-pro", "auto-gemini-2.5"] + "requestedModels": [ + "gemini-2.5-pro", + "auto-gemini-2.5" + ] }, "target": "gemini-2.5-pro" },