Fix: Show models from connected BYOK providers, not all cloud models

This commit is contained in:
Sarah Wooders
2026-01-28 21:46:46 -08:00
parent 549e862e9a
commit 89d4b5d082
2 changed files with 41 additions and 17 deletions

View File

@@ -462,7 +462,9 @@ async function stepModel(config: OnboardConfig, env: Record<string, string>): Pr
}
spinner.start('Fetching models...');
const modelOptions = await buildModelOptions({ billingTier, isSelfHosted });
// Pass connected provider IDs so we show models from those providers
const connectedProviders = config.providers?.map(p => p.id) || [];
const modelOptions = await buildModelOptions({ billingTier, isSelfHosted, connectedProviders });
spinner.stop('Models loaded');
// Show appropriate message for free tier

View File

@@ -73,20 +73,32 @@ export function getDefaultModelForTier(billingTier?: string | null): string {
return defaultModel?.handle ?? models[0]?.handle ?? 'anthropic/claude-sonnet-4-5-20250929';
}
// Map provider IDs to model handle prefixes
const PROVIDER_TO_MODEL_PREFIX: Record<string, string[]> = {
'anthropic': ['anthropic/'],
'openai': ['openai/'],
'gemini': ['google_ai/'],
'zai': ['zai/'],
'minimax': ['minimax/'],
'openrouter': ['openrouter/'],
};
/**
* Build model selection options based on billing tier
* Build model selection options based on billing tier and connected providers
* Returns array ready for @clack/prompts select()
*
* For free users: Show free models first, then BYOK option
* For free users: Show free models first, then connected BYOK models
* For paid users: Show featured models first, then all models
* For self-hosted: Fetch models from server
*/
export async function buildModelOptions(options?: {
billingTier?: string | null;
isSelfHosted?: boolean;
connectedProviders?: string[]; // Provider IDs like 'anthropic', 'minimax'
}): Promise<Array<{ value: string; label: string; hint: string }>> {
const billingTier = options?.billingTier;
const isSelfHosted = options?.isSelfHosted;
const connectedProviders = options?.connectedProviders || [];
const isFreeTier = billingTier?.toLowerCase() === 'free';
// For self-hosted servers, fetch models from server
@@ -96,6 +108,14 @@ export async function buildModelOptions(options?: {
const result: Array<{ value: string; label: string; hint: string }> = [];
// Helper to check if a model is from a connected provider
const isFromConnectedProvider = (handle: string) => {
return connectedProviders.some(providerId => {
const prefixes = PROVIDER_TO_MODEL_PREFIX[providerId] || [];
return prefixes.some(prefix => handle.startsWith(prefix));
});
};
if (isFreeTier) {
// Free tier: Show free models first
const freeModels = models.filter(m => m.free);
@@ -105,20 +125,22 @@ export async function buildModelOptions(options?: {
hint: `🆓 Free - ${m.description}`,
})));
// Add BYOK header and options
result.push({
value: '__byok_header__',
label: '── BYOK (Bring Your Own Key) ──',
hint: 'Connect your own API keys',
});
// Show featured non-free models as BYOK options
const byokModels = models.filter(m => m.isFeatured && !m.free);
result.push(...byokModels.map(m => ({
value: m.handle,
label: m.label,
hint: `🔑 BYOK - ${m.description}`,
})));
// If user has connected providers, show their models
if (connectedProviders.length > 0) {
result.push({
value: '__byok_header__',
label: '── Your Connected Providers ──',
hint: 'Models from your API keys',
});
// Show models from connected providers only
const connectedModels = models.filter(m => !m.free && isFromConnectedProvider(m.handle));
result.push(...connectedModels.map(m => ({
value: m.handle,
label: m.label,
hint: `🔑 ${m.description}`,
})));
}
} else {
// Paid tier: Show featured models first
const featured = models.filter(m => m.isFeatured);