diff --git a/ui/src/components/setup/wizard/steps/variant-step.tsx b/ui/src/components/setup/wizard/steps/variant-step.tsx index 7eafe601..97e99166 100644 --- a/ui/src/components/setup/wizard/steps/variant-step.tsx +++ b/ui/src/components/setup/wizard/steps/variant-step.tsx @@ -2,6 +2,7 @@ * Variant Creation Step */ +import { useState } from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; @@ -18,6 +19,8 @@ import { PRIVACY_BLUR_CLASS } from '@/contexts/privacy-context'; import { MODEL_CATALOGS } from '@/lib/model-catalogs'; import type { VariantStepProps } from '../types'; +const CUSTOM_MODEL_VALUE = '__custom__'; + export function VariantStep({ selectedProvider, selectedAccount, @@ -31,6 +34,21 @@ export function VariantStep({ onSkip, onCreate, }: VariantStepProps) { + // Track if user selected custom model option + const catalogModels = MODEL_CATALOGS[selectedProvider]?.models || []; + const isCustomModel = modelName && !catalogModels.some((m) => m.id === modelName); + const [showCustomInput, setShowCustomInput] = useState(isCustomModel); + + const handleModelSelect = (value: string) => { + if (value === CUSTOM_MODEL_VALUE) { + setShowCustomInput(true); + onModelChange(''); // Clear to let user type custom + } else { + setShowCustomInput(false); + onModelChange(value); + } + }; + return (
{selectedAccount && ( @@ -60,25 +78,50 @@ export function VariantStep({
- onModelChange(e.target.value)} + placeholder="e.g., gemini-2.5-pro, claude-opus-4-5" + /> + +
+ ) : ( + + + + )}
- Default: {MODEL_CATALOGS[selectedProvider]?.defaultModel || 'provider default'} + {showCustomInput + ? 'Enter any model name supported by CLIProxy' + : `Default: ${MODEL_CATALOGS[selectedProvider]?.defaultModel || 'provider default'}`}