Skip to content

Commit 22d962e

Browse files
authored
feat(core): fallback to 2.5 models with no access for toolcalls (#21283)
1 parent 0135b03 commit 22d962e

File tree

3 files changed

+73
-8
lines changed

3 files changed

+73
-8
lines changed

packages/core/src/availability/policyHelpers.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,16 @@ export function resolvePolicyChain(
4949
const useCustomToolModel =
5050
useGemini31 &&
5151
config.getContentGeneratorConfig?.()?.authType === AuthType.USE_GEMINI;
52+
const hasAccessToPreview = config.getHasAccessToPreviewModel?.() ?? true;
5253

5354
const resolvedModel = resolveModel(
5455
modelFromConfig,
5556
useGemini31,
5657
useCustomToolModel,
58+
hasAccessToPreview,
5759
);
5860
const isAutoPreferred = preferredModel ? isAutoModel(preferredModel) : false;
5961
const isAutoConfigured = isAutoModel(configuredModel);
60-
const hasAccessToPreview = config.getHasAccessToPreviewModel?.() ?? true;
6162

6263
if (resolvedModel === DEFAULT_GEMINI_FLASH_LITE_MODEL) {
6364
chain = getFlashLitePolicyChain();
@@ -80,7 +81,7 @@ export function resolvePolicyChain(
8081
} else {
8182
// User requested Gemini 3 but has no access. Proactively downgrade
8283
// to the stable Gemini 2.5 chain.
83-
return getModelPolicyChain({
84+
chain = getModelPolicyChain({
8485
previewEnabled: false,
8586
userTier: config.getUserTier(),
8687
useGemini31,

packages/core/src/config/models.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,38 @@ describe('resolveModel', () => {
217217
expect(model).toBe(customModel);
218218
});
219219
});
220+
221+
describe('hasAccessToPreview logic', () => {
222+
it('should return default model when access to preview is false and preview model is requested', () => {
223+
expect(resolveModel(PREVIEW_GEMINI_MODEL, false, false, false)).toBe(
224+
DEFAULT_GEMINI_MODEL,
225+
);
226+
});
227+
228+
it('should return default flash model when access to preview is false and preview flash model is requested', () => {
229+
expect(
230+
resolveModel(PREVIEW_GEMINI_FLASH_MODEL, false, false, false),
231+
).toBe(DEFAULT_GEMINI_FLASH_MODEL);
232+
});
233+
234+
it('should return default model when access to preview is false and auto-gemini-3 is requested', () => {
235+
expect(resolveModel(PREVIEW_GEMINI_MODEL_AUTO, false, false, false)).toBe(
236+
DEFAULT_GEMINI_MODEL,
237+
);
238+
});
239+
240+
it('should return default model when access to preview is false and Gemini 3.1 is requested', () => {
241+
expect(resolveModel(PREVIEW_GEMINI_MODEL_AUTO, true, false, false)).toBe(
242+
DEFAULT_GEMINI_MODEL,
243+
);
244+
});
245+
246+
it('should still return default model when access to preview is false and auto-gemini-2.5 is requested', () => {
247+
expect(resolveModel(DEFAULT_GEMINI_MODEL_AUTO, false, false, false)).toBe(
248+
DEFAULT_GEMINI_MODEL,
249+
);
250+
});
251+
});
220252
});
221253

222254
describe('isGemini2Model', () => {

packages/core/src/config/models.ts

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,38 +43,70 @@ export const DEFAULT_THINKING_MODE = 8192;
4343
*
4444
* @param requestedModel The model alias or concrete model name requested by the user.
4545
* @param useGemini3_1 Whether to use Gemini 3.1 Pro Preview for auto/pro aliases.
46+
* @param hasAccessToPreview Whether the user has access to preview models.
4647
* @returns The resolved concrete model name.
4748
*/
4849
export function resolveModel(
4950
requestedModel: string,
5051
useGemini3_1: boolean = false,
5152
useCustomToolModel: boolean = false,
53+
hasAccessToPreview: boolean = true,
5254
): string {
55+
let resolved: string;
5356
switch (requestedModel) {
5457
case PREVIEW_GEMINI_MODEL:
5558
case PREVIEW_GEMINI_MODEL_AUTO:
5659
case GEMINI_MODEL_ALIAS_AUTO:
5760
case GEMINI_MODEL_ALIAS_PRO: {
5861
if (useGemini3_1) {
59-
return useCustomToolModel
62+
resolved = useCustomToolModel
6063
? PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL
6164
: PREVIEW_GEMINI_3_1_MODEL;
65+
} else {
66+
resolved = PREVIEW_GEMINI_MODEL;
6267
}
63-
return PREVIEW_GEMINI_MODEL;
68+
break;
6469
}
6570
case DEFAULT_GEMINI_MODEL_AUTO: {
66-
return DEFAULT_GEMINI_MODEL;
71+
resolved = DEFAULT_GEMINI_MODEL;
72+
break;
6773
}
6874
case GEMINI_MODEL_ALIAS_FLASH: {
69-
return PREVIEW_GEMINI_FLASH_MODEL;
75+
resolved = PREVIEW_GEMINI_FLASH_MODEL;
76+
break;
7077
}
7178
case GEMINI_MODEL_ALIAS_FLASH_LITE: {
72-
return DEFAULT_GEMINI_FLASH_LITE_MODEL;
79+
resolved = DEFAULT_GEMINI_FLASH_LITE_MODEL;
80+
break;
7381
}
7482
default: {
75-
return requestedModel;
83+
resolved = requestedModel;
84+
break;
85+
}
86+
}
87+
88+
if (!hasAccessToPreview && isPreviewModel(resolved)) {
89+
// Downgrade to stable models if user lacks preview access.
90+
switch (resolved) {
91+
case PREVIEW_GEMINI_FLASH_MODEL:
92+
return DEFAULT_GEMINI_FLASH_MODEL;
93+
case PREVIEW_GEMINI_MODEL:
94+
case PREVIEW_GEMINI_3_1_MODEL:
95+
case PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL:
96+
return DEFAULT_GEMINI_MODEL;
97+
default:
98+
// Fallback for unknown preview models, preserving original logic.
99+
if (resolved.includes('flash-lite')) {
100+
return DEFAULT_GEMINI_FLASH_LITE_MODEL;
101+
}
102+
if (resolved.includes('flash')) {
103+
return DEFAULT_GEMINI_FLASH_MODEL;
104+
}
105+
return DEFAULT_GEMINI_MODEL;
76106
}
77107
}
108+
109+
return resolved;
78110
}
79111

80112
/**

0 commit comments

Comments
 (0)