feat: add support for Gemma 4 model

This commit is contained in:
Akhilesh Kumar
2026-04-16 21:14:05 +00:00
parent 277f0bb361
commit 7c0f3ecef9
6 changed files with 89 additions and 1 deletions
+5
View File
@@ -40,6 +40,7 @@ import {
DEFAULT_GEMINI_MODEL,
DEFAULT_GEMINI_FLASH_MODEL,
DEFAULT_GEMINI_FLASH_LITE_MODEL,
DEFAULT_GEMMA_4_MODEL,
PREVIEW_GEMINI_MODEL,
PREVIEW_GEMINI_3_1_MODEL,
PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL,
@@ -1654,6 +1655,10 @@ function buildAvailableModels(
value: DEFAULT_GEMINI_FLASH_LITE_MODEL,
title: getDisplayString(DEFAULT_GEMINI_FLASH_LITE_MODEL),
},
{
value: DEFAULT_GEMMA_4_MODEL,
title: getDisplayString(DEFAULT_GEMMA_4_MODEL),
},
];
if (shouldShowPreviewModels) {
@@ -15,6 +15,7 @@ import {
DEFAULT_GEMINI_MODEL_AUTO,
DEFAULT_GEMINI_FLASH_MODEL,
DEFAULT_GEMINI_FLASH_LITE_MODEL,
DEFAULT_GEMMA_4_MODEL,
PREVIEW_GEMINI_MODEL,
PREVIEW_GEMINI_3_1_MODEL,
PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL,
@@ -212,6 +213,33 @@ describe('<ModelDialog />', () => {
unmount();
});
it('shows Gemma 4 in manual view', async () => {
mockGetDisplayString.mockImplementation((val: string) => {
if (val === DEFAULT_GEMMA_4_MODEL) return 'Gemma 4 (26B)';
return val;
});
const { lastFrame, stdin, waitUntilReady, unmount } =
await renderComponent();
// Select "Manual" (index 1)
await act(async () => {
stdin.write('\u001B[B'); // Arrow Down
});
await waitUntilReady();
await act(async () => {
stdin.write('\r');
});
await waitUntilReady();
// Should now show manual options including Gemma 4
await waitFor(() => {
const output = lastFrame();
expect(output).toContain('Gemma 4 (26B)');
});
unmount();
});
it('sets model and closes when a model is selected in "main" view', async () => {
const { stdin, waitUntilReady, unmount } = await renderComponent();
@@ -17,6 +17,7 @@ import {
DEFAULT_GEMINI_FLASH_MODEL,
DEFAULT_GEMINI_FLASH_LITE_MODEL,
DEFAULT_GEMINI_MODEL_AUTO,
DEFAULT_GEMMA_4_MODEL,
ModelSlashCommandEvent,
logModelSlashCommand,
getDisplayString,
@@ -72,6 +73,7 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element {
DEFAULT_GEMINI_MODEL,
DEFAULT_GEMINI_FLASH_MODEL,
DEFAULT_GEMINI_FLASH_LITE_MODEL,
DEFAULT_GEMMA_4_MODEL,
PREVIEW_GEMINI_MODEL,
PREVIEW_GEMINI_3_1_MODEL,
PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL,
@@ -152,6 +154,11 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element {
title: getDisplayString(DEFAULT_GEMINI_FLASH_LITE_MODEL),
key: DEFAULT_GEMINI_FLASH_LITE_MODEL,
},
{
value: DEFAULT_GEMMA_4_MODEL,
title: getDisplayString(DEFAULT_GEMMA_4_MODEL),
key: DEFAULT_GEMMA_4_MODEL,
},
];
if (shouldShowPreviewModels) {
@@ -89,6 +89,17 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = {
model: 'gemini-2.5-flash-lite',
},
},
gemma4: {
extends: 'base',
modelConfig: {
model: 'gemma-4-26b-a4b-it',
generateContentConfig: {
temperature: 1,
topP: 0.95,
topK: 64,
},
},
},
// Bases for the internal model configs.
'gemini-2.5-flash-base': {
extends: 'base',
@@ -300,6 +311,13 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = {
isVisible: true,
features: { thinking: false, multimodalToolUse: false },
},
'gemma-4-26b-a4b-it': {
tier: 'pro',
family: 'gemma-4',
isPreview: false,
isVisible: true,
features: { thinking: false, multimodalToolUse: false },
},
// Aliases
auto: {
tier: 'auto',
@@ -307,6 +325,12 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = {
isVisible: false,
features: { thinking: true, multimodalToolUse: false },
},
gemma4: {
tier: 'pro',
isPreview: false,
isVisible: true,
features: { thinking: false, multimodalToolUse: false },
},
pro: {
tier: 'pro',
isPreview: false,
@@ -416,6 +440,9 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = {
'flash-lite': {
default: 'gemini-2.5-flash-lite',
},
gemma4: {
default: 'gemma-4-26b-a4b-it',
},
},
classifierIdResolutions: {
flash: {
+13 -1
View File
@@ -15,12 +15,14 @@ import {
isAutoModel,
getDisplayString,
DEFAULT_GEMINI_MODEL,
DEFAULT_GEMMA_4_MODEL,
PREVIEW_GEMINI_MODEL,
DEFAULT_GEMINI_FLASH_MODEL,
DEFAULT_GEMINI_FLASH_LITE_MODEL,
supportsMultimodalFunctionResponse,
GEMINI_MODEL_ALIAS_PRO,
GEMINI_MODEL_ALIAS_FLASH,
GEMMA_MODEL_ALIAS_4,
GEMINI_MODEL_ALIAS_AUTO,
PREVIEW_GEMINI_FLASH_MODEL,
PREVIEW_GEMINI_MODEL_AUTO,
@@ -336,6 +338,10 @@ describe('getDisplayString', () => {
);
});
it('should return the correct display string for Gemma 4', () => {
expect(getDisplayString(DEFAULT_GEMMA_4_MODEL)).toBe('Gemma 4 (26B)');
});
it('should return the model name as is for other models', () => {
expect(getDisplayString('custom-model')).toBe('custom-model');
expect(getDisplayString(DEFAULT_GEMINI_FLASH_LITE_MODEL)).toBe(
@@ -392,6 +398,11 @@ describe('resolveModel', () => {
);
});
it('should return Gemma 4 when gemma4 alias is requested', () => {
const model = resolveModel(GEMMA_MODEL_ALIAS_4);
expect(model).toBe(DEFAULT_GEMMA_4_MODEL);
});
it('should return a custom model name when requested', () => {
const customModel = 'custom-model-v1';
const model = resolveModel(customModel);
@@ -537,9 +548,10 @@ describe('isActiveModel', () => {
expect(isActiveModel(PREVIEW_GEMINI_MODEL)).toBe(true);
expect(isActiveModel(DEFAULT_GEMINI_FLASH_MODEL)).toBe(true);
expect(isActiveModel(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL)).toBe(true);
expect(isActiveModel(DEFAULT_GEMMA_4_MODEL)).toBe(true);
});
it('should return true for unknown models and aliases', () => {
it('should return false for unknown models and aliases', () => {
expect(isActiveModel('invalid-model')).toBe(false);
expect(isActiveModel(GEMINI_MODEL_ALIAS_AUTO)).toBe(false);
});
+9
View File
@@ -59,6 +59,7 @@ export const PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL =
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';
export const DEFAULT_GEMMA_4_MODEL = 'gemma-4-26b-a4b-it';
export const VALID_GEMINI_MODELS = new Set([
PREVIEW_GEMINI_MODEL,
@@ -69,6 +70,7 @@ export const VALID_GEMINI_MODELS = new Set([
DEFAULT_GEMINI_MODEL,
DEFAULT_GEMINI_FLASH_MODEL,
DEFAULT_GEMINI_FLASH_LITE_MODEL,
DEFAULT_GEMMA_4_MODEL,
]);
export const PREVIEW_GEMINI_MODEL_AUTO = 'auto-gemini-3';
@@ -79,6 +81,7 @@ export const GEMINI_MODEL_ALIAS_AUTO = 'auto';
export const GEMINI_MODEL_ALIAS_PRO = 'pro';
export const GEMINI_MODEL_ALIAS_FLASH = 'flash';
export const GEMINI_MODEL_ALIAS_FLASH_LITE = 'flash-lite';
export const GEMMA_MODEL_ALIAS_4 = 'gemma4';
export const DEFAULT_GEMINI_EMBEDDING_MODEL = 'gemini-embedding-001';
@@ -136,6 +139,10 @@ export function resolveModel(
resolved = DEFAULT_GEMINI_FLASH_LITE_MODEL;
break;
}
case GEMMA_MODEL_ALIAS_4: {
resolved = DEFAULT_GEMMA_4_MODEL;
break;
}
default: {
resolved = requestedModel;
break;
@@ -236,6 +243,8 @@ export function getDisplayString(
return PREVIEW_GEMINI_FLASH_MODEL;
case PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL:
return PREVIEW_GEMINI_3_1_MODEL;
case DEFAULT_GEMMA_4_MODEL:
return 'Gemma 4 (26B)';
default:
return model;
}