import { useCallback, useState } from 'react'; import { useQueryClient } from '@tanstack/react-query'; import { QueryKeys } from 'librechat-data-provider'; import { useRecoilState, useResetRecoilState, useSetRecoilState } from 'recoil'; import { useGetMessagesByConvoId } from 'librechat-data-provider/react-query'; import type { TMessage } from 'librechat-data-provider'; import useChatFunctions from '~/hooks/Chat/useChatFunctions'; import { useAuthContext } from '~/hooks/AuthContext'; import useNewConvo from '~/hooks/useNewConvo'; import store from '~/store'; // this to be set somewhere else export default function useChatHelpers(index = 0, paramId?: string) { const clearAllSubmissions = store.useClearSubmissionState(); const [files, setFiles] = useRecoilState(store.filesByIndex(index)); const [filesLoading, setFilesLoading] = useState(false); const queryClient = useQueryClient(); const { isAuthenticated } = useAuthContext(); const { newConversation } = useNewConvo(index); const { useCreateConversationAtom } = store; const { conversation, setConversation } = useCreateConversationAtom(index); const { conversationId } = conversation ?? {}; const queryParam = paramId === 'new' ? paramId : conversationId ?? paramId ?? ''; /* Messages: here simply to fetch, don't export and use `getMessages()` instead */ // eslint-disable-next-line @typescript-eslint/no-unused-vars const { data: _messages } = useGetMessagesByConvoId(conversationId ?? '', { enabled: isAuthenticated, }); const resetLatestMessage = useResetRecoilState(store.latestMessageFamily(index)); const [isSubmitting, setIsSubmitting] = useRecoilState(store.isSubmittingFamily(index)); const [latestMessage, setLatestMessage] = useRecoilState(store.latestMessageFamily(index)); const setSiblingIdx = useSetRecoilState( store.messagesSiblingIdxFamily(latestMessage?.parentMessageId ?? null), ); const setMessages = useCallback( (messages: TMessage[]) => { queryClient.setQueryData([QueryKeys.messages, queryParam], messages); if (queryParam === 'new') { queryClient.setQueryData([QueryKeys.messages, conversationId], messages); } }, [queryParam, queryClient, conversationId], ); const getMessages = useCallback(() => { return queryClient.getQueryData([QueryKeys.messages, queryParam]); }, [queryParam, queryClient]); /* Conversation */ // const setActiveConvos = useSetRecoilState(store.activeConversations); // const setConversation = useCallback( // (convoUpdate: TConversation) => { // _setConversation(prev => { // const { conversationId: convoId } = prev ?? { conversationId: null }; // const { conversationId: currentId } = convoUpdate; // if (currentId && convoId && convoId !== 'new' && convoId !== currentId) { // // for now, we delete the prev convoId from activeConversations // const newActiveConvos = { [currentId]: true }; // setActiveConvos(newActiveConvos); // } // return convoUpdate; // }); // }, // [_setConversation, setActiveConvos], // ); const setSubmission = useSetRecoilState(store.submissionByIndex(index)); const { ask, regenerate } = useChatFunctions({ index, files, setFiles, getMessages, setMessages, isSubmitting, conversation, latestMessage, setSubmission, setLatestMessage, }); const continueGeneration = () => { if (!latestMessage) { console.error('Failed to regenerate the message: latestMessage not found.'); return; } const messages = getMessages(); const parentMessage = messages?.find( (element) => element.messageId == latestMessage.parentMessageId, ); if (parentMessage && parentMessage.isCreatedByUser) { ask({ ...parentMessage }, { isContinued: true, isRegenerate: true, isEdited: true }); } else { console.error( 'Failed to regenerate the message: parentMessage not found, or not created by user.', ); } }; const stopGenerating = () => clearAllSubmissions(); const handleStopGenerating = (e: React.MouseEvent) => { e.preventDefault(); stopGenerating(); }; const handleRegenerate = (e: React.MouseEvent) => { e.preventDefault(); const parentMessageId = latestMessage?.parentMessageId; if (!parentMessageId) { console.error('Failed to regenerate the message: parentMessageId not found.'); return; } regenerate({ parentMessageId }); }; const handleContinue = (e: React.MouseEvent) => { e.preventDefault(); continueGeneration(); setSiblingIdx(0); }; const [showBingToneSetting, setShowBingToneSetting] = useRecoilState( store.showBingToneSettingFamily(index), ); const [showPopover, setShowPopover] = useRecoilState(store.showPopoverFamily(index)); const [abortScroll, setAbortScroll] = useRecoilState(store.abortScrollFamily(index)); const [preset, setPreset] = useRecoilState(store.presetByIndex(index)); const [optionSettings, setOptionSettings] = useRecoilState(store.optionSettingsFamily(index)); const [showAgentSettings, setShowAgentSettings] = useRecoilState( store.showAgentSettingsFamily(index), ); return { newConversation, conversation, setConversation, // getConvos, // setConvos, isSubmitting, setIsSubmitting, getMessages, setMessages, setSiblingIdx, latestMessage, setLatestMessage, resetLatestMessage, ask, index, regenerate, stopGenerating, handleStopGenerating, handleRegenerate, handleContinue, showPopover, setShowPopover, abortScroll, setAbortScroll, showBingToneSetting, setShowBingToneSetting, preset, setPreset, optionSettings, setOptionSettings, showAgentSettings, setShowAgentSettings, files, setFiles, filesLoading, setFilesLoading, }; }