import { useRecoilValue } from 'recoil'; import { useCallback, useRef, useEffect } from 'react'; import { useGetModelsQuery } from 'librechat-data-provider/react-query'; import { LocalStorageKeys, isAssistantsEndpoint } from 'librechat-data-provider'; import type { TPreset, TModelsConfig, TConversation, TEndpointsConfig, EModelEndpoint, } from 'librechat-data-provider'; import type { SetterOrUpdater } from 'recoil'; import type { AssistantListItem } from '~/common'; import { getEndpointField, buildDefaultConvo, getDefaultEndpoint, logger } from '~/utils'; import useAssistantListMap from '~/hooks/Assistants/useAssistantListMap'; import { useGetEndpointsQuery } from '~/data-provider'; import { mainTextareaId } from '~/common'; import store from '~/store'; const useGenerateConvo = ({ index = 0, rootIndex, setConversation, }: { index?: number; rootIndex: number; setConversation?: SetterOrUpdater; }) => { const modelsQuery = useGetModelsQuery(); const assistantsListMap = useAssistantListMap(); const { data: endpointsConfig = {} as TEndpointsConfig } = useGetEndpointsQuery(); const timeoutIdRef = useRef(); const rootConvo = useRecoilValue(store.conversationByKeySelector(rootIndex)); useEffect(() => { if (rootConvo?.conversationId != null && setConversation) { setConversation((prevState) => { if (!prevState) { return prevState; } const update = { ...prevState, conversationId: rootConvo.conversationId, } as TConversation; logger.log('conversation', 'Setting conversation from `useNewConvo`', update); return update; }); } }, [rootConvo?.conversationId, setConversation]); const generateConversation = useCallback( ({ template = {}, preset, modelsData, }: { template?: Partial; preset?: Partial; modelsData?: TModelsConfig; } = {}) => { let conversation = { conversationId: 'new', title: 'New Chat', endpoint: null, ...template, createdAt: '', updatedAt: '', }; if (rootConvo?.conversationId) { conversation.conversationId = rootConvo.conversationId; } const modelsConfig = modelsData ?? modelsQuery.data; const defaultEndpoint = getDefaultEndpoint({ convoSetup: preset ?? conversation, endpointsConfig, }); const endpointType = getEndpointField(endpointsConfig, defaultEndpoint, 'type'); if (!conversation.endpointType && endpointType) { conversation.endpointType = endpointType; } else if (conversation.endpointType && !endpointType) { conversation.endpointType = undefined; } const isAssistantEndpoint = isAssistantsEndpoint(defaultEndpoint); const assistants: AssistantListItem[] = assistantsListMap[defaultEndpoint ?? ''] ?? []; if ( conversation.assistant_id && !assistantsListMap[defaultEndpoint ?? '']?.[conversation.assistant_id] ) { conversation.assistant_id = undefined; } if (!conversation.assistant_id && isAssistantEndpoint) { conversation.assistant_id = localStorage.getItem(`${LocalStorageKeys.ASST_ID_PREFIX}${index}${defaultEndpoint}`) ?? assistants[0]?.id; } if ( conversation.assistant_id != null && isAssistantEndpoint && conversation.conversationId === 'new' ) { const assistant = assistants.find((asst) => asst.id === conversation.assistant_id); conversation.model = assistant?.model; } if (conversation.assistant_id != null && !isAssistantEndpoint) { conversation.assistant_id = undefined; } const models = modelsConfig?.[defaultEndpoint ?? ''] ?? []; conversation = buildDefaultConvo({ conversation, lastConversationSetup: preset as TConversation, endpoint: defaultEndpoint ?? ('' as EModelEndpoint), models, }); if (preset?.title != null && preset.title !== '') { conversation.title = preset.title; } if (setConversation) { setConversation(conversation); } clearTimeout(timeoutIdRef.current); timeoutIdRef.current = setTimeout(() => { const textarea = document.getElementById(mainTextareaId); if (textarea) { textarea.focus(); } }, 150); return conversation; }, [assistantsListMap, endpointsConfig, index, modelsQuery.data, rootConvo, setConversation], ); return { generateConversation }; }; export default useGenerateConvo;