import { memo, useCallback, useMemo, useState } from 'react' import { LocalEngines, Model } from '@janhq/core' import { Badge, Button, useClickOutside } from '@janhq/joi' import { useAtomValue, useSetAtom } from 'jotai' import { MoreVerticalIcon, PlayIcon, StopCircleIcon, Trash2Icon, } from 'lucide-react' import { twMerge } from 'tailwind-merge' import useModelStart from '@/hooks/useModelStart' import useModelStop from '@/hooks/useModelStop' import useModels from '@/hooks/useModels' import { showWarningMultipleModelModalAtom } from '@/screens/HubScreen2/components/WarningMultipleModelModal' import { activeModelsAtom } from '@/helpers/atoms/Model.atom' type Props = { model: Model } // If more than this number of models are running, show a warning modal. export const concurrentModelWarningThreshold = 2 const ModelItem: React.FC = ({ model }) => { const activeModels = useAtomValue(activeModelsAtom) const startModel = useModelStart() const stopModel = useModelStop() const [more, setMore] = useState(false) const { deleteModel } = useModels() const [menu, setMenu] = useState(null) const [toggle, setToggle] = useState(null) const setShowWarningMultipleModelModal = useSetAtom( showWarningMultipleModelModalAtom ) useClickOutside(() => setMore(false), null, [menu, toggle]) const isActive = useMemo( () => activeModels.map((m) => m.model).includes(model.model), [activeModels, model.model] ) const onModelActionClick = useCallback( (modelId: string) => { if (isActive) { // if model already active, stop it stopModel.mutate(modelId) return } if (activeModels.length >= concurrentModelWarningThreshold) { // if max concurrent models reached, stop the first model // display popup setShowWarningMultipleModelModal(true) } startModel.mutate(modelId) }, [ isActive, startModel, stopModel, activeModels.length, setShowWarningMultipleModelModal, ] ) const onDeleteModelClicked = useCallback( async (modelId: string) => { await stopModel.mutateAsync(modelId) await deleteModel(modelId) }, [stopModel, deleteModel] ) const isLocalModel = LocalEngines.find( (e) => model.engine != null && e === model.engine ) return (
{model.model}
{model.engine === 'cortex.llamacpp' && (

{model.model}

)}
{isLocalModel && (
{model.version != null ? `v${model.version}` : '-'}
{isActive ? ( Active ) : ( Inactive )}
{ setMore(!more) }} > {more && (
{ onModelActionClick(model.model) setMore(false) }} > {isActive ? ( ) : ( )} {isActive ? 'Stop' : 'Start'}  Model
onDeleteModelClicked(model.model)} > Delete Model
)}
)}
) } export default memo(ModelItem)