import { useState, useCallback, useEffect, useRef } from 'react' import { LlmEngines, LocalEngines, Model, RemoteEngines } from '@janhq/core' import { Badge, Input, ScrollArea, Select, useClickOutside } from '@janhq/joi' import { useAtomValue } from 'jotai' import { ChevronDownIcon, XIcon } from 'lucide-react' import { twMerge } from 'tailwind-merge' import useCortex from '@/hooks/useCortex' import useSelectModel from '@/hooks/useSelectModel' import ModelSection from './ModelSection' import { downloadedModelsAtom, getSelectedModelAtom, } from '@/helpers/atoms/Model.atom' import { activeThreadAtom } from '@/helpers/atoms/Thread.atom' type Props = { chatInputMode?: boolean } const ModelDropdown: React.FC = ({ chatInputMode }) => { const downloadedModels = useAtomValue(downloadedModelsAtom) const [searchFilter, setSearchFilter] = useState('all') const [filterOptionsOpen, setFilterOptionsOpen] = useState(false) const [searchText, setSearchText] = useState('') const { selectModel } = useSelectModel() const [open, setOpen] = useState(false) const activeThread = useAtomValue(activeThreadAtom) const [toggle, setToggle] = useState(null) const selectedModel = useAtomValue(getSelectedModelAtom) const { createModel } = useCortex() const [dropdownOptions, setDropdownOptions] = useState( null ) const searchInputRef = useRef(null) useClickOutside(() => !filterOptionsOpen && setOpen(false), null, [ dropdownOptions, toggle, ]) useEffect(() => { if (open && searchInputRef.current) { searchInputRef.current.focus() } }, [open]) const onModelSelected = useCallback( async (model: Model) => { const isModelAddedToCortex = downloadedModels.find( (m) => m.model === model.model ) if (!isModelAddedToCortex) { await createModel(model) } selectModel(model) setOpen(false) }, [selectModel, createModel, downloadedModels] ) const engines = searchFilter === 'local' ? LocalEngines : searchFilter === 'remote' ? RemoteEngines : LlmEngines if (!activeThread) return null const modelId = selectedModel?.model ?? '' const modelName = selectedModel?.name ?? modelId return (
{chatInputMode ? ( setOpen(!open)} > {modelName} ) : ( } onClick={() => setOpen(!open)} /> )}
setSearchText(e.target.value)} suffixIcon={ searchText.length > 0 && ( setSearchText('')} /> ) } />