import React, { useEffect } from "react"; import { displayDate } from "@/_utils/datetime"; import { useStore } from "@/_models/RootStore"; import { StreamingText, useTextBuffer } from "nextjs-openai"; import { MessageSenderType, MessageStatus } from "@/_models/ChatMessage"; import { Role } from "@/_models/History"; import { useMutation } from "@apollo/client"; import { OpenAI } from "openai-streams"; import { UpdateMessageDocument, UpdateMessageMutation, UpdateMessageMutationVariables, } from "@/graphql"; type Props = { id?: string; avatarUrl?: string; senderName: string; createdAt: number; text?: string; }; const StreamTextMessage: React.FC = ({ id, senderName, createdAt, avatarUrl = "", }) => { const [data, setData] = React.useState(); const { historyStore } = useStore(); const conversation = historyStore?.getActiveConversation(); const [updateMessage] = useMutation( UpdateMessageDocument ); React.useEffect(() => { if ( !conversation || conversation.chatMessages.findIndex((e) => e.id === id) !== conversation.chatMessages.length - 1 ) { return; } const messages = conversation?.chatMessages .slice(-10) .filter((e) => e.id !== id) .map((e) => ({ role: e.messageSenderType === MessageSenderType.User ? Role.User : Role.Assistant, content: e.text, })); setData({ messages, }); }, [conversation]); const { buffer, done } = useTextBuffer({ url: `api/openai`, data, }); useEffect(() => { if (done) { // mutate result const variables: UpdateMessageMutationVariables = { id: id, data: { content: buffer.join(""), status: MessageStatus.Ready, }, }; updateMessage({ variables, }); } }, [done]); useEffect(() => { if (buffer.length > 0 && conversation?.isWaitingForModelResponse) { historyStore.finishActiveConversationWaiting(); } }, [buffer]); return data ? (
{senderName}
{displayDate(createdAt)}
) : ( <> ); }; export default React.memo(StreamTextMessage);