@@ -71,6 +71,10 @@ export default function AgentSettings() {
7171 // Provider settings state
7272 const [ settings , setSettings ] = useState < Record < string , string > > ( { } ) ;
7373 const [ error , setError ] = useState < ErrorState > ( null ) ;
74+
75+ // Edit provider state
76+ const [ editingProvider , setEditingProvider ] = useState < string | null > ( null ) ;
77+ const [ isEditDialogOpen , setIsEditDialogOpen ] = useState ( false ) ;
7478
7579 // Wallet state
7680 const [ walletData , setWalletData ] = useState < WalletKeys | null > ( null ) ;
@@ -91,6 +95,9 @@ export default function AgentSettings() {
9195 } ;
9296 }
9397
98+ console . log ( 'Agent settings:' , agentData . agent . settings ) ;
99+ console . log ( 'All providers:' , providerData . map ( p => ( { name : p . name , settings : p . settings ?. map ( s => s . name ) } ) ) ) ;
100+
94101 const connected = providerData . filter ( ( provider ) => {
95102 // Skip providers without settings
96103 if ( ! provider . settings ?. length ) return false ;
@@ -103,16 +110,29 @@ export default function AgentSettings() {
103110 return isSensitive && agentData . agent ?. settings . some ( ( s ) => s . name === setting . name ) ;
104111 } ) ;
105112
113+ console . log ( `Provider ${ provider . name } :` , {
114+ hasSettings : ! ! provider . settings ?. length ,
115+ relevantSettings : relevantSettings . map ( s => s . name ) ,
116+ relevantCount : relevantSettings . length
117+ } ) ;
118+
106119 // If no relevant settings found, provider is not connected
107120 if ( relevantSettings . length === 0 ) return false ;
108121
109122 // Check if ALL relevant settings are HIDDEN
110- return relevantSettings . every ( ( setting ) => {
123+ const isConnected = relevantSettings . every ( ( setting ) => {
111124 const agentSetting = agentData . agent ?. settings . find ( ( s ) => s . name === setting . name ) ;
112- return agentSetting && agentSetting . value === 'HIDDEN' ;
125+ const isHidden = agentSetting && agentSetting . value === 'HIDDEN' ;
126+ console . log ( ` Setting ${ setting . name } : agent value = "${ agentSetting ?. value } ", is hidden = ${ isHidden } ` ) ;
127+ return isHidden ;
113128 } ) ;
129+
130+ console . log ( `Provider ${ provider . name } is connected:` , isConnected ) ;
131+ return isConnected ;
114132 } ) ;
115133
134+ console . log ( 'Connected providers:' , connected . map ( p => p . name ) ) ;
135+
116136 return {
117137 connected,
118138 available : providerData . filter ( ( provider ) => ! connected . includes ( provider ) ) ,
@@ -133,11 +153,20 @@ export default function AgentSettings() {
133153 const handleSaveSettings = async ( extensionName : string , settings : Record < string , string > ) => {
134154 try {
135155 setError ( null ) ;
156+
157+ // Filter out HIDDEN and empty values
158+ const filteredSettings = Object . entries ( settings ) . reduce ( ( acc , [ key , value ] ) => {
159+ if ( value && value !== 'HIDDEN' && value . trim ( ) !== '' ) {
160+ acc [ key ] = value ;
161+ }
162+ return acc ;
163+ } , { } as Record < string , string > ) ;
164+
136165 const response = await axios . put < { status : number ; data : any } > (
137166 `${ process . env . NEXT_PUBLIC_AGIXT_SERVER } /api/agent/${ agent_name } ` ,
138167 {
139168 agent_name : agent_name ,
140- settings : settings ,
169+ settings : filteredSettings ,
141170 } as ExtensionSettings ,
142171 {
143172 headers : {
@@ -150,34 +179,68 @@ export default function AgentSettings() {
150179 if ( response . status === 200 ) {
151180 setError ( {
152181 type : 'success' ,
153- message : 'Extension connected successfully!' ,
182+ message : 'Extension updated successfully!' ,
183+ } ) ;
184+ setEditingProvider ( null ) ;
185+ setIsEditDialogOpen ( false ) ;
186+
187+ // Show toast notification for success
188+ const isEditing = editingProvider !== null ;
189+ toast ( {
190+ title : 'Success' ,
191+ description : `${ extensionName } ${ isEditing ? 'updated' : 'connected' } successfully!` ,
154192 } ) ;
155- window . location . reload ( ) ;
193+
194+ // Just refresh the data, don't reload the whole page
195+ mutateAgent ( ) ;
156196 }
157197 } catch ( error : any ) {
158198 setError ( {
159199 type : 'error' ,
160- message : error . response ?. data ?. detail || error . message || 'Failed to connect extension' ,
200+ message : error . response ?. data ?. detail || error . message || 'Failed to update extension' ,
161201 } ) ;
162202 }
163203 mutateAgent ( ) ;
164204 } ;
165205
166206 // Handler for disconnecting provider
167207 const handleDisconnect = async ( name : string ) => {
168- const extension = providerData ?. find ( ( ext ) => ext . name === name ) ;
169- if ( ! extension ) return ;
170-
171- const emptySettings = extension . settings
172- . filter ( ( setting ) => {
173- return [ 'API_KEY' , 'SECRET' , 'PASSWORD' , 'TOKEN' ] . some ( ( keyword ) =>
174- setting . name . replaceAll ( 'TOKENS' , '' ) . includes ( keyword ) ,
175- ) ;
176- } )
177- . reduce ( ( acc , setting ) => {
178- return { ...acc , [ setting . name ] : '' } ;
179- } , { } ) ;
180- await handleSaveSettings ( extension . name , emptySettings ) ;
208+ try {
209+ setError ( null ) ;
210+
211+ console . log ( 'Disconnecting provider:' , name ) ;
212+ console . log ( 'Using agent name:' , agent_name ) ;
213+ console . log ( 'Full URL:' , `${ process . env . NEXT_PUBLIC_AGIXT_SERVER } /v1/agent/${ agent_name } /provider/${ name } ` ) ;
214+
215+ const response = await axios . delete (
216+ `${ process . env . NEXT_PUBLIC_AGIXT_SERVER } /v1/agent/${ agent_name } /provider/${ name } ` ,
217+ {
218+ headers : {
219+ 'Content-Type' : 'application/json' ,
220+ Authorization : getCookie ( 'jwt' ) ,
221+ } ,
222+ } ,
223+ ) ;
224+
225+ console . log ( 'Disconnect response:' , response ) ;
226+
227+ if ( response . status === 200 ) {
228+ toast ( {
229+ title : 'Success' ,
230+ description : `${ name } disconnected successfully!` ,
231+ } ) ;
232+ // Just refresh the data, don't reload the whole page
233+ mutateAgent ( ) ;
234+ }
235+ } catch ( error : any ) {
236+ console . error ( 'Failed to disconnect provider:' , error ) ;
237+ console . error ( 'Error response:' , error . response ) ;
238+ toast ( {
239+ title : 'Error' ,
240+ description : error . response ?. data ?. detail || error . response ?. data ?. message || 'Failed to disconnect provider. Please try again.' ,
241+ variant : 'destructive' ,
242+ } ) ;
243+ }
181244 } ;
182245
183246 // Agent creation handler
@@ -612,15 +675,85 @@ export default function AgentSettings() {
612675 < p className = 'text-sm text-muted-foreground' > Connected</ p >
613676 </ div >
614677 </ div >
615- < Button
616- variant = 'outline'
617- size = { isMobile ? 'sm' : 'default' }
618- className = { cn ( 'gap-2' , isMobile ? 'px-2' : '' ) }
619- onClick = { ( ) => handleDisconnect ( provider . name ) }
620- >
621- < Unlink className = 'w-4 h-4' />
622- { ! isMobile && 'Disconnect' }
623- </ Button >
678+ < div className = 'flex gap-2' >
679+ < Dialog open = { isEditDialogOpen && editingProvider === provider . name } onOpenChange = { setIsEditDialogOpen } >
680+ < DialogTrigger asChild >
681+ < Button
682+ variant = 'outline'
683+ size = { isMobile ? 'sm' : 'default' }
684+ className = { cn ( 'gap-2' , isMobile ? 'px-2' : '' ) }
685+ onClick = { ( ) => {
686+ setEditingProvider ( provider . name ) ;
687+ setIsEditDialogOpen ( true ) ;
688+ // Initialize settings with current agent settings values, showing HIDDEN for protected values
689+ const currentSettings = provider . settings . reduce ( ( acc : Record < string , string > , setting ) => {
690+ const agentSetting = agentData ?. agent ?. settings . find ( ( s ) => s . name === setting . name ) ;
691+ acc [ setting . name ] = agentSetting ?. value || setting . value as string ;
692+ return acc ;
693+ } , { } ) ;
694+ setSettings ( currentSettings ) ;
695+ } }
696+ >
697+ < LuPencil className = 'w-4 h-4' />
698+ { ! isMobile && 'Edit' }
699+ </ Button >
700+ </ DialogTrigger >
701+ < DialogContent className = { cn ( 'sm:max-w-[425px]' , isMobile ? 'w-[90%] p-4' : '' ) } >
702+ < DialogHeader >
703+ < DialogTitle > Edit { provider . name } </ DialogTitle >
704+ < DialogDescription >
705+ Update the credentials for this service. Leave fields as "HIDDEN" to keep existing values, or clear them to remove the setting.
706+ </ DialogDescription >
707+ </ DialogHeader >
708+
709+ < div className = 'grid gap-4 py-4' >
710+ { provider . settings . map ( ( prov ) => (
711+ < div key = { prov . name } className = 'grid gap-2' >
712+ < Label htmlFor = { `edit-${ prov . name } ` } > { prov . name } </ Label >
713+ < Input
714+ id = { `edit-${ prov . name } ` }
715+ type = {
716+ prov . name . toLowerCase ( ) . includes ( 'key' ) || prov . name . toLowerCase ( ) . includes ( 'password' )
717+ ? 'password'
718+ : 'text'
719+ }
720+ value = { settings [ prov . name ] || '' }
721+ onChange = { ( e ) =>
722+ setSettings ( ( prev ) => ( {
723+ ...prev ,
724+ [ prov . name ] : e . target . value ,
725+ } ) )
726+ }
727+ placeholder = { settings [ prov . name ] === 'HIDDEN' ? 'Leave as HIDDEN to keep current value' : `Enter ${ prov . name . toLowerCase ( ) } ` }
728+ />
729+ </ div >
730+ ) ) }
731+ </ div >
732+
733+ < DialogFooter >
734+ < DialogClose asChild >
735+ < Button variant = 'outline' onClick = { ( ) => setIsEditDialogOpen ( false ) } > Cancel</ Button >
736+ </ DialogClose >
737+ < Button onClick = { ( ) => handleSaveSettings ( provider . name , settings ) } > Update Provider</ Button >
738+ </ DialogFooter >
739+
740+ { error && editingProvider === provider . name && (
741+ < Alert variant = { error . type === 'success' ? 'default' : 'destructive' } >
742+ < AlertDescription > { error . message } </ AlertDescription >
743+ </ Alert >
744+ ) }
745+ </ DialogContent >
746+ </ Dialog >
747+ < Button
748+ variant = 'outline'
749+ size = { isMobile ? 'sm' : 'default' }
750+ className = { cn ( 'gap-2' , isMobile ? 'px-2' : '' ) }
751+ onClick = { ( ) => handleDisconnect ( provider . name ) }
752+ >
753+ < Unlink className = 'w-4 h-4' />
754+ { ! isMobile && 'Disconnect' }
755+ </ Button >
756+ </ div >
624757 </ div >
625758 < div className = 'text-sm text-muted-foreground' >
626759 < MarkdownBlock content = { provider . description } />
@@ -696,10 +829,13 @@ export default function AgentSettings() {
696829 </ div >
697830
698831 < DialogFooter >
832+ < DialogClose asChild >
833+ < Button variant = 'outline' > Cancel</ Button >
834+ </ DialogClose >
699835 < Button onClick = { ( ) => handleSaveSettings ( provider . name , settings ) } > Connect Provider</ Button >
700836 </ DialogFooter >
701837
702- { error && (
838+ { error && ! editingProvider && (
703839 < Alert variant = { error . type === 'success' ? 'default' : 'destructive' } >
704840 < AlertDescription > { error . message } </ AlertDescription >
705841 </ Alert >
0 commit comments