From 8d8bc8edcb3f4817a8d8091ff29df4a954472ec9 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 4 Aug 2026 12:39:16 +0000 Subject: [PATCH] fix(providers): hide models until credentials exist For OAuth-only providers like Cursor, open the auth panel when credentials are missing and omit the models list until auth/env credentials are present so placeholder catalog entries are not shown before login. Co-authored-by: Serhii Dziupin --- .../sections/providers/ProvidersPage.tsx | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/packages/ui/src/components/sections/providers/ProvidersPage.tsx b/packages/ui/src/components/sections/providers/ProvidersPage.tsx index 222b3577..008b04e2 100644 --- a/packages/ui/src/components/sections/providers/ProvidersPage.tsx +++ b/packages/ui/src/components/sections/providers/ProvidersPage.tsx @@ -179,10 +179,10 @@ export const ProvidersPage: React.FC = () => { }, [providers, selectedProviderId, setSelectedProvider]); React.useEffect(() => { - // Auth methods drive which credential UI to show (API key vs OAuth). Load - // them for add-provider and reconnect so OAuth-only providers never fall + // Auth methods drive which credential UI to show (API key vs OAuth). Keep + // them loaded for the active provider view so OAuth-only plugins never fall // back to an API key form merely because methods were never fetched. - if (!isAddMode && !showAuthPanel) { + if (!selectedProviderId) { return; } @@ -213,7 +213,7 @@ export const ProvidersPage: React.FC = () => { return () => { isMounted = false; }; - }, [isAddMode, showAuthPanel, t]); + }, [selectedProviderId, t]); React.useEffect(() => { if (!shouldLoadAvailableProviders(isAddMode)) { @@ -300,6 +300,26 @@ export const ProvidersPage: React.FC = () => { } }, [selectedProviderId, editingCustomProviderId]); + // Unauthenticated providers (OAuth-only plugins before login) should open the + // auth panel instead of a false "Connected" summary. + React.useEffect(() => { + if (!selectedProviderId || selectedProviderId === ADD_PROVIDER_ID) { + return; + } + const sources = providerSources[selectedProviderId]; + if (!sources) { + return; + } + const provider = providers.find((entry) => entry.id === selectedProviderId); + const envEntries = Array.isArray(provider?.env) + ? provider.env.filter((entry): entry is string => typeof entry === 'string' && entry.trim().length > 0) + : []; + const hasCreds = Boolean(sources.auth.exists) || envEntries.length > 0; + if (!hasCreds) { + setShowAuthPanel(true); + } + }, [selectedProviderId, providerSources, providers]); + React.useEffect(() => { if (!selectedProviderId || selectedProviderId === ADD_PROVIDER_ID) { return; @@ -910,7 +930,11 @@ export const ProvidersPage: React.FC = () => { const hasStoredAuth = Boolean(selectedSources?.auth.exists); const hasEnvCredentials = providerEnv.length > 0; const hasCredentials = hasStoredAuth || hasEnvCredentials; - const authStatusIncomplete = isEditableCustomProvider && !hasCredentials; + const authStatusIncomplete = sourcesLoaded && !hasCredentials; + const showModelsSection = providerModels.length > 0 && (!sourcesLoaded || hasCredentials); + const incompleteAuthHint = !showApiKeyAuth && oauthAuthMethods.length > 0 + ? t('settings.providers.page.auth.useReconnectHint') + : t('settings.providers.page.auth.incompleteHint'); const filteredModels = providerModels.filter((model) => { const name = typeof model?.name === 'string' ? model.name : ''; @@ -993,7 +1017,7 @@ export const ProvidersPage: React.FC = () => {
{t('settings.providers.page.auth.incomplete')} - {t('settings.providers.page.auth.incompleteHint')} + {incompleteAuthHint}
) : (
@@ -1156,7 +1180,7 @@ export const ProvidersPage: React.FC = () => {
- {providerModels.length > 0 ? ( + {showModelsSection ? (