set it so none status models don't show up in the model dialog. Additionally, display full model name in getAutoModelDescription rather than by magic strings.

This commit is contained in:
davidapierce
2026-05-21 19:13:16 +00:00
parent 31199796c1
commit 6dbaf84381
7 changed files with 109 additions and 48 deletions

View File

@@ -243,6 +243,27 @@ describe('AcpSessionManager', () => {
);
});
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(
{
cwd: '/tmp',
mcpServers: [],
},
{},
);
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 () => {
mockConfig.getContentGeneratorConfig = vi.fn().mockReturnValue({
apiKey: 'test-key',

View File

@@ -336,7 +336,7 @@ export function buildAvailableModels(
},
];
if (useGemini31FlashLite) {
if (useGemini31FlashLite && PREVIEW_GEMINI_FLASH_LITE_MODEL !== 'none') {
previewOptions.push({
value: PREVIEW_GEMINI_FLASH_LITE_MODEL,
title: getDisplayString(PREVIEW_GEMINI_FLASH_LITE_MODEL),

View File

@@ -47,7 +47,7 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
mockModelSlashCommandEvent(model);
}
},
PREVIEW_GEMINI_FLASH_LITE_MODEL: 'gemini-3.1-flash-lite',
PREVIEW_GEMINI_FLASH_LITE_MODEL: 'none',
};
});
@@ -159,7 +159,7 @@ describe('<ModelDialog />', () => {
// Verify order: Flash Preview -> Flash Lite (Preview/Default) -> Flash
const flashPreviewIdx = output.indexOf(PREVIEW_GEMINI_FLASH_MODEL);
const flashLiteIdx = output.indexOf(PREVIEW_GEMINI_FLASH_LITE_MODEL);
const flashLiteIdx = output.indexOf(DEFAULT_GEMINI_FLASH_LITE_MODEL);
const flashIdx = output.indexOf(DEFAULT_GEMINI_FLASH_MODEL);
expect(flashPreviewIdx).toBeLessThan(flashLiteIdx);
@@ -449,7 +449,7 @@ describe('<ModelDialog />', () => {
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 +468,8 @@ describe('<ModelDialog />', () => {
await waitUntilReady();
const output = lastFrame();
expect(output).toContain(PREVIEW_GEMINI_FLASH_LITE_MODEL);
expect(output).not.toContain(PREVIEW_GEMINI_FLASH_LITE_MODEL);
expect(output).toContain(DEFAULT_GEMINI_FLASH_LITE_MODEL);
unmount();
});
});

View File

@@ -96,7 +96,7 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element {
PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL,
PREVIEW_GEMINI_FLASH_LITE_MODEL,
PREVIEW_GEMINI_FLASH_MODEL,
];
].filter((m) => m !== 'none');
if (manualModels.includes(preferredModel)) {
return preferredModel;
}
@@ -223,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) {
@@ -272,7 +272,7 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element {
},
];
if (useGemini31FlashLite) {
if (useGemini31FlashLite && PREVIEW_GEMINI_FLASH_LITE_MODEL !== 'none') {
previewOptions.push({
value: PREVIEW_GEMINI_FLASH_LITE_MODEL,
title: getDisplayString(PREVIEW_GEMINI_FLASH_LITE_MODEL),

View File

@@ -229,13 +229,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(PREVIEW_GEMINI_FLASH_LITE_MODEL)).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', () => {
@@ -625,22 +641,28 @@ describe('isActiveModel', () => {
expect(isActiveModel(DEFAULT_GEMINI_MODEL, true)).toBe(true);
});
it('should return true for PREVIEW_GEMINI_FLASH_LITE_MODEL only when useGemini3_1FlashLite is true, and always true for DEFAULT_GEMINI_FLASH_LITE_MODEL', () => {
expect(isActiveModel(PREVIEW_GEMINI_FLASH_LITE_MODEL, false, true)).toBe(
true,
);
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(PREVIEW_GEMINI_FLASH_LITE_MODEL, true, true)).toBe(
true,
);
expect(isActiveModel(DEFAULT_GEMINI_FLASH_LITE_MODEL, true, true)).toBe(
true,
);
expect(isActiveModel(PREVIEW_GEMINI_FLASH_LITE_MODEL, true, false)).toBe(
false,
);
expect(isActiveModel(DEFAULT_GEMINI_FLASH_LITE_MODEL, true, false)).toBe(
true,
);
@@ -677,9 +699,11 @@ describe('isActiveModel', () => {
expect(
isActiveModel(PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, false, false, false),
).toBe(false);
expect(isActiveModel(PREVIEW_GEMINI_FLASH_LITE_MODEL, 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,
);
@@ -707,14 +731,23 @@ describe('Gemini 3.1 Config Resolution', () => {
).toBeDefined();
});
it('PREVIEW_GEMINI_FLASH_LITE_MODEL should resolve to chat-base-3 config (including thinkingLevel)', () => {
const resolved = modelConfigService.getResolvedConfig({
model: PREVIEW_GEMINI_FLASH_LITE_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();
}
});
});
@@ -727,13 +760,13 @@ describe('getAutoModelDescription', () => {
it('should return Gemini 3.0 description when hasAccessToPreview is true', () => {
const desc = getAutoModelDescription(true, false);
expect(desc).toContain('gemini-3-pro');
expect(desc).toContain('gemini-3-flash');
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');
expect(desc).toContain('gemini-3-flash');
expect(desc).toContain('gemini-3.1-pro-preview');
expect(desc).toContain('gemini-3-flash-preview');
});
});

View File

@@ -101,10 +101,12 @@ export function getAutoModelDescription(
) {
const proModel = hasAccessToPreview
? useGemini3_1
? 'gemini-3.1-pro'
: 'gemini-3-pro'
: 'gemini-2.5-pro';
const flashModel = hasAccessToPreview ? 'gemini-3-flash' : 'gemini-2.5-flash';
? PREVIEW_GEMINI_3_1_MODEL
: PREVIEW_GEMINI_MODEL
: DEFAULT_GEMINI_MODEL;
const flashModel = hasAccessToPreview
? PREVIEW_GEMINI_FLASH_MODEL
: DEFAULT_GEMINI_FLASH_MODEL;
return `Let Gemini CLI decide the best model for the task: ${proModel}, ${flashModel}`;
}
@@ -332,6 +334,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
@@ -345,7 +350,7 @@ export function isPreviewModel(
model === PREVIEW_GEMINI_FLASH_MODEL ||
model === PREVIEW_GEMINI_MODEL_AUTO ||
model === GEMINI_MODEL_ALIAS_AUTO ||
(model === PREVIEW_GEMINI_FLASH_LITE_MODEL && model !== 'none')
model === PREVIEW_GEMINI_FLASH_LITE_MODEL
);
}

View File

@@ -107,6 +107,7 @@ export function modelStringToModelConfigAlias(model: string): string {
case PREVIEW_GEMINI_FLASH_MODEL:
return 'chat-compression-3-flash';
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':