mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-26 21:14:35 -07:00
feat(cli): Add /model command for interactive model selection (#8940)
Co-authored-by: Miguel Solorio <miguel.solorio07@gmail.com>
This commit is contained in:
@@ -107,6 +107,7 @@ describe('useSlashCommandProcessor', () => {
|
||||
const mockLoadHistory = vi.fn();
|
||||
const mockOpenThemeDialog = vi.fn();
|
||||
const mockOpenAuthDialog = vi.fn();
|
||||
const mockOpenModelDialog = vi.fn();
|
||||
const mockSetQuittingMessages = vi.fn();
|
||||
|
||||
const mockConfig = makeFakeConfig({});
|
||||
@@ -147,6 +148,7 @@ describe('useSlashCommandProcessor', () => {
|
||||
openEditorDialog: vi.fn(),
|
||||
openPrivacyNotice: vi.fn(),
|
||||
openSettingsDialog: vi.fn(),
|
||||
openModelDialog: mockOpenModelDialog,
|
||||
quit: mockSetQuittingMessages,
|
||||
setDebugMessage: vi.fn(),
|
||||
toggleCorgiMode: vi.fn(),
|
||||
@@ -391,6 +393,21 @@ describe('useSlashCommandProcessor', () => {
|
||||
expect(mockOpenThemeDialog).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle "dialog: model" action', async () => {
|
||||
const command = createTestCommand({
|
||||
name: 'modelcmd',
|
||||
action: vi.fn().mockResolvedValue({ type: 'dialog', dialog: 'model' }),
|
||||
});
|
||||
const result = setupProcessorHook([command]);
|
||||
await waitFor(() => expect(result.current.slashCommands).toHaveLength(1));
|
||||
|
||||
await act(async () => {
|
||||
await result.current.handleSlashCommand('/modelcmd');
|
||||
});
|
||||
|
||||
expect(mockOpenModelDialog).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle "load_history" action', async () => {
|
||||
const mockClient = {
|
||||
setHistory: vi.fn(),
|
||||
|
||||
@@ -49,6 +49,7 @@ interface SlashCommandProcessorActions {
|
||||
openEditorDialog: () => void;
|
||||
openPrivacyNotice: () => void;
|
||||
openSettingsDialog: () => void;
|
||||
openModelDialog: () => void;
|
||||
openPermissionsDialog: () => void;
|
||||
quit: (messages: HistoryItem[]) => void;
|
||||
setDebugMessage: (message: string) => void;
|
||||
@@ -374,6 +375,9 @@ export const useSlashCommandProcessor = (
|
||||
case 'settings':
|
||||
actions.openSettingsDialog();
|
||||
return { type: 'handled' };
|
||||
case 'model':
|
||||
actions.openModelDialog();
|
||||
return { type: 'handled' };
|
||||
case 'permissions':
|
||||
actions.openPermissionsDialog();
|
||||
return { type: 'handled' };
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { renderHook, act } from '@testing-library/react';
|
||||
import { useModelCommand } from './useModelCommand.js';
|
||||
|
||||
describe('useModelCommand', () => {
|
||||
it('should initialize with the model dialog closed', () => {
|
||||
const { result } = renderHook(() => useModelCommand());
|
||||
expect(result.current.isModelDialogOpen).toBe(false);
|
||||
});
|
||||
|
||||
it('should open the model dialog when openModelDialog is called', () => {
|
||||
const { result } = renderHook(() => useModelCommand());
|
||||
|
||||
act(() => {
|
||||
result.current.openModelDialog();
|
||||
});
|
||||
|
||||
expect(result.current.isModelDialogOpen).toBe(true);
|
||||
});
|
||||
|
||||
it('should close the model dialog when closeModelDialog is called', () => {
|
||||
const { result } = renderHook(() => useModelCommand());
|
||||
|
||||
// Open it first
|
||||
act(() => {
|
||||
result.current.openModelDialog();
|
||||
});
|
||||
expect(result.current.isModelDialogOpen).toBe(true);
|
||||
|
||||
// Then close it
|
||||
act(() => {
|
||||
result.current.closeModelDialog();
|
||||
});
|
||||
expect(result.current.isModelDialogOpen).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
|
||||
interface UseModelCommandReturn {
|
||||
isModelDialogOpen: boolean;
|
||||
openModelDialog: () => void;
|
||||
closeModelDialog: () => void;
|
||||
}
|
||||
|
||||
export const useModelCommand = (): UseModelCommandReturn => {
|
||||
const [isModelDialogOpen, setIsModelDialogOpen] = useState(false);
|
||||
|
||||
const openModelDialog = useCallback(() => {
|
||||
setIsModelDialogOpen(true);
|
||||
}, []);
|
||||
|
||||
const closeModelDialog = useCallback(() => {
|
||||
setIsModelDialogOpen(false);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
isModelDialogOpen,
|
||||
openModelDialog,
|
||||
closeModelDialog,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user