@@ -83,6 +83,7 @@ function ProviderDetail() {
8383 const [ refreshingModels , setRefreshingModels ] = useState ( false )
8484 const [ isCheckingBackendUpdate , setIsCheckingBackendUpdate ] = useState ( false )
8585 const [ isInstallingBackend , setIsInstallingBackend ] = useState ( false )
86+ const [ importingModel , setImportingModel ] = useState < string | null > ( null )
8687 const { checkForUpdate : checkForBackendUpdate , installBackend } =
8788 useBackendUpdater ( )
8889 const { providerName } = useParams ( { from : Route . id } )
@@ -102,58 +103,66 @@ function ProviderDetail() {
102103 )
103104
104105 const handleModelImportSuccess = async ( importedModelName ?: string ) => {
105- // Refresh the provider to update the models list
106- await serviceHub . providers ( ) . getProviders ( ) . then ( setProviders )
106+ if ( importedModelName ) {
107+ setImportingModel ( importedModelName )
108+ }
107109
108- // If a model was imported and it might have vision capabilities, check and update
109- if ( importedModelName && providerName === 'llamacpp' ) {
110- try {
111- const mmprojExists = await serviceHub
112- . models ( )
113- . checkMmprojExists ( importedModelName )
114- if ( mmprojExists ) {
115- // Get the updated provider after refresh
116- const { getProviderByName, updateProvider : updateProviderState } =
117- useModelProvider . getState ( )
118- const llamacppProvider = getProviderByName ( 'llamacpp' )
119-
120- if ( llamacppProvider ) {
121- const modelIndex = llamacppProvider . models . findIndex (
122- ( m : Model ) => m . id === importedModelName
123- )
124- if ( modelIndex !== - 1 ) {
125- const model = llamacppProvider . models [ modelIndex ]
126- const capabilities = model . capabilities || [ ]
127-
128- // Add 'vision' capability if not already present AND if user hasn't manually configured capabilities
129- // Check if model has a custom capabilities config flag
130-
131- const hasUserConfiguredCapabilities =
132- ( model as any ) . _userConfiguredCapabilities === true
133-
134- if (
135- ! capabilities . includes ( 'vision' ) &&
136- ! hasUserConfiguredCapabilities
137- ) {
138- const updatedModels = [ ...llamacppProvider . models ]
139- updatedModels [ modelIndex ] = {
140- ...model ,
141- capabilities : [ ...capabilities , 'vision' ] ,
142- // Mark this as auto-detected, not user-configured
143- _autoDetectedVision : true ,
144- } as any
145-
146- updateProviderState ( 'llamacpp' , { models : updatedModels } )
147- console . log (
148- `Vision capability added to model after provider refresh: ${ importedModelName } `
149- )
110+ try {
111+ // Refresh the provider to update the models list
112+ await serviceHub . providers ( ) . getProviders ( ) . then ( setProviders )
113+
114+ // If a model was imported and it might have vision capabilities, check and update
115+ if ( importedModelName && providerName === 'llamacpp' ) {
116+ try {
117+ const mmprojExists = await serviceHub
118+ . models ( )
119+ . checkMmprojExists ( importedModelName )
120+ if ( mmprojExists ) {
121+ // Get the updated provider after refresh
122+ const { getProviderByName, updateProvider : updateProviderState } =
123+ useModelProvider . getState ( )
124+ const llamacppProvider = getProviderByName ( 'llamacpp' )
125+
126+ if ( llamacppProvider ) {
127+ const modelIndex = llamacppProvider . models . findIndex (
128+ ( m : Model ) => m . id === importedModelName
129+ )
130+ if ( modelIndex !== - 1 ) {
131+ const model = llamacppProvider . models [ modelIndex ]
132+ const capabilities = model . capabilities || [ ]
133+
134+ // Add 'vision' capability if not already present AND if user hasn't manually configured capabilities
135+ // Check if model has a custom capabilities config flag
136+
137+ const hasUserConfiguredCapabilities =
138+ ( model as any ) . _userConfiguredCapabilities === true
139+
140+ if (
141+ ! capabilities . includes ( 'vision' ) &&
142+ ! hasUserConfiguredCapabilities
143+ ) {
144+ const updatedModels = [ ...llamacppProvider . models ]
145+ updatedModels [ modelIndex ] = {
146+ ...model ,
147+ capabilities : [ ...capabilities , 'vision' ] ,
148+ // Mark this as auto-detected, not user-configured
149+ _autoDetectedVision : true ,
150+ } as any
151+
152+ updateProviderState ( 'llamacpp' , { models : updatedModels } )
153+ console . log (
154+ `Vision capability added to model after provider refresh: ${ importedModelName } `
155+ )
156+ }
150157 }
151158 }
152159 }
160+ } catch ( error ) {
161+ console . error ( 'Error checking mmproj existence after import:' , error )
153162 }
154- } catch ( error ) {
155- console . error ( 'Error checking mmproj existence after import:' , error )
156163 }
164+ } finally {
165+ // The importing state will be cleared by the useEffect when model appears in list
157166 }
158167 }
159168
@@ -175,6 +184,29 @@ function ProviderDetail() {
175184 return ( ) => clearInterval ( intervalId )
176185 } , [ serviceHub , setActiveModels ] )
177186
187+ // Clear importing state when model appears in the provider's model list
188+ useEffect ( ( ) => {
189+ if ( importingModel && provider ?. models ) {
190+ const modelExists = provider . models . some (
191+ ( model ) => model . id === importingModel
192+ )
193+ if ( modelExists ) {
194+ setImportingModel ( null )
195+ }
196+ }
197+ } , [ importingModel , provider ?. models ] )
198+
199+ // Fallback: Clear importing state after 10 seconds to prevent infinite loading
200+ useEffect ( ( ) => {
201+ if ( importingModel ) {
202+ const timeoutId = setTimeout ( ( ) => {
203+ setImportingModel ( null )
204+ } , 10000 ) // 10 seconds fallback
205+
206+ return ( ) => clearTimeout ( timeoutId )
207+ }
208+ } , [ importingModel ] )
209+
178210 // Auto-refresh provider settings to get updated backend configuration
179211 const refreshSettings = useCallback ( async ( ) => {
180212 if ( ! provider ) return
@@ -831,6 +863,28 @@ function ProviderDetail() {
831863 </ p >
832864 </ div >
833865 ) }
866+ { /* Show importing skeleton first if there's one */ }
867+ { importingModel && (
868+ < CardItem
869+ key = "importing-skeleton"
870+ title = {
871+ < div className = "flex items-center gap-2" >
872+ < div className = "flex items-center gap-2 animate-pulse" >
873+ < div className = "bg-accent/20 flex gap-2 text-accent px-2 py-1 rounded-full text-xs" >
874+ < IconLoader
875+ size = { 16 }
876+ className = "animate-spin text-accent"
877+ />
878+ Importing...
879+ </ div >
880+ < h1 className = "font-medium line-clamp-1" >
881+ { importingModel }
882+ </ h1 >
883+ </ div >
884+ </ div >
885+ }
886+ />
887+ ) }
834888 </ Card >
835889 </ div >
836890 </ div >
0 commit comments