import { useCallback } from 'react'; import { useRecoilValue } from 'recoil'; import { useGetModelsQuery } from 'librechat-data-provider/react-query'; import { getEndpointField, LocalStorageKeys, isAssistantsEndpoint } from 'librechat-data-provider'; import type { TEndpointsConfig, EModelEndpoint, TConversation } from 'librechat-data-provider'; import type { AssistantListItem, NewConversationParams } from '~/common'; import useAssistantListMap from '~/hooks/Assistants/useAssistantListMap'; import { buildDefaultConvo, getDefaultEndpoint } from '~/utils'; import { useGetEndpointsQuery } from '~/data-provider'; import { mainTextareaId } from '~/common'; import store from '~/store'; const ADDED_INDEX = 1; /** * Simplified hook for added conversation state. * Provides just the conversation state and a function to generate a new conversation, * mirroring the pattern from useNewConvo. */ export default function useAddedResponse() { const modelsQuery = useGetModelsQuery(); const assistantsListMap = useAssistantListMap(); const rootConvo = useRecoilValue(store.conversationByKeySelector(0)); const { data: endpointsConfig = {} as TEndpointsConfig } = useGetEndpointsQuery(); const { conversation, setConversation } = store.useCreateConversationAtom(ADDED_INDEX); /** * Generate a new conversation based on template and preset. * Mirrors the logic from useNewConvo's switchToConversation. */ const generateConversation = useCallback( ({ template = {}, preset, modelsData }: NewConversationParams = {}) => { let newConversation: TConversation = { conversationId: rootConvo?.conversationId ?? 'new', title: '', endpoint: null, ...template, createdAt: '', updatedAt: '', } as TConversation; const modelsConfig = modelsData ?? modelsQuery.data; const activePreset = preset ?? newConversation; const defaultEndpoint = getDefaultEndpoint({ convoSetup: activePreset, endpointsConfig, }); const endpointType = getEndpointField(endpointsConfig, defaultEndpoint, 'type'); if (!newConversation.endpointType && endpointType) { newConversation.endpointType = endpointType; } else if (newConversation.endpointType && !endpointType) { newConversation.endpointType = undefined; } const isAssistantEndpoint = isAssistantsEndpoint(defaultEndpoint); const assistants: AssistantListItem[] = assistantsListMap[defaultEndpoint ?? ''] ?? []; if ( newConversation.assistant_id && !assistantsListMap[defaultEndpoint ?? '']?.[newConversation.assistant_id] ) { newConversation.assistant_id = undefined; } if (!newConversation.assistant_id && isAssistantEndpoint) { newConversation.assistant_id = localStorage.getItem(`${LocalStorageKeys.ASST_ID_PREFIX}0${defaultEndpoint}`) ?? assistants[0]?.id; } if ( newConversation.assistant_id != null && isAssistantEndpoint && newConversation.conversationId === 'new' ) { const assistant = assistants.find((asst) => asst.id === newConversation.assistant_id); newConversation.model = assistant?.model; } if (newConversation.assistant_id != null && !isAssistantEndpoint) { newConversation.assistant_id = undefined; } const models = modelsConfig?.[defaultEndpoint ?? ''] ?? []; newConversation = buildDefaultConvo({ conversation: newConversation, lastConversationSetup: preset as TConversation, endpoint: defaultEndpoint ?? ('' as EModelEndpoint), models, }); if (preset?.title != null && preset.title !== '') { newConversation.title = preset.title; } setConversation(newConversation); setTimeout(() => { const textarea = document.getElementById(mainTextareaId); if (textarea) { textarea.focus(); } }, 150); return newConversation; }, [ endpointsConfig, setConversation, modelsQuery.data, assistantsListMap, rootConvo?.conversationId, ], ); return { conversation, setConversation, generateConversation, }; }