Spaces:
Running
Running
| "use client"; | |
| import { getModels, getDefaultModel, ModelID } from "@/lib/models"; | |
| import { | |
| Select, | |
| SelectContent, | |
| SelectGroup, | |
| SelectItem, | |
| SelectTrigger, | |
| SelectValue, | |
| } from "./ui/select"; | |
| import { cn } from "@/lib/utils"; | |
| import { Bot } from "lucide-react"; | |
| import { useEffect, useState } from "react"; | |
| interface ModelPickerProps { | |
| selectedModel: ModelID; | |
| setSelectedModel: (model: ModelID) => void; | |
| } | |
| export const ModelPicker = ({ selectedModel, setSelectedModel }: ModelPickerProps) => { | |
| const [models, setModels] = useState<ModelID[]>([]); | |
| const [validModelId, setValidModelId] = useState<ModelID>(""); | |
| useEffect(() => { | |
| const fetchModels = async () => { | |
| const availableModels = await getModels(); | |
| setModels(availableModels); | |
| const defaultModel = await getDefaultModel(); | |
| const currentModel = selectedModel || defaultModel; | |
| const isValid = availableModels.includes(currentModel); | |
| const newValidModelId = isValid ? currentModel : defaultModel; | |
| setValidModelId(newValidModelId); | |
| if (selectedModel !== newValidModelId) { | |
| setSelectedModel(newValidModelId); | |
| } | |
| }; | |
| fetchModels(); | |
| }, [selectedModel, setSelectedModel]); | |
| // Handle model change | |
| const handleModelChange = (modelId: string) => { | |
| if (models.includes(modelId as ModelID)) { | |
| setSelectedModel(modelId as ModelID); | |
| } | |
| }; | |
| return ( | |
| <div className="absolute bottom-2 left-2 z-10"> | |
| <Select | |
| value={validModelId} | |
| onValueChange={handleModelChange} | |
| defaultValue={validModelId} | |
| > | |
| <SelectTrigger | |
| className="max-w-[200px] sm:max-w-fit sm:w-80 px-2 sm:px-3 h-8 sm:h-9 rounded-full group border-primary/20 bg-primary/5 hover:bg-primary/10 dark:bg-primary/10 dark:hover:bg-primary/20 transition-all duration-200 ring-offset-background focus:ring-2 focus:ring-primary/30 focus:ring-offset-2" | |
| > | |
| <SelectValue | |
| placeholder="Select model" | |
| className="text-xs font-medium flex items-center gap-1 sm:gap-2 text-primary dark:text-primary-foreground" | |
| > | |
| <div className="flex items-center gap-1 sm:gap-2"> | |
| <Bot className="h-3 w-3" /> | |
| <span className="font-medium truncate">{validModelId}</span> | |
| </div> | |
| </SelectValue> | |
| </SelectTrigger> | |
| <SelectContent | |
| align="start" | |
| className="bg-background/95 dark:bg-muted/95 backdrop-blur-sm border-border/80 rounded-lg overflow-hidden p-0 w-[280px]" | |
| > | |
| <SelectGroup className="space-y-1 p-1"> | |
| {models.map((id) => ( | |
| <SelectItem | |
| key={id} | |
| value={id} | |
| className={cn( | |
| "!px-2 sm:!px-3 py-1.5 sm:py-2 cursor-pointer rounded-md text-xs transition-colors duration-150", | |
| "hover:bg-primary/5 hover:text-primary-foreground", | |
| "focus:bg-primary/10 focus:text-primary focus:outline-none", | |
| "data-[highlighted]:bg-primary/10 data-[highlighted]:text-primary", | |
| validModelId === id && "!bg-primary/15 !text-primary font-medium" | |
| )} | |
| > | |
| <div className="flex items-center gap-1.5"> | |
| <Bot className="h-4 w-4" /> | |
| <span className="font-medium truncate">{id}</span> | |
| </div> | |
| </SelectItem> | |
| ))} | |
| </SelectGroup> | |
| </SelectContent> | |
| </Select> | |
| </div> | |
| ); | |
| }; | |