fix(walkthrough): keep unauthenticated models out of the picker

Treat an empty allowedProviderIds list as allow-none, disable Generate
when no usable model is selected, and mute the button styling so it
reads as unavailable rather than actionable.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-08-04 12:35:25 +00:00
co-authored by Serhii Dziupin
parent 35f17e9e96
commit 5c6eee331e
3 changed files with 17 additions and 8 deletions
@@ -436,7 +436,10 @@ export const ModelPickerList: React.FC<ModelPickerListProps> = ({
);
const allowedProviderSet = React.useMemo(() => {
if (!allowedProviderIds || allowedProviderIds.length === 0) return null;
// undefined = no restriction; [] = allow none. Treating empty like
// "unrestricted" would resurface providers without a login in pickers that
// intentionally pass the authenticated-only list.
if (!allowedProviderIds) return null;
return new Set(allowedProviderIds);
}, [allowedProviderIds]);
@@ -150,7 +150,7 @@ export const WalkthroughBlocker = ({
onChange={(providerId, modelId) => {
void handleModelChange(providerId, modelId);
}}
allowedProviderIds={providers}
allowedProviderIds={providers ?? []}
isModelAllowed={isStructuredOutputCapable}
/>
</div>
@@ -331,7 +331,9 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
const providerIsAuthenticated = (providerId: string | undefined) => {
if (!providerId) return false;
if (modelProviders === undefined) return true;
// Until the auth list loads, do not present a candidate as selected —
// otherwise an unauthenticated config model flashes in the picker.
if (modelProviders === undefined) return false;
return modelProviders.includes(providerId);
};
const readinessModelRef = entry.readiness?.model
@@ -442,9 +444,9 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
const blockedRequiredChars = entry.error?.requiredChars ?? entry.readiness?.requiredChars;
const blockedAvailableChars = entry.error?.availableChars ?? entry.readiness?.availableChars;
// Not ready means Generate must not look actionable — including when the
// resolved model has no login (reason no-provider-login).
const generateDisabled = Boolean(entry.readiness && !entry.readiness.ready);
// Not ready, or no usable selected model, means Generate must not look
// actionable — including when the resolved model has no login.
const generateDisabled = !activeModel || Boolean(entry.readiness && !entry.readiness.ready);
const handleGenerate = useCallback(
(force: boolean) => {
@@ -571,7 +573,8 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
onChange={(providerId, modelId) => {
selectModel(directory, source, providerId && modelId ? `${providerId}/${modelId}` : null);
}}
allowedProviderIds={modelProviders}
// While the auth list is loading, allow none — not every provider.
allowedProviderIds={modelProviders ?? []}
isModelAllowed={isStructuredOutputCapable}
tooltipsEnabled={false}
dropdownPortalToBody
@@ -619,7 +622,10 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
type="button"
variant="outline"
size="sm"
className={WALKTHROUGH_ACTION_CLASS}
className={cn(
WALKTHROUGH_ACTION_CLASS,
generateDisabled && 'border-border bg-transparent text-muted-foreground hover:bg-transparent hover:text-muted-foreground',
)}
disabled={generateDisabled}
aria-label={compactHeader
? (view ? t('walkthrough.action.regenerate') : t('walkthrough.action.generate'))