| import { useCallback, useMemo } from 'react'; |
| import { ContentTypes } from 'librechat-data-provider'; |
| import { useQueryClient } from '@tanstack/react-query'; |
|
|
| import type { |
| Text, |
| TMessage, |
| ImageFile, |
| ContentPart, |
| PartMetadata, |
| TContentData, |
| EventSubmission, |
| TMessageContentParts, |
| } from 'librechat-data-provider'; |
| import { addFileToCache } from '~/utils'; |
|
|
| type TUseContentHandler = { |
| setMessages: (messages: TMessage[]) => void; |
| getMessages: () => TMessage[] | undefined; |
| }; |
|
|
| type TContentHandler = { |
| data: TContentData; |
| submission: EventSubmission; |
| }; |
|
|
| export default function useContentHandler({ setMessages, getMessages }: TUseContentHandler) { |
| const queryClient = useQueryClient(); |
| const messageMap = useMemo(() => new Map<string, TMessage>(), []); |
| return useCallback( |
| ({ data, submission }: TContentHandler) => { |
| const { type, messageId, thread_id, conversationId, index } = data; |
|
|
| const _messages = getMessages(); |
| const messages = |
| _messages?.filter((m) => m.messageId !== messageId).map((msg) => ({ ...msg, thread_id })) ?? |
| []; |
| const userMessage = messages[messages.length - 1] as TMessage | undefined; |
|
|
| const { initialResponse } = submission; |
|
|
| let response = messageMap.get(messageId); |
| if (!response) { |
| response = { |
| ...(initialResponse as TMessage), |
| parentMessageId: userMessage?.messageId ?? '', |
| conversationId, |
| messageId, |
| thread_id, |
| }; |
| messageMap.set(messageId, response); |
| } |
|
|
| |
| const textPart: Text | string | undefined = data[ContentTypes.TEXT]; |
| const part: ContentPart = |
| textPart != null && typeof textPart === 'string' ? { value: textPart } : data[type]; |
|
|
| if (type === ContentTypes.IMAGE_FILE) { |
| addFileToCache(queryClient, part as ImageFile & PartMetadata); |
| } |
|
|
| |
| response.content = [...(response.content ?? [])]; |
|
|
| response.content[index] = { type, [type]: part } as TMessageContentParts; |
|
|
| const lastContentPart = response.content[response.content.length - 1]; |
| const initialContentPart = initialResponse.content?.[0]; |
| if ( |
| type !== ContentTypes.TEXT && |
| initialContentPart != null && |
| lastContentPart != null && |
| ((lastContentPart.type === ContentTypes.TOOL_CALL && |
| lastContentPart[ContentTypes.TOOL_CALL]?.progress === 1) || |
| lastContentPart.type === ContentTypes.IMAGE_FILE) |
| ) { |
| response.content.push(initialContentPart); |
| } |
|
|
| setMessages([...messages, response]); |
| }, |
| [queryClient, getMessages, messageMap, setMessages], |
| ); |
| } |
|
|