import { useState } from 'react'; import { Settings } from 'lucide-react'; import { useRecoilValue } from 'recoil'; import { EModelEndpoint, modularEndpoints } from 'librechat-data-provider'; import { useGetEndpointsQuery } from 'librechat-data-provider/react-query'; import type { TPreset, TConversation } from 'librechat-data-provider'; import type { FC } from 'react'; import { useLocalize, useUserKey, useDefaultConvo } from '~/hooks'; import { SetKeyDialog } from '~/components/Input/SetKeyDialog'; import { cn, getEndpointField } from '~/utils'; import { useChatContext } from '~/Providers'; import { icons } from './Icons'; import store from '~/store'; type MenuItemProps = { title: string; value: EModelEndpoint; selected: boolean; description?: string; userProvidesKey: boolean; // iconPath: string; // hoverContent?: string; }; const MenuItem: FC = ({ title, value: endpoint, description, selected, userProvidesKey, ...rest }) => { const modularChat = useRecoilValue(store.modularChat); const [isDialogOpen, setDialogOpen] = useState(false); const { data: endpointsConfig } = useGetEndpointsQuery(); const { conversation, newConversation } = useChatContext(); const getDefaultConversation = useDefaultConvo(); const { getExpiry } = useUserKey(endpoint); const localize = useLocalize(); const expiryTime = getExpiry(); const onSelectEndpoint = (newEndpoint: EModelEndpoint) => { if (!newEndpoint) { return; } else { if (!expiryTime) { setDialogOpen(true); } const currentEndpoint = conversation?.endpoint; const template: Partial = { ...conversation, endpoint: newEndpoint, conversationId: 'new', }; const isAssistantSwitch = newEndpoint === EModelEndpoint.assistants && currentEndpoint === EModelEndpoint.assistants && currentEndpoint === newEndpoint; const { conversationId } = conversation ?? {}; const isExistingConversation = conversationId && conversationId !== 'new'; const currentEndpointType = getEndpointField(endpointsConfig, currentEndpoint, 'type') ?? currentEndpoint; const newEndpointType = getEndpointField(endpointsConfig, newEndpoint, 'type') ?? newEndpoint; const hasEndpoint = modularEndpoints.has(currentEndpoint ?? ''); const hasCurrentEndpointType = modularEndpoints.has(currentEndpointType ?? ''); const isCurrentModular = hasEndpoint || hasCurrentEndpointType || isAssistantSwitch; const hasNewEndpoint = modularEndpoints.has(newEndpoint ?? ''); const hasNewEndpointType = modularEndpoints.has(newEndpointType ?? ''); const isNewModular = hasNewEndpoint || hasNewEndpointType || isAssistantSwitch; const endpointsMatch = currentEndpoint === newEndpoint; const shouldSwitch = endpointsMatch || modularChat || isAssistantSwitch; if (isExistingConversation && isCurrentModular && isNewModular && shouldSwitch) { template.endpointType = newEndpointType; const currentConvo = getDefaultConversation({ /* target endpointType is necessary to avoid endpoint mixing */ conversation: { ...(conversation ?? {}), endpointType: template.endpointType }, preset: template, }); /* We don't reset the latest message, only when changing settings mid-converstion */ newConversation({ template: currentConvo, preset: currentConvo, keepLatestMessage: true }); return; } newConversation({ template: { ...(template as Partial) } }); } }; const endpointType = getEndpointField(endpointsConfig, endpoint, 'type'); const iconKey = endpointType ? 'unknown' : endpoint ?? 'unknown'; const Icon = icons[iconKey]; return ( <>
onSelectEndpoint(endpoint)} >
{Icon && ( )}
{title}
{description}
{userProvidesKey ? (
) : null} {selected && ( )} {(!userProvidesKey || expiryTime) && (
{!userProvidesKey &&
{localize('com_ui_new_chat')}
}
)}
{userProvidesKey && ( )} ); }; export default MenuItem;