2025-09-23 12:50:09 -04:00
/ * *
* @license
* Copyright 2025 Google LLC
* SPDX - License - Identifier : Apache - 2.0
* /
import type React from 'react' ;
import { useCallback , useContext , useMemo } from 'react' ;
import { Box , Text } from 'ink' ;
import {
2025-11-18 12:01:16 -05:00
PREVIEW_GEMINI_MODEL ,
2025-09-23 12:50:09 -04:00
DEFAULT_GEMINI_MODEL ,
2025-11-18 12:01:16 -05:00
DEFAULT_GEMINI_FLASH_MODEL ,
DEFAULT_GEMINI_FLASH_LITE_MODEL ,
2025-09-23 12:50:09 -04:00
DEFAULT_GEMINI_MODEL_AUTO ,
2025-11-18 12:01:16 -05:00
GEMINI_MODEL_ALIAS_FLASH ,
GEMINI_MODEL_ALIAS_FLASH_LITE ,
GEMINI_MODEL_ALIAS_PRO ,
2025-09-23 16:52:34 -07:00
ModelSlashCommandEvent ,
logModelSlashCommand ,
2025-09-23 12:50:09 -04:00
} from '@google/gemini-cli-core' ;
import { useKeypress } from '../hooks/useKeypress.js' ;
import { theme } from '../semantic-colors.js' ;
import { DescriptiveRadioButtonSelect } from './shared/DescriptiveRadioButtonSelect.js' ;
import { ConfigContext } from '../contexts/ConfigContext.js' ;
2025-11-18 12:01:16 -05:00
import Gradient from 'ink-gradient' ;
2025-09-23 12:50:09 -04:00
interface ModelDialogProps {
onClose : ( ) = > void ;
}
export function ModelDialog ( { onClose } : ModelDialogProps ) : React . JSX . Element {
const config = useContext ( ConfigContext ) ;
// Determine the Preferred Model (read once when the dialog opens).
const preferredModel = config ? . getModel ( ) || DEFAULT_GEMINI_MODEL_AUTO ;
useKeypress (
( key ) = > {
if ( key . name === 'escape' ) {
onClose ( ) ;
}
} ,
{ isActive : true } ,
) ;
2025-11-18 12:01:16 -05:00
const options = useMemo (
( ) = > [
{
value : DEFAULT_GEMINI_MODEL_AUTO ,
title : 'Auto' ,
description : 'Let the system choose the best model for your task.' ,
key : DEFAULT_GEMINI_MODEL_AUTO ,
} ,
{
value : GEMINI_MODEL_ALIAS_PRO ,
title : config?.getPreviewFeatures ( )
? ` Pro ( ${ PREVIEW_GEMINI_MODEL } , ${ DEFAULT_GEMINI_MODEL } ) `
: ` Pro ( ${ DEFAULT_GEMINI_MODEL } ) ` ,
description :
'For complex tasks that require deep reasoning and creativity' ,
key : GEMINI_MODEL_ALIAS_PRO ,
} ,
{
value : GEMINI_MODEL_ALIAS_FLASH ,
title : ` Flash ( ${ DEFAULT_GEMINI_FLASH_MODEL } ) ` ,
description : 'For tasks that need a balance of speed and reasoning' ,
key : GEMINI_MODEL_ALIAS_FLASH ,
} ,
{
value : GEMINI_MODEL_ALIAS_FLASH_LITE ,
title : ` Flash-Lite ( ${ DEFAULT_GEMINI_FLASH_LITE_MODEL } ) ` ,
description : 'For simple tasks that need to be done quickly' ,
key : GEMINI_MODEL_ALIAS_FLASH_LITE ,
} ,
] ,
[ config ] ,
) ;
2025-09-23 12:50:09 -04:00
// Calculate the initial index based on the preferred model.
const initialIndex = useMemo (
2025-11-18 12:01:16 -05:00
( ) = > options . findIndex ( ( option ) = > option . value === preferredModel ) ,
[ preferredModel , options ] ,
2025-09-23 12:50:09 -04:00
) ;
// Handle selection internally (Autonomous Dialog).
const handleSelect = useCallback (
( model : string ) = > {
if ( config ) {
config . setModel ( model ) ;
2025-09-23 18:06:03 -04:00
const event = new ModelSlashCommandEvent ( model ) ;
logModelSlashCommand ( config , event ) ;
2025-09-23 12:50:09 -04:00
}
onClose ( ) ;
} ,
[ config , onClose ] ,
) ;
2025-11-18 12:01:16 -05:00
const header = config ? . getPreviewFeatures ( )
? 'Gemini 3 is now enabled.'
: 'Gemini 3 is now available.' ;
const subheader = config ? . getPreviewFeatures ( )
? ` To disable Gemini 3, disable "Preview features" in /settings. \ nLearn more at https://goo.gle/enable-preview-features \ n \ nWhen you select Auto or Pro, Gemini CLI will attempt to use ${ PREVIEW_GEMINI_MODEL } first, before falling back to ${ DEFAULT_GEMINI_MODEL } . `
: ` To use Gemini 3, enable "Preview features" in /settings. \ nLearn more at https://goo.gle/enable-preview-features ` ;
2025-09-23 12:50:09 -04:00
return (
< Box
borderStyle = "round"
borderColor = { theme . border . default }
flexDirection = "column"
padding = { 1 }
width = "100%"
>
< Text bold > Select Model < / Text >
2025-11-18 12:01:16 -05:00
< Box marginTop = { 1 } marginBottom = { 1 } flexDirection = "column" >
< Gradient colors = { theme . ui . gradient } >
< Text > { header } < / Text >
< / Gradient >
< Text > { subheader } < / Text >
< / Box >
2025-09-23 12:50:09 -04:00
< Box marginTop = { 1 } >
< DescriptiveRadioButtonSelect
2025-11-18 12:01:16 -05:00
items = { options }
2025-09-23 12:50:09 -04:00
onSelect = { handleSelect }
initialIndex = { initialIndex }
showNumbers = { true }
/ >
< / Box >
2025-11-18 12:01:16 -05:00
< Box marginTop = { 1 } flexDirection = "column" >
2025-09-23 12:50:09 -04:00
< Text color = { theme . text . secondary } >
2025-11-18 12:01:16 -05:00
{ 'To use a specific Gemini model on startup, use the --model flag.' }
2025-09-23 12:50:09 -04:00
< / Text >
< / Box >
< Box marginTop = { 1 } flexDirection = "column" >
< Text color = { theme . text . secondary } > ( Press Esc to close ) < / Text >
< / Box >
< / Box >
) ;
}