feat(core): fallback to 2.5 models with no access for toolcalls (#21283)

This commit is contained in:
Sehoon Shon
2026-03-05 15:37:15 -05:00
committed by GitHub
parent 0135b03c8a
commit 22d962e761
3 changed files with 73 additions and 8 deletions

View File

@@ -49,15 +49,16 @@ export function resolvePolicyChain(
const useCustomToolModel =
useGemini31 &&
config.getContentGeneratorConfig?.()?.authType === AuthType.USE_GEMINI;
const hasAccessToPreview = config.getHasAccessToPreviewModel?.() ?? true;
const resolvedModel = resolveModel(
modelFromConfig,
useGemini31,
useCustomToolModel,
hasAccessToPreview,
);
const isAutoPreferred = preferredModel ? isAutoModel(preferredModel) : false;
const isAutoConfigured = isAutoModel(configuredModel);
const hasAccessToPreview = config.getHasAccessToPreviewModel?.() ?? true;
if (resolvedModel === DEFAULT_GEMINI_FLASH_LITE_MODEL) {
chain = getFlashLitePolicyChain();
@@ -80,7 +81,7 @@ export function resolvePolicyChain(
} else {
// User requested Gemini 3 but has no access. Proactively downgrade
// to the stable Gemini 2.5 chain.
return getModelPolicyChain({
chain = getModelPolicyChain({
previewEnabled: false,
userTier: config.getUserTier(),
useGemini31,

View File

@@ -217,6 +217,38 @@ describe('resolveModel', () => {
expect(model).toBe(customModel);
});
});
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)).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),
).toBe(DEFAULT_GEMINI_FLASH_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)).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)).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)).toBe(
DEFAULT_GEMINI_MODEL,
);
});
});
});
describe('isGemini2Model', () => {

View File

@@ -43,38 +43,70 @@ export const DEFAULT_THINKING_MODE = 8192;
*
* @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 hasAccessToPreview Whether the user has access to preview models.
* @returns The resolved concrete model name.
*/
export function resolveModel(
requestedModel: string,
useGemini3_1: boolean = false,
useCustomToolModel: boolean = false,
hasAccessToPreview: boolean = true,
): string {
let resolved: string;
switch (requestedModel) {
case PREVIEW_GEMINI_MODEL:
case PREVIEW_GEMINI_MODEL_AUTO:
case GEMINI_MODEL_ALIAS_AUTO:
case GEMINI_MODEL_ALIAS_PRO: {
if (useGemini3_1) {
return useCustomToolModel
resolved = useCustomToolModel
? PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL
: PREVIEW_GEMINI_3_1_MODEL;
} else {
resolved = PREVIEW_GEMINI_MODEL;
}
return PREVIEW_GEMINI_MODEL;
break;
}
case DEFAULT_GEMINI_MODEL_AUTO: {
return DEFAULT_GEMINI_MODEL;
resolved = DEFAULT_GEMINI_MODEL;
break;
}
case GEMINI_MODEL_ALIAS_FLASH: {
return PREVIEW_GEMINI_FLASH_MODEL;
resolved = PREVIEW_GEMINI_FLASH_MODEL;
break;
}
case GEMINI_MODEL_ALIAS_FLASH_LITE: {
return DEFAULT_GEMINI_FLASH_LITE_MODEL;
resolved = DEFAULT_GEMINI_FLASH_LITE_MODEL;
break;
}
default: {
return requestedModel;
resolved = requestedModel;
break;
}
}
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_MODEL:
case PREVIEW_GEMINI_3_1_MODEL:
case PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL:
return DEFAULT_GEMINI_MODEL;
default:
// Fallback for unknown preview models, preserving original logic.
if (resolved.includes('flash-lite')) {
return DEFAULT_GEMINI_FLASH_LITE_MODEL;
}
if (resolved.includes('flash')) {
return DEFAULT_GEMINI_FLASH_MODEL;
}
return DEFAULT_GEMINI_MODEL;
}
}
return resolved;
}
/**