@@ -48,6 +48,8 @@ export function LLMProviderUpdateForm({
48
48
49
49
const [ isTesting , setIsTesting ] = useState ( false ) ;
50
50
const [ testError , setTestError ] = useState < string > ( "" ) ;
51
+ const [ isFetchingModels , setIsFetchingModels ] = useState ( false ) ;
52
+ const [ fetchModelsError , setFetchModelsError ] = useState < string > ( "" ) ;
51
53
52
54
const [ showAdvancedOptions , setShowAdvancedOptions ] = useState ( false ) ;
53
55
@@ -97,6 +99,9 @@ export function LLMProviderUpdateForm({
97
99
( llmProviderDescriptor . model_configurations
98
100
. filter ( ( modelConfiguration ) => modelConfiguration . is_visible )
99
101
. map ( ( modelConfiguration ) => modelConfiguration . name ) as string [ ] ) ,
102
+
103
+ // Helper field to force re-renders when model list updates
104
+ _modelListUpdated : 0 ,
100
105
} ;
101
106
102
107
// Setup validation schema if required
@@ -179,6 +184,99 @@ export function LLMProviderUpdateForm({
179
184
) ;
180
185
} ;
181
186
187
+ const fetchBedrockModels = async ( values : any , setFieldValue : any ) => {
188
+ if ( llmProviderDescriptor . name !== "bedrock" ) {
189
+ return ;
190
+ }
191
+
192
+ setIsFetchingModels ( true ) ;
193
+ setFetchModelsError ( "" ) ;
194
+
195
+ try {
196
+ const response = await fetch ( "/api/admin/llm/bedrock/available-models" , {
197
+ method : "POST" ,
198
+ headers : {
199
+ "Content-Type" : "application/json" ,
200
+ } ,
201
+ body : JSON . stringify ( {
202
+ aws_region_name : values . custom_config ?. AWS_REGION_NAME ,
203
+ aws_access_key_id : values . custom_config ?. AWS_ACCESS_KEY_ID ,
204
+ aws_secret_access_key : values . custom_config ?. AWS_SECRET_ACCESS_KEY ,
205
+ aws_bearer_token_bedrock :
206
+ values . custom_config ?. AWS_BEARER_TOKEN_BEDROCK ,
207
+ provider_name : existingLlmProvider ?. name , // Save models to existing provider if editing
208
+ } ) ,
209
+ } ) ;
210
+
211
+ if ( ! response . ok ) {
212
+ const errorData = await response . json ( ) ;
213
+ throw new Error ( errorData . detail || "Failed to fetch models" ) ;
214
+ }
215
+
216
+ const availableModels : string [ ] = await response . json ( ) ;
217
+
218
+ // Update the model configurations with the fetched models
219
+ const updatedModelConfigs = availableModels . map ( ( modelName ) => {
220
+ // Find existing configuration to preserve is_visible setting
221
+ const existingConfig = llmProviderDescriptor . model_configurations . find (
222
+ ( config ) => config . name === modelName
223
+ ) ;
224
+
225
+ return {
226
+ name : modelName ,
227
+ is_visible : existingConfig ?. is_visible ?? false , // Preserve existing visibility or default to false
228
+ max_input_tokens : null ,
229
+ supports_image_input : false , // Will be determined by the backend
230
+ } ;
231
+ } ) ;
232
+
233
+ // Update the descriptor and form values
234
+ llmProviderDescriptor . model_configurations = updatedModelConfigs ;
235
+
236
+ // Update selected model names to only include previously visible models that are available
237
+ const previouslySelectedModels = values . selected_model_names || [ ] ;
238
+ const stillAvailableSelectedModels = previouslySelectedModels . filter (
239
+ ( modelName : string ) => availableModels . includes ( modelName )
240
+ ) ;
241
+ setFieldValue ( "selected_model_names" , stillAvailableSelectedModels ) ;
242
+
243
+ // Set a default model if none is set
244
+ if (
245
+ ( ! values . default_model_name ||
246
+ ! availableModels . includes ( values . default_model_name ) ) &&
247
+ availableModels . length > 0
248
+ ) {
249
+ setFieldValue ( "default_model_name" , availableModels [ 0 ] ) ;
250
+ }
251
+
252
+ // Clear fast model if it's not in the new list
253
+ if (
254
+ values . fast_default_model_name &&
255
+ ! availableModels . includes ( values . fast_default_model_name )
256
+ ) {
257
+ setFieldValue ( "fast_default_model_name" , null ) ;
258
+ }
259
+
260
+ // Force a re-render by updating a timestamp or counter
261
+ setFieldValue ( "_modelListUpdated" , Date . now ( ) ) ;
262
+
263
+ setPopup ?.( {
264
+ message : `Successfully fetched ${ availableModels . length } models for the selected region (including cross-region inference models).` ,
265
+ type : "success" ,
266
+ } ) ;
267
+ } catch ( error ) {
268
+ const errorMessage =
269
+ error instanceof Error ? error . message : "Unknown error" ;
270
+ setFetchModelsError ( errorMessage ) ;
271
+ setPopup ?.( {
272
+ message : `Failed to fetch models: ${ errorMessage } ` ,
273
+ type : "error" ,
274
+ } ) ;
275
+ } finally {
276
+ setIsFetchingModels ( false ) ;
277
+ }
278
+ } ;
279
+
182
280
return (
183
281
< Formik
184
282
initialValues = { initialValues }
@@ -191,6 +289,7 @@ export function LLMProviderUpdateForm({
191
289
selected_model_names : visibleModels ,
192
290
model_configurations : modelConfigurations ,
193
291
target_uri,
292
+ _modelListUpdated,
194
293
...rest
195
294
} = values ;
196
295
@@ -390,6 +489,7 @@ export function LLMProviderUpdateForm({
390
489
</ ReactMarkdown >
391
490
}
392
491
placeholder = { customConfigKey . default_value || undefined }
492
+ type = { customConfigKey . is_secret ? "password" : "text" }
393
493
/>
394
494
</ div >
395
495
) ;
@@ -407,6 +507,47 @@ export function LLMProviderUpdateForm({
407
507
}
408
508
} ) }
409
509
510
+ { /* Bedrock-specific fetch models button */ }
511
+ { llmProviderDescriptor . name === "bedrock" && (
512
+ < div className = "flex flex-col gap-2" >
513
+ < Button
514
+ type = "button"
515
+ onClick = { ( ) =>
516
+ fetchBedrockModels (
517
+ formikProps . values ,
518
+ formikProps . setFieldValue
519
+ )
520
+ }
521
+ disabled = {
522
+ isFetchingModels ||
523
+ ! formikProps . values . custom_config ?. AWS_REGION_NAME
524
+ }
525
+ className = "w-fit"
526
+ >
527
+ { isFetchingModels ? (
528
+ < >
529
+ < LoadingAnimation size = "text-sm" />
530
+ < span className = "ml-2" > Fetching Models...</ span >
531
+ </ >
532
+ ) : (
533
+ "Fetch Available Models for Region"
534
+ ) }
535
+ </ Button >
536
+
537
+ { fetchModelsError && (
538
+ < Text className = "text-red-600 text-sm" > { fetchModelsError } </ Text >
539
+ ) }
540
+
541
+ < Text className = "text-sm text-gray-600" >
542
+ Enter your AWS region, then click this button to fetch available
543
+ Bedrock models.
544
+ < br />
545
+ If you're updating your existing provider, you'll need
546
+ to click this button to fetch the latest models.
547
+ </ Text >
548
+ </ div >
549
+ ) }
550
+
410
551
{ ! firstTimeConfiguration && (
411
552
< >
412
553
< Separator />
0 commit comments