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> | |
); | |
}; | |