@@ -33,6 +33,7 @@ function App() {
3333 const [ modelsFetched , setModelsFetched ] = useState ( false ) ;
3434 const [ form , setForm ] = useState ( defaultForm ( ) ) ;
3535 const [ ollamaModels , setOllamaModels ] = useState ( [ ] ) ;
36+ const [ bedrockModels , setBedrockModels ] = useState ( [ ] ) ;
3637 const [ dynamicModels , setDynamicModels ] = useState ( [ ] ) ;
3738 const [ apiDefaultModel , setApiDefaultModel ] = useState ( '' ) ;
3839 const [ session , setSession ] = useState ( null ) ;
@@ -44,7 +45,7 @@ function App() {
4445 } , [ form . provider_name ] ) ;
4546
4647 useEffect ( ( ) => {
47- if ( ! form . provider_name || form . provider_name === 'ollama' ) {
48+ if ( ! form . provider_name || form . provider_name === 'ollama' || form . provider_name === 'bedrock' ) {
4849 setDynamicModels ( [ ] ) ;
4950 setApiDefaultModel ( '' ) ;
5051 return ;
@@ -93,11 +94,14 @@ function App() {
9394 if ( form . provider_name === 'ollama' && ollamaModels . length > 0 ) {
9495 return ollamaModels ;
9596 }
97+ if ( form . provider_name === 'bedrock' && bedrockModels . length > 0 ) {
98+ return bedrockModels . map ( ( model ) => model . model_id ) ;
99+ }
96100 if ( dynamicModels . length > 0 ) {
97101 return dynamicModels ;
98102 }
99103 return selectedProvider . models || [ ] ;
100- } , [ selectedProvider , form . provider_name , ollamaModels , dynamicModels ] ) ;
104+ } , [ selectedProvider , form . provider_name , ollamaModels , bedrockModels , dynamicModels ] ) ;
101105
102106 const [ searchQuery , setSearchQuery ] = useState ( '' ) ;
103107 const [ isOpen , setIsOpen ] = useState ( false ) ;
@@ -431,6 +435,7 @@ function App() {
431435 const connector = connectors . find ( ( entry ) => String ( entry . id ) === String ( route . connectorID ) ) ;
432436 if ( connector ) {
433437 setOllamaModels ( [ ] ) ;
438+ setBedrockModels ( [ ] ) ;
434439 setModelsFetched ( false ) ;
435440 setFetchingModels ( false ) ;
436441 setForm ( {
@@ -442,6 +447,8 @@ function App() {
442447 selected_model : connector . selected_model || '' ,
443448 gcp_project_id : connector . gcp_project_id || '' ,
444449 gcp_location : connector . gcp_location || '' ,
450+ aws_access_key_id : connector . aws_access_key_id || '' ,
451+ aws_region : connector . aws_region || '' ,
445452 role : connector . role || 'leader' ,
446453 } ) ;
447454 setStatus ( `Editing connector #${ connector . id } ` ) ;
@@ -452,6 +459,7 @@ function App() {
452459 function resetFormState ( role ) {
453460 setForm ( { ...defaultForm ( ) , role : role || 'leader' } ) ;
454461 setOllamaModels ( [ ] ) ;
462+ setBedrockModels ( [ ] ) ;
455463 setApiDefaultModel ( '' ) ;
456464 setModelsFetched ( false ) ;
457465 setFetchingModels ( false ) ;
@@ -471,12 +479,21 @@ function App() {
471479 : '' ,
472480 gcp_project_id : '' ,
473481 gcp_location : '' ,
482+ aws_access_key_id : '' ,
483+ aws_region : '' ,
474484 } ) ) ;
475485 if ( provider . id !== 'ollama' ) {
476486 setOllamaModels ( [ ] ) ;
487+ }
488+ if ( provider . id !== 'bedrock' ) {
489+ setBedrockModels ( [ ] ) ;
490+ }
491+ if ( provider . id !== 'ollama' && provider . id !== 'bedrock' ) {
477492 setApiDefaultModel ( '' ) ;
478493 setModelsFetched ( false ) ;
479494 }
495+ setStatus ( '' ) ;
496+ setError ( '' ) ;
480497 }
481498
482499 function setFormField ( field , value ) {
@@ -501,8 +518,14 @@ function App() {
501518 selected_model : connector . selected_model || '' ,
502519 gcp_project_id : connector . gcp_project_id || '' ,
503520 gcp_location : connector . gcp_location || '' ,
521+ aws_access_key_id : connector . aws_access_key_id || '' ,
522+ aws_region : connector . aws_region || '' ,
504523 role : connector . role || 'leader' ,
505524 } ) ;
525+ setOllamaModels ( [ ] ) ;
526+ setBedrockModels ( [ ] ) ;
527+ setModelsFetched ( false ) ;
528+ setFetchingModels ( false ) ;
506529 setStatus ( `Editing connector #${ connector . id } ` ) ;
507530 navigate ( `/connectors/edit/${ connector . id } ` ) ;
508531 }
@@ -545,6 +568,51 @@ function App() {
545568 }
546569 }
547570
571+ async function fetchBedrockModels ( ) {
572+ setFetchingModels ( true ) ;
573+ setError ( '' ) ;
574+ setStatus ( '' ) ;
575+ const awsRegion = ( form . aws_region || '' ) . trim ( ) ;
576+ if ( ! awsRegion ) {
577+ setError ( 'Region is required for Bedrock model discovery' ) ;
578+ setFetchingModels ( false ) ;
579+ return ;
580+ }
581+ try {
582+ const response = await api ( '/api/ui/connectors/bedrock/models' , {
583+ method : 'POST' ,
584+ body : JSON . stringify ( {
585+ access_key_id : ( form . aws_access_key_id || '' ) . trim ( ) ,
586+ secret_access_key : form . api_key || '' ,
587+ region : awsRegion ,
588+ } ) ,
589+ } ) ;
590+ const models = response . models || [ ] ;
591+ setBedrockModels ( models ) ;
592+ setModelsFetched ( true ) ;
593+ const modelIds = models . map ( ( model ) => model . model_id ) ;
594+ setForm ( ( prev ) => {
595+ if ( prev . selected_model && modelIds . includes ( prev . selected_model ) ) {
596+ return prev ;
597+ }
598+ return { ...prev , selected_model : '' } ;
599+ } ) ;
600+ if ( models . length === 0 ) {
601+ setError ( 'No foundation models found for this region. Request model access in the AWS Bedrock console first.' ) ;
602+ } else {
603+ setStatus ( `Fetched ${ models . length } Bedrock model(s)` ) ;
604+ }
605+ } catch ( err ) {
606+ setModelsFetched ( false ) ;
607+ if ( await handleAuthError ( err ) ) {
608+ return ;
609+ }
610+ setError ( err . message || String ( err ) ) ;
611+ } finally {
612+ setFetchingModels ( false ) ;
613+ }
614+ }
615+
548616 async function saveConnector ( ) {
549617 const provider = providers . find ( ( entry ) => entry . id === form . provider_name ) || providers [ 0 ] ;
550618 const connectorName = ( form . connector_name || '' ) . trim ( ) ;
@@ -582,6 +650,27 @@ function App() {
582650 return ;
583651 }
584652
653+ if ( ! selectedModel ) {
654+ setError ( 'Please select a model' ) ;
655+ setStatus ( '' ) ;
656+ return ;
657+ }
658+ } else if ( provider . id === 'bedrock' ) {
659+ if ( ! ( form . aws_access_key_id || '' ) . trim ( ) ) {
660+ setError ( 'AWS Access Key ID is required' ) ;
661+ setStatus ( '' ) ;
662+ return ;
663+ }
664+ if ( ! apiKey ) {
665+ setError ( 'AWS Secret Access Key is required' ) ;
666+ setStatus ( '' ) ;
667+ return ;
668+ }
669+ if ( ! ( form . aws_region || '' ) . trim ( ) ) {
670+ setError ( 'Region is required' ) ;
671+ setStatus ( '' ) ;
672+ return ;
673+ }
585674 if ( ! selectedModel ) {
586675 setError ( 'Please select a model' ) ;
587676 setStatus ( '' ) ;
@@ -609,6 +698,8 @@ function App() {
609698 model : selectedModel || apiDefaultModel || undefined ,
610699 gcp_project_id : ( form . gcp_project_id || '' ) . trim ( ) || undefined ,
611700 gcp_location : ( form . gcp_location || '' ) . trim ( ) || undefined ,
701+ aws_access_key_id : ( form . aws_access_key_id || '' ) . trim ( ) || undefined ,
702+ aws_region : ( form . aws_region || '' ) . trim ( ) || undefined ,
612703 } ) ,
613704 } ) ;
614705
@@ -627,6 +718,8 @@ function App() {
627718 selected_model : selectedModel || apiDefaultModel || undefined ,
628719 gcp_project_id : ( form . gcp_project_id || '' ) . trim ( ) || undefined ,
629720 gcp_location : ( form . gcp_location || '' ) . trim ( ) || undefined ,
721+ aws_access_key_id : ( form . aws_access_key_id || '' ) . trim ( ) || undefined ,
722+ aws_region : ( form . aws_region || '' ) . trim ( ) || undefined ,
630723 display_order : 0 ,
631724 role : form . role || 'leader' ,
632725 } ;
@@ -759,6 +852,12 @@ function App() {
759852 return ! apiKey || ! gcpProjectID || ! gcpLocation ;
760853 }
761854
855+ if ( provider . id === 'bedrock' ) {
856+ const awsAccessKeyID = ( form . aws_access_key_id || '' ) . trim ( ) ;
857+ const awsRegion = ( form . aws_region || '' ) . trim ( ) ;
858+ return ! apiKey || ! awsAccessKeyID || ! awsRegion || ! selectedModel ;
859+ }
860+
762861 if ( ! apiKey ) {
763862 return true ;
764863 }
@@ -838,6 +937,7 @@ function App() {
838937 onProviderChange=${ setProvider }
839938 onFieldChange=${ setFormField }
840939 onFetchOllamaModels=${ fetchOllamaModels }
940+ onFetchBedrockModels=${ fetchBedrockModels }
841941 onSave=${ saveConnector }
842942 onGenerateName=${ generateConnectorName }
843943 onCancel=${ ( ) => {
0 commit comments