import endpoints from './endpoints'; import { useCallback } from 'react'; import { atom, selector, atomFamily, useSetRecoilState, useResetRecoilState, useRecoilCallback, } from 'recoil'; import buildTree from '~/utils/buildTree'; import getDefaultConversation from '~/utils/getDefaultConversation'; import submission from './submission.js'; const conversation = atom({ key: 'conversation', default: null, }); // current messages of the conversation, must be an array // sample structure // [{text, sender, messageId, parentMessageId, isCreatedByUser}] const messages = atom({ key: 'messages', default: [], }); const messagesTree = selector({ key: 'messagesTree', get: ({ get }) => { return buildTree(get(messages), false); }, }); const latestMessage = atom({ key: 'latestMessage', default: null, }); const messagesSiblingIdxFamily = atomFamily({ key: 'messagesSiblingIdx', default: 0, }); const useConversation = () => { const setConversation = useSetRecoilState(conversation); const setMessages = useSetRecoilState(messages); const setSubmission = useSetRecoilState(submission.submission); const resetLatestMessage = useResetRecoilState(latestMessage); const _switchToConversation = ( conversation, messages = null, preset = null, { endpointsConfig = {}, prevConversation = {} }, ) => { let { endpoint = null } = conversation; if (endpoint === null) { // get the default model conversation = getDefaultConversation({ conversation, endpointsConfig, prevConversation, preset, }); } setConversation(conversation); setMessages(messages); setSubmission({}); resetLatestMessage(); }; const switchToConversation = useRecoilCallback( ({ snapshot }) => async (_conversation, messages = null, preset = null) => { const prevConversation = await snapshot.getPromise(conversation); const endpointsConfig = await snapshot.getPromise(endpoints.endpointsConfig); _switchToConversation(_conversation, messages, preset, { endpointsConfig, prevConversation, }); }, [], ); const newConversation = useCallback( (template = {}, preset) => { switchToConversation( { conversationId: 'new', title: 'New Chat', ...template, }, [], preset, ); }, [switchToConversation], ); const searchPlaceholderConversation = () => { switchToConversation( { conversationId: 'search', title: 'Search', }, [], ); }; return { _switchToConversation, newConversation, switchToConversation, searchPlaceholderConversation, }; }; export default { conversation, messages, messagesTree, latestMessage, messagesSiblingIdxFamily, useConversation, };