diff --git a/web-app/src/routes/settings/providers/$providerName.tsx b/web-app/src/routes/settings/providers/$providerName.tsx index 533536281..efba6233c 100644 --- a/web-app/src/routes/settings/providers/$providerName.tsx +++ b/web-app/src/routes/settings/providers/$providerName.tsx @@ -83,6 +83,7 @@ function ProviderDetail() { const [refreshingModels, setRefreshingModels] = useState(false) const [isCheckingBackendUpdate, setIsCheckingBackendUpdate] = useState(false) const [isInstallingBackend, setIsInstallingBackend] = useState(false) + const [importingModel, setImportingModel] = useState(null) const { checkForUpdate: checkForBackendUpdate, installBackend } = useBackendUpdater() const { providerName } = useParams({ from: Route.id }) @@ -102,58 +103,66 @@ function ProviderDetail() { ) const handleModelImportSuccess = async (importedModelName?: string) => { - // Refresh the provider to update the models list - await serviceHub.providers().getProviders().then(setProviders) + if (importedModelName) { + setImportingModel(importedModelName) + } - // If a model was imported and it might have vision capabilities, check and update - if (importedModelName && providerName === 'llamacpp') { - try { - const mmprojExists = await serviceHub - .models() - .checkMmprojExists(importedModelName) - if (mmprojExists) { - // Get the updated provider after refresh - const { getProviderByName, updateProvider: updateProviderState } = - useModelProvider.getState() - const llamacppProvider = getProviderByName('llamacpp') + try { + // Refresh the provider to update the models list + await serviceHub.providers().getProviders().then(setProviders) - if (llamacppProvider) { - const modelIndex = llamacppProvider.models.findIndex( - (m: Model) => m.id === importedModelName - ) - if (modelIndex !== -1) { - const model = llamacppProvider.models[modelIndex] - const capabilities = model.capabilities || [] + // If a model was imported and it might have vision capabilities, check and update + if (importedModelName && providerName === 'llamacpp') { + try { + const mmprojExists = await serviceHub + .models() + .checkMmprojExists(importedModelName) + if (mmprojExists) { + // Get the updated provider after refresh + const { getProviderByName, updateProvider: updateProviderState } = + useModelProvider.getState() + const llamacppProvider = getProviderByName('llamacpp') - // Add 'vision' capability if not already present AND if user hasn't manually configured capabilities - // Check if model has a custom capabilities config flag + if (llamacppProvider) { + const modelIndex = llamacppProvider.models.findIndex( + (m: Model) => m.id === importedModelName + ) + if (modelIndex !== -1) { + const model = llamacppProvider.models[modelIndex] + const capabilities = model.capabilities || [] - const hasUserConfiguredCapabilities = - (model as any)._userConfiguredCapabilities === true + // Add 'vision' capability if not already present AND if user hasn't manually configured capabilities + // Check if model has a custom capabilities config flag - if ( - !capabilities.includes('vision') && - !hasUserConfiguredCapabilities - ) { - const updatedModels = [...llamacppProvider.models] - updatedModels[modelIndex] = { - ...model, - capabilities: [...capabilities, 'vision'], - // Mark this as auto-detected, not user-configured - _autoDetectedVision: true, - } as any + const hasUserConfiguredCapabilities = + (model as any)._userConfiguredCapabilities === true - updateProviderState('llamacpp', { models: updatedModels }) - console.log( - `Vision capability added to model after provider refresh: ${importedModelName}` - ) + if ( + !capabilities.includes('vision') && + !hasUserConfiguredCapabilities + ) { + const updatedModels = [...llamacppProvider.models] + updatedModels[modelIndex] = { + ...model, + capabilities: [...capabilities, 'vision'], + // Mark this as auto-detected, not user-configured + _autoDetectedVision: true, + } as any + + updateProviderState('llamacpp', { models: updatedModels }) + console.log( + `Vision capability added to model after provider refresh: ${importedModelName}` + ) + } } } } + } catch (error) { + console.error('Error checking mmproj existence after import:', error) } - } catch (error) { - console.error('Error checking mmproj existence after import:', error) } + } finally { + // The importing state will be cleared by the useEffect when model appears in list } } @@ -175,6 +184,29 @@ function ProviderDetail() { return () => clearInterval(intervalId) }, [serviceHub, setActiveModels]) + // Clear importing state when model appears in the provider's model list + useEffect(() => { + if (importingModel && provider?.models) { + const modelExists = provider.models.some( + (model) => model.id === importingModel + ) + if (modelExists) { + setImportingModel(null) + } + } + }, [importingModel, provider?.models]) + + // Fallback: Clear importing state after 10 seconds to prevent infinite loading + useEffect(() => { + if (importingModel) { + const timeoutId = setTimeout(() => { + setImportingModel(null) + }, 10000) // 10 seconds fallback + + return () => clearTimeout(timeoutId) + } + }, [importingModel]) + // Auto-refresh provider settings to get updated backend configuration const refreshSettings = useCallback(async () => { if (!provider) return @@ -831,6 +863,28 @@ function ProviderDetail() {

)} + {/* Show importing skeleton first if there's one */} + {importingModel && ( + +
+
+ + Importing... +
+

+ {importingModel} +

+
+ + } + /> + )}