feat: automatic /model persistence across Gemini CLI sessions (#13199)

Co-authored-by: Jack Wotherspoon <jackwoth@google.com>
This commit is contained in:
Niyas Hameed
2025-12-23 19:53:43 +05:30
committed by GitHub
parent 3b1dbcd42d
commit 6be034392f
7 changed files with 48 additions and 6 deletions
+2 -4
View File
@@ -25,13 +25,11 @@ import { ExtensionManager } from './extension-manager.js';
import { RESUME_LATEST } from '../utils/sessionUtils.js';
vi.mock('./trustedFolders.js', () => ({
isWorkspaceTrusted: vi
.fn()
.mockReturnValue({ isTrusted: true, source: 'file' }), // Default to trusted
isWorkspaceTrusted: vi.fn(() => ({ isTrusted: true, source: 'file' })), // Default to trusted
}));
vi.mock('./sandboxConfig.js', () => ({
loadSandboxConfig: vi.fn().mockResolvedValue(undefined),
loadSandboxConfig: vi.fn(async () => undefined),
}));
vi.mock('fs', async (importOriginal) => {
+4
View File
@@ -35,6 +35,7 @@ import {
PREVIEW_GEMINI_MODEL_AUTO,
} from '@google/gemini-cli-core';
import type { Settings } from './settings.js';
import { saveModelChange, loadSettings } from './settings.js';
import { loadSandboxConfig } from './sandboxConfig.js';
import { resolvePath } from '../utils/resolvePath.js';
@@ -387,6 +388,8 @@ export async function loadCliConfig(
): Promise<Config> {
const debugMode = isDebugMode(argv);
const loadedSettings = loadSettings(cwd);
if (argv.sandbox) {
process.env['GEMINI_SANDBOX'] = 'true';
}
@@ -693,6 +696,7 @@ export async function loadCliConfig(
// TODO: loading of hooks based on workspace trust
enableHooks: settings.tools?.enableHooks ?? false,
hooks: settings.hooks || {},
onModelChange: (model: string) => saveModelChange(loadedSettings, model),
});
}
+15
View File
@@ -874,3 +874,18 @@ export function saveSettings(settingsFile: SettingsFile): void {
);
}
}
export function saveModelChange(
loadedSettings: LoadedSettings,
model: string,
): void {
try {
loadedSettings.setValue(SettingScope.User, 'model.name', model);
} catch (error) {
coreEvents.emitFeedback(
'error',
'There was an error saving your preferred model.',
error,
);
}
}
@@ -89,6 +89,9 @@ describe('<ModelDialog />', () => {
it('renders the initial "main" view correctly', () => {
const { lastFrame } = renderComponent();
expect(lastFrame()).toContain('Select Model');
expect(lastFrame()).toContain(
'Applies to this session and future Gemini CLI sessions.',
);
expect(lastFrame()).toContain('Auto');
expect(lastFrame()).toContain('Manual');
});
@@ -204,7 +204,6 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element {
)}
{subheader && <Text>{subheader}</Text>}
</Box>
<Box marginTop={1}>
<DescriptiveRadioButtonSelect
items={options}
@@ -215,7 +214,12 @@ export function ModelDialog({ onClose }: ModelDialogProps): React.JSX.Element {
</Box>
<Box marginTop={1} flexDirection="column">
<Text color={theme.text.secondary}>
{'To use a specific Gemini model on startup, use the --model flag.'}
Applies to this session and future Gemini CLI sessions.
</Text>
</Box>
<Box marginTop={1} flexDirection="column">
<Text color={theme.text.secondary}>
{'> To use a specific Gemini model on startup, use the --model flag.'}
</Text>
</Box>
<Box marginTop={1} flexDirection="column">