| | import throttle from 'lodash/throttle'; |
| | import { useEffect, useRef, useCallback, useMemo } from 'react'; |
| | import { Constants, isAssistantsEndpoint, isAgentsEndpoint } from 'librechat-data-provider'; |
| | import type { TMessageProps } from '~/common'; |
| | import { useMessagesViewContext, useAssistantsMapContext, useAgentsMapContext } from '~/Providers'; |
| | import { getTextKey, TEXT_KEY_DIVIDER, logger } from '~/utils'; |
| | import useCopyToClipboard from './useCopyToClipboard'; |
| |
|
| | export default function useMessageHelpers(props: TMessageProps) { |
| | const latestText = useRef<string | number>(''); |
| | const { message, currentEditId, setCurrentEditId } = props; |
| |
|
| | const { |
| | ask, |
| | index, |
| | regenerate, |
| | isSubmitting, |
| | conversation, |
| | latestMessage, |
| | setAbortScroll, |
| | handleContinue, |
| | setLatestMessage, |
| | } = useMessagesViewContext(); |
| | const agentsMap = useAgentsMapContext(); |
| | const assistantMap = useAssistantsMapContext(); |
| |
|
| | const { text, content, children, messageId = null, isCreatedByUser } = message ?? {}; |
| | const edit = messageId === currentEditId; |
| | const isLast = children?.length === 0 || children?.length === undefined; |
| |
|
| | useEffect(() => { |
| | const convoId = conversation?.conversationId; |
| | if (convoId === Constants.NEW_CONVO) { |
| | return; |
| | } |
| | if (!message) { |
| | return; |
| | } |
| | if (!isLast) { |
| | return; |
| | } |
| |
|
| | const textKey = getTextKey(message, convoId); |
| |
|
| | |
| | const logInfo = { |
| | textKey, |
| | 'latestText.current': latestText.current, |
| | messageId: message.messageId, |
| | convoId, |
| | }; |
| |
|
| | |
| | let previousConvoId: string | null = null; |
| | if ( |
| | latestText.current && |
| | typeof latestText.current === 'string' && |
| | latestText.current.length > 0 |
| | ) { |
| | const parts = latestText.current.split(TEXT_KEY_DIVIDER); |
| | previousConvoId = parts[parts.length - 1] || null; |
| | } |
| |
|
| | if ( |
| | textKey !== latestText.current || |
| | (convoId != null && previousConvoId != null && convoId !== previousConvoId) |
| | ) { |
| | logger.log('latest_message', '[useMessageHelpers] Setting latest message: ', logInfo); |
| | latestText.current = textKey; |
| | setLatestMessage({ ...message }); |
| | } else { |
| | logger.log('latest_message', 'No change in latest message', logInfo); |
| | } |
| | }, [isLast, message, setLatestMessage, conversation?.conversationId]); |
| |
|
| | const enterEdit = useCallback( |
| | (cancel?: boolean) => setCurrentEditId && setCurrentEditId(cancel === true ? -1 : messageId), |
| | [messageId, setCurrentEditId], |
| | ); |
| |
|
| | const handleScroll = useCallback( |
| | (event: unknown) => { |
| | throttle(() => { |
| | logger.log( |
| | 'message_scrolling', |
| | `useMessageHelpers: setting abort scroll to ${isSubmitting}, handleScroll event`, |
| | event, |
| | ); |
| | if (isSubmitting) { |
| | setAbortScroll(true); |
| | } else { |
| | setAbortScroll(false); |
| | } |
| | }, 500)(); |
| | }, |
| | [isSubmitting, setAbortScroll], |
| | ); |
| |
|
| | const assistant = useMemo(() => { |
| | if (!isAssistantsEndpoint(conversation?.endpoint)) { |
| | return undefined; |
| | } |
| |
|
| | const endpointKey = conversation?.endpoint ?? ''; |
| | const modelKey = message?.model ?? ''; |
| |
|
| | return assistantMap?.[endpointKey] ? assistantMap[endpointKey][modelKey] : undefined; |
| | }, [conversation?.endpoint, message?.model, assistantMap]); |
| |
|
| | const agent = useMemo(() => { |
| | if (!isAgentsEndpoint(conversation?.endpoint)) { |
| | return undefined; |
| | } |
| |
|
| | const modelKey = message?.model ?? ''; |
| |
|
| | return agentsMap ? agentsMap[modelKey] : undefined; |
| | }, [agentsMap, conversation?.endpoint, message?.model]); |
| |
|
| | const regenerateMessage = () => { |
| | if ((isSubmitting && isCreatedByUser === true) || !message) { |
| | return; |
| | } |
| |
|
| | regenerate(message); |
| | }; |
| |
|
| | const copyToClipboard = useCopyToClipboard({ text, content }); |
| |
|
| | return { |
| | ask, |
| | edit, |
| | agent, |
| | index, |
| | isLast, |
| | assistant, |
| | enterEdit, |
| | conversation, |
| | isSubmitting, |
| | handleScroll, |
| | latestMessage, |
| | handleContinue, |
| | copyToClipboard, |
| | regenerateMessage, |
| | }; |
| | } |
| |
|