Spaces:
Sleeping
Sleeping
| 'use client' | |
| import { useState } from 'react' | |
| import { useForm } from 'react-hook-form' | |
| import { CreateModelRequest, ProviderAvailability } from '@/lib/types/models' | |
| import { Button } from '@/components/ui/button' | |
| import { Input } from '@/components/ui/input' | |
| import { Label } from '@/components/ui/label' | |
| import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' | |
| import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog' | |
| import { useCreateModel } from '@/lib/hooks/use-models' | |
| import { Plus } from 'lucide-react' | |
| interface AddModelFormProps { | |
| modelType: 'language' | 'embedding' | 'text_to_speech' | 'speech_to_text' | |
| providers: ProviderAvailability | |
| } | |
| export function AddModelForm({ modelType, providers }: AddModelFormProps) { | |
| const [open, setOpen] = useState(false) | |
| const createModel = useCreateModel() | |
| const { register, handleSubmit, formState: { errors }, reset, setValue, watch } = useForm<CreateModelRequest>({ | |
| defaultValues: { | |
| type: modelType | |
| } | |
| }) | |
| // Get available providers that support this model type | |
| const availableProviders = providers.available.filter(provider => | |
| providers.supported_types[provider]?.includes(modelType) | |
| ) | |
| const onSubmit = async (data: CreateModelRequest) => { | |
| await createModel.mutateAsync(data) | |
| reset() | |
| setOpen(false) | |
| } | |
| const getModelTypeName = () => { | |
| return modelType.replace(/_/g, ' ') | |
| } | |
| const getModelPlaceholder = () => { | |
| switch (modelType) { | |
| case 'language': | |
| return 'e.g., gpt-5-mini, claude, gemini' | |
| case 'embedding': | |
| return 'e.g., text-embedding-3-small' | |
| case 'text_to_speech': | |
| return 'e.g., tts-gpt-4o-mini-tts, tts-1-hd' | |
| case 'speech_to_text': | |
| return 'e.g., whisper-1' | |
| default: | |
| return 'Enter model name' | |
| } | |
| } | |
| if (availableProviders.length === 0) { | |
| return ( | |
| <div className="text-sm text-muted-foreground"> | |
| No providers available for {getModelTypeName()} models | |
| </div> | |
| ) | |
| } | |
| const handleOpenChange = (isOpen: boolean) => { | |
| setOpen(isOpen) | |
| if (!isOpen) { | |
| reset() | |
| } | |
| } | |
| return ( | |
| <Dialog open={open} onOpenChange={handleOpenChange}> | |
| <DialogTrigger asChild> | |
| <Button size="sm"> | |
| <Plus className="h-4 w-4 mr-2" /> | |
| Add Model | |
| </Button> | |
| </DialogTrigger> | |
| <DialogContent> | |
| <DialogHeader> | |
| <DialogTitle>Add {getModelTypeName()} Model</DialogTitle> | |
| <DialogDescription> | |
| Configure a new {getModelTypeName()} model from available providers. | |
| </DialogDescription> | |
| </DialogHeader> | |
| <form onSubmit={handleSubmit(onSubmit)} className="space-y-4"> | |
| <div> | |
| <Label htmlFor="provider">Provider</Label> | |
| <Select onValueChange={(value) => setValue('provider', value)} required> | |
| <SelectTrigger> | |
| <SelectValue placeholder="Select a provider" /> | |
| </SelectTrigger> | |
| <SelectContent> | |
| {availableProviders.map((provider) => ( | |
| <SelectItem key={provider} value={provider}> | |
| <span className="capitalize">{provider}</span> | |
| </SelectItem> | |
| ))} | |
| </SelectContent> | |
| </Select> | |
| {errors.provider && ( | |
| <p className="text-sm text-destructive mt-1">Provider is required</p> | |
| )} | |
| </div> | |
| <div> | |
| <Label htmlFor="name">Model Name</Label> | |
| <Input | |
| id="name" | |
| {...register('name', { required: 'Model name is required' })} | |
| placeholder={getModelPlaceholder()} | |
| /> | |
| {errors.name && ( | |
| <p className="text-sm text-destructive mt-1">{errors.name.message}</p> | |
| )} | |
| <p className="text-xs text-muted-foreground mt-1"> | |
| {modelType === 'language' && watch('provider') === 'azure' && | |
| 'For Azure, use the deployment name as the model name'} | |
| </p> | |
| </div> | |
| <div className="flex justify-end gap-2"> | |
| <Button type="button" variant="outline" onClick={() => setOpen(false)}> | |
| Cancel | |
| </Button> | |
| <Button type="submit" disabled={createModel.isPending}> | |
| {createModel.isPending ? 'Adding...' : 'Add Model'} | |
| </Button> | |
| </div> | |
| </form> | |
| </DialogContent> | |
| </Dialog> | |
| ) | |
| } |