"use client" import * as React from "react" import { useState, useEffect } from "react"; import { PopoverProps } from "@radix-ui/react-popover" import { Check, CaretUpDown } from "@phosphor-icons/react"; import { cn } from "@/lib/utils" import { useIsMobileWidth, useMutationObserver } from "@/app/common/utils"; import { Button } from "@/components/ui/button"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { ModelOptions, useUserConfig } from "./auth"; import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card"; import { Skeleton } from "@/components/ui/skeleton"; interface ModelSelectorProps extends PopoverProps { onSelect: (model: ModelOptions) => void; disabled?: boolean; initialModel?: string; } export function ModelSelector({ ...props }: ModelSelectorProps) { const [open, setOpen] = React.useState(false) const [peekedModel, setPeekedModel] = useState(undefined); const [selectedModel, setSelectedModel] = useState(undefined); const { data: userConfig, error, isLoading: isLoadingUserConfig } = useUserConfig(true); const [models, setModels] = useState([]); const isMobileWidth = useIsMobileWidth(); useEffect(() => { if (isLoadingUserConfig) return; if (userConfig) { setModels(userConfig.chat_model_options); if (!props.initialModel) { const selectedChatModelOption = userConfig.chat_model_options.find(model => model.id === userConfig.selected_chat_model_config); if (!selectedChatModelOption && userConfig.chat_model_options.length > 0) { setSelectedModel(userConfig.chat_model_options[0]); } else { setSelectedModel(selectedChatModelOption); } } else { const model = userConfig.chat_model_options.find(model => model.name === props.initialModel); setSelectedModel(model); } } }, [userConfig, props.initialModel, isLoadingUserConfig]); useEffect(() => { if (selectedModel && userConfig) { props.onSelect(selectedModel); } }, [selectedModel, userConfig, props.onSelect]); if (isLoadingUserConfig) { return ( ); } if (error) { return (
{error.message}
); } return (
{ isMobileWidth ?
No Models found. {models && models.length > 0 && models .map((model) => ( setPeekedModel(model)} onSelect={() => { setSelectedModel(model) setOpen(false) }} /> ))}
:

{peekedModel?.name}

{peekedModel?.description}
{peekedModel?.strengths ? (
Strengths

{peekedModel.strengths}

) : null}
No Models found. {models && models.length > 0 && models .map((model) => ( setPeekedModel(model)} onSelect={() => { setSelectedModel(model) setOpen(false) }} /> ))}
}
) } interface ModelItemProps { model: ModelOptions, isSelected: boolean, onSelect: () => void, onPeek: (model: ModelOptions) => void } function ModelItem({ model, isSelected, onSelect, onPeek }: ModelItemProps) { const ref = React.useRef(null) useMutationObserver(ref, (mutations) => { mutations.forEach((mutation) => { if ( mutation.type === "attributes" && mutation.attributeName === "aria-selected" && ref.current?.getAttribute("aria-selected") === "true" ) { onPeek(model) } }) }) return ( {model.name} ) }