feat(cli): add streamlined gemini gemma local model setup (#25498)

Co-authored-by: Abhijit Balaji <abhijitbalaji@google.com>
Co-authored-by: Samee Zahid <sameez@google.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
Samee Zahid
2026-04-20 16:57:56 -07:00
committed by GitHub
parent 6afc47f81c
commit 1d383a4a8e
31 changed files with 2509 additions and 12 deletions
+13
View File
@@ -338,6 +338,7 @@ describe('parseArguments', () => {
{ cmd: 'skill list', expected: true },
{ cmd: 'hooks migrate', expected: true },
{ cmd: 'hook migrate', expected: true },
{ cmd: 'gemma status', expected: true },
{ cmd: 'some query', expected: undefined },
{ cmd: 'hello world', expected: undefined },
])(
@@ -758,6 +759,12 @@ describe('parseArguments', () => {
const argv = await parseArguments(settings);
expect(argv.isCommand).toBe(true);
});
it('should set isCommand to true for gemma command', async () => {
process.argv = ['node', 'script.js', 'gemma', 'status'];
const argv = await parseArguments(createTestMergedSettings());
expect(argv.isCommand).toBe(true);
});
});
describe('loadCliConfig', () => {
@@ -3030,6 +3037,8 @@ describe('loadCliConfig gemmaModelRouter', () => {
experimental: {
gemmaModelRouter: {
enabled: true,
autoStartServer: false,
binaryPath: '/custom/lit',
classifier: {
host: 'http://custom:1234',
model: 'custom-gemma',
@@ -3040,6 +3049,8 @@ describe('loadCliConfig gemmaModelRouter', () => {
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getGemmaModelRouterEnabled()).toBe(true);
const gemmaSettings = config.getGemmaModelRouterSettings();
expect(gemmaSettings.autoStartServer).toBe(false);
expect(gemmaSettings.binaryPath).toBe('/custom/lit');
expect(gemmaSettings.classifier?.host).toBe('http://custom:1234');
expect(gemmaSettings.classifier?.model).toBe('custom-gemma');
});
@@ -3057,6 +3068,8 @@ describe('loadCliConfig gemmaModelRouter', () => {
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getGemmaModelRouterEnabled()).toBe(true);
const gemmaSettings = config.getGemmaModelRouterSettings();
expect(gemmaSettings.autoStartServer).toBe(false);
expect(gemmaSettings.binaryPath).toBe('');
expect(gemmaSettings.classifier?.host).toBe('http://localhost:9379');
expect(gemmaSettings.classifier?.model).toBe('gemma3-1b-gpu-custom');
});
+3
View File
@@ -13,6 +13,7 @@ import { mcpCommand } from '../commands/mcp.js';
import { extensionsCommand } from '../commands/extensions.js';
import { skillsCommand } from '../commands/skills.js';
import { hooksCommand } from '../commands/hooks.js';
import { gemmaCommand } from '../commands/gemma.js';
import {
setGeminiMdFilename as setServerGeminiMdFilename,
getCurrentGeminiMdFilename,
@@ -181,6 +182,7 @@ export async function parseArguments(
extensionsCommand,
skillsCommand,
hooksCommand,
gemmaCommand,
];
const subcommands = commandModules.flatMap((mod) => {
@@ -260,6 +262,7 @@ export async function parseArguments(
yargsInstance.command(extensionsCommand);
yargsInstance.command(skillsCommand);
yargsInstance.command(hooksCommand);
yargsInstance.command(gemmaCommand);
yargsInstance
.command('$0 [query..]', 'Launch Gemini CLI', (yargsInstance) =>
+23 -1
View File
@@ -471,11 +471,33 @@ describe('SettingsSchema', () => {
expect(enabled.category).toBe('Experimental');
expect(enabled.default).toBe(false);
expect(enabled.requiresRestart).toBe(true);
expect(enabled.showInDialog).toBe(false);
expect(enabled.showInDialog).toBe(true);
expect(enabled.description).toBe(
'Enable the Gemma Model Router (experimental). Requires a local endpoint serving Gemma via the Gemini API using LiteRT-LM shim.',
);
const autoStartServer = gemmaModelRouter.properties.autoStartServer;
expect(autoStartServer).toBeDefined();
expect(autoStartServer.type).toBe('boolean');
expect(autoStartServer.category).toBe('Experimental');
expect(autoStartServer.default).toBe(false);
expect(autoStartServer.requiresRestart).toBe(true);
expect(autoStartServer.showInDialog).toBe(true);
expect(autoStartServer.description).toBe(
'Automatically start the LiteRT-LM server when Gemini CLI starts and the Gemma router is enabled.',
);
const binaryPath = gemmaModelRouter.properties.binaryPath;
expect(binaryPath).toBeDefined();
expect(binaryPath.type).toBe('string');
expect(binaryPath.category).toBe('Experimental');
expect(binaryPath.default).toBe('');
expect(binaryPath.requiresRestart).toBe(true);
expect(binaryPath.showInDialog).toBe(false);
expect(binaryPath.description).toBe(
'Custom path to the LiteRT-LM binary. Leave empty to use the default location (~/.gemini/bin/litert/).',
);
const classifier = gemmaModelRouter.properties.classifier;
expect(classifier).toBeDefined();
expect(classifier.type).toBe('object');
+20
View File
@@ -2169,6 +2169,26 @@ const SETTINGS_SCHEMA = {
default: false,
description:
'Enable the Gemma Model Router (experimental). Requires a local endpoint serving Gemma via the Gemini API using LiteRT-LM shim.',
showInDialog: true,
},
autoStartServer: {
type: 'boolean',
label: 'Auto-start LiteRT Server',
category: 'Experimental',
requiresRestart: true,
default: false,
description:
'Automatically start the LiteRT-LM server when Gemini CLI starts and the Gemma router is enabled.',
showInDialog: true,
},
binaryPath: {
type: 'string',
label: 'LiteRT Binary Path',
category: 'Experimental',
requiresRestart: true,
default: '',
description:
'Custom path to the LiteRT-LM binary. Leave empty to use the default location (~/.gemini/bin/litert/).',
showInDialog: false,
},
classifier: {