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(() => { 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); return new Set(allowedProviderIds);
}, [allowedProviderIds]); }, [allowedProviderIds]);
@@ -150,7 +150,7 @@ export const WalkthroughBlocker = ({
onChange={(providerId, modelId) => { onChange={(providerId, modelId) => {
void handleModelChange(providerId, modelId); void handleModelChange(providerId, modelId);
}} }}
allowedProviderIds={providers} allowedProviderIds={providers ?? []}
isModelAllowed={isStructuredOutputCapable} isModelAllowed={isStructuredOutputCapable}
/> />
</div> </div>
@@ -331,7 +331,9 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
const providerIsAuthenticated = (providerId: string | undefined) => { const providerIsAuthenticated = (providerId: string | undefined) => {
if (!providerId) return false; 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); return modelProviders.includes(providerId);
}; };
const readinessModelRef = entry.readiness?.model const readinessModelRef = entry.readiness?.model
@@ -442,9 +444,9 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
const blockedRequiredChars = entry.error?.requiredChars ?? entry.readiness?.requiredChars; const blockedRequiredChars = entry.error?.requiredChars ?? entry.readiness?.requiredChars;
const blockedAvailableChars = entry.error?.availableChars ?? entry.readiness?.availableChars; const blockedAvailableChars = entry.error?.availableChars ?? entry.readiness?.availableChars;
// Not ready means Generate must not look actionable — including when the // Not ready, or no usable selected model, means Generate must not look
// resolved model has no login (reason no-provider-login). // actionable — including when the resolved model has no login.
const generateDisabled = Boolean(entry.readiness && !entry.readiness.ready); const generateDisabled = !activeModel || Boolean(entry.readiness && !entry.readiness.ready);
const handleGenerate = useCallback( const handleGenerate = useCallback(
(force: boolean) => { (force: boolean) => {
@@ -571,7 +573,8 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
onChange={(providerId, modelId) => { onChange={(providerId, modelId) => {
selectModel(directory, source, providerId && modelId ? `${providerId}/${modelId}` : null); 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} isModelAllowed={isStructuredOutputCapable}
tooltipsEnabled={false} tooltipsEnabled={false}
dropdownPortalToBody dropdownPortalToBody
@@ -619,7 +622,10 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
type="button" type="button"
variant="outline" variant="outline"
size="sm" 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} disabled={generateDisabled}
aria-label={compactHeader aria-label={compactHeader
? (view ? t('walkthrough.action.regenerate') : t('walkthrough.action.generate')) ? (view ? t('walkthrough.action.regenerate') : t('walkthrough.action.generate'))