@@ -81,6 +81,14 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
8181 const [ modelDialogOpen , setModelDialogOpen ] = useState < boolean > ( false ) ;
8282 const [ showKeys , setShowKeys ] = useState < boolean > ( false ) ;
8383 const [ tempSelectedModelId , setTempSelectedModeId ] = useState < string | undefined > ( selectedModelId ) ;
84+ const [ providerModelOptions , setProviderModelOptions ] = useState < { [ key : string ] : string [ ] } > ( {
85+ 'openai' : [ ] ,
86+ 'azure' : [ ] ,
87+ 'anthropic' : [ ] ,
88+ 'gemini' : [ ] ,
89+ 'ollama' : [ ]
90+ } ) ;
91+ const [ isLoadingModelOptions , setIsLoadingModelOptions ] = useState < boolean > ( false ) ;
8492 const [ appConfig , setAppConfig ] = useState < AppConfig > ( { SHOW_KEYS_ENABLED : true } ) ;
8593
8694 // Fetch app configuration
@@ -108,23 +116,60 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
108116 const [ newApiBase , setNewApiBase ] = useState < string | undefined > ( undefined ) ;
109117 const [ newApiVersion , setNewApiVersion ] = useState < string | undefined > ( undefined ) ;
110118
119+ // Fetch available models from the API
120+ useEffect ( ( ) => {
121+ const fetchModelOptions = async ( ) => {
122+ setIsLoadingModelOptions ( true ) ;
123+ try {
124+ const response = await fetch ( getUrls ( ) . CHECK_AVAILABLE_MODELS ) ;
125+ const data = await response . json ( ) ;
126+
127+ // Group models by provider
128+ const modelsByProvider : { [ key : string ] : string [ ] } = {
129+ 'openai' : [ ] ,
130+ 'azure' : [ ] ,
131+ 'anthropic' : [ ] ,
132+ 'gemini' : [ ] ,
133+ 'ollama' : [ ]
134+ } ;
135+
136+ data . forEach ( ( modelConfig : any ) => {
137+ const provider = modelConfig . endpoint ;
138+ const model = modelConfig . model ;
139+
140+ if ( provider && model && ! modelsByProvider [ provider ] . includes ( model ) ) {
141+ modelsByProvider [ provider ] . push ( model ) ;
142+ }
143+ } ) ;
144+
145+ setProviderModelOptions ( modelsByProvider ) ;
146+ } catch ( error ) {
147+ console . error ( "Failed to fetch model options:" , error ) ;
148+ } finally {
149+ setIsLoadingModelOptions ( false ) ;
150+ }
151+ } ;
152+
153+ fetchModelOptions ( ) ;
154+ } , [ ] ) ;
155+
111156 useEffect ( ( ) => {
112157 if ( newEndpoint == 'ollama' ) {
113158 if ( ! newApiBase ) {
114159 setNewApiBase ( 'http://localhost:11434' ) ;
115160 }
116161 }
117162 if ( newEndpoint == "openai" ) {
118- if ( ! newModel ) {
119- setNewModel ( 'gpt-4o' ) ;
163+ if ( ! newModel && providerModelOptions . openai . length > 0 ) {
164+ setNewModel ( providerModelOptions . openai [ 0 ] ) ;
120165 }
121166 }
122167 if ( newEndpoint == "anthropic" ) {
123- if ( ! newModel ) {
124- setNewModel ( 'claude-3-5-sonnet-20241022' ) ;
168+ if ( ! newModel && providerModelOptions . anthropic . length > 0 ) {
169+ setNewModel ( providerModelOptions . anthropic [ 0 ] ) ;
125170 }
126171 }
127- } , [ newEndpoint ] ) ;
172+ } , [ newEndpoint , providerModelOptions ] ) ;
128173
129174 let modelExists = models . some ( m =>
130175 m . endpoint == newEndpoint && m . model == newModel && m . api_base == newApiBase
@@ -168,8 +213,8 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
168213 value = { newEndpoint }
169214 onChange = { ( event : any , newValue : string | null ) => {
170215 setNewEndpoint ( newValue || "" ) ;
171- if ( newModel == "" && newValue == "openai" ) {
172- setNewModel ( "gpt-4o" ) ;
216+ if ( newModel == "" && newValue == "openai" && providerModelOptions . openai . length > 0 ) {
217+ setNewModel ( providerModelOptions . openai [ 0 ] ) ;
173218 }
174219 if ( ! newApiVersion && newValue == "azure" ) {
175220 setNewApiVersion ( "2024-02-15" ) ;
@@ -220,7 +265,8 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
220265 freeSolo
221266 onChange = { ( event : any , newValue : string | null ) => { setNewModel ( newValue || "" ) ; } }
222267 value = { newModel }
223- options = { [ 'gpt-4o-mini' , 'gpt-4o' , 'claude-3-5-sonnet-20241022' ] }
268+ options = { newEndpoint && providerModelOptions [ newEndpoint ] ? providerModelOptions [ newEndpoint ] : [ ] }
269+ loading = { isLoadingModelOptions }
224270 renderOption = { ( props , option ) => {
225271 return < Typography { ...props } onClick = { ( ) => { setNewModel ( option ) ; } } sx = { { fontSize : "small" } } > { option } </ Typography >
226272 } }
@@ -229,7 +275,16 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
229275 error = { newEndpoint != "" && ! newModel }
230276 { ...params }
231277 placeholder = "model name"
232- InputProps = { { ...params . InputProps , style : { fontSize : "0.875rem" } } }
278+ InputProps = { {
279+ ...params . InputProps ,
280+ style : { fontSize : "0.875rem" } ,
281+ endAdornment : (
282+ < >
283+ { isLoadingModelOptions ? < CircularProgress color = "inherit" size = { 20 } /> : null }
284+ { params . InputProps . endAdornment }
285+ </ >
286+ ) ,
287+ } }
233288 inputProps = { {
234289 ...params . inputProps ,
235290 'aria-label' : 'Select or enter a model' ,
@@ -244,7 +299,7 @@ export const ModelSelectionButton: React.FC<{}> = ({ }) => {
244299 PaperComponent = { ( { children } ) => (
245300 < Paper >
246301 < Typography sx = { { p : 1 , color : 'gray' , fontStyle : 'italic' , fontSize : 'small' } } >
247- examples
302+ { isLoadingModelOptions ? 'Loading models...' : ' examples' }
248303 </ Typography >
249304 { children }
250305 </ Paper >
0 commit comments