| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- import { MessageType } from '@/constants/chat';
- import { useFetchFlow } from '@/hooks/flow-hooks';
- import {
- useHandleMessageInputChange,
- useScrollToBottom,
- useSelectDerivedMessages,
- useSendMessageWithSse,
- } from '@/hooks/logic-hooks';
- import { IAnswer, Message } from '@/interfaces/database/chat';
- import { IMessage } from '@/pages/chat/interface';
- import api from '@/utils/api';
- import { buildMessageUuid } from '@/utils/chat';
- import { message } from 'antd';
- import trim from 'lodash/trim';
- import { useCallback, useEffect, useState } from 'react';
- import { useParams } from 'umi';
- import { v4 as uuid } from 'uuid';
- import { receiveMessageError } from '../utils';
-
- const antMessage = message;
-
- export const useSelectCurrentMessages = () => {
- const { id: id } = useParams();
- const [currentMessages, setCurrentMessages] = useState<IMessage[]>([]);
-
- const { data: flowDetail, loading } = useFetchFlow();
- const messages = flowDetail.dsl.messages;
- const reference = flowDetail.dsl.reference;
-
- const ref = useScrollToBottom(currentMessages);
-
- const addNewestQuestion = useCallback(
- (message: Message, answer: string = '') => {
- setCurrentMessages((pre) => {
- return [
- ...pre,
- {
- ...message,
- id: buildMessageUuid(message),
- },
- {
- role: MessageType.Assistant,
- content: answer,
- id: buildMessageUuid({ ...message, role: MessageType.Assistant }),
- },
- ];
- });
- },
- [],
- );
-
- const addNewestAnswer = useCallback((answer: IAnswer) => {
- setCurrentMessages((pre) => {
- return [
- ...pre.slice(0, -1),
- {
- role: MessageType.Assistant,
- content: answer.answer,
- reference: answer.reference,
- id: buildMessageUuid({
- id: answer.id,
- role: MessageType.Assistant,
- }),
- },
- ];
- });
- }, []);
-
- const removeLatestMessage = useCallback(() => {
- setCurrentMessages((pre) => {
- const nextMessages = pre?.slice(0, -2) ?? [];
- return nextMessages;
- return [...pre, ...nextMessages];
- });
- }, []);
-
- useEffect(() => {
- if (id) {
- const nextMessages = messages.map((x) => ({ ...x, id: uuid() }));
- setCurrentMessages(nextMessages);
- }
- }, [messages, id]);
-
- return {
- currentMessages,
- reference,
- addNewestQuestion,
- removeLatestMessage,
- addNewestAnswer,
- ref,
- loading,
- };
- };
-
- export const useSelectNextMessages = () => {
- const { id: id } = useParams();
- const { data: flowDetail, loading } = useFetchFlow();
- const messages = flowDetail.dsl.messages;
- const reference = flowDetail.dsl.reference;
- const {
- derivedMessages,
- setDerivedMessages,
- ref,
- addNewestQuestion,
- addNewestAnswer,
- removeLatestMessage,
- removeMessageById,
- removeMessagesAfterCurrentMessage,
- } = useSelectDerivedMessages();
-
- useEffect(() => {
- if (id) {
- const nextMessages = messages.map((x) => ({ ...x, id: uuid() }));
- setDerivedMessages(nextMessages);
- }
- }, [messages, id, setDerivedMessages]);
-
- return {
- reference,
- loading,
- derivedMessages,
- ref,
- addNewestQuestion,
- addNewestAnswer,
- removeLatestMessage,
- removeMessageById,
- removeMessagesAfterCurrentMessage,
- };
- };
-
- export const useSendMessage = (
- addNewestQuestion: (message: Message, answer?: string) => void,
- removeLatestMessage: () => void,
- addNewestAnswer: (answer: IAnswer) => void,
- ) => {
- const { id: flowId } = useParams();
- const { handleInputChange, value, setValue } = useHandleMessageInputChange();
- const { refetch } = useFetchFlow();
-
- const { send, answer, done } = useSendMessageWithSse(api.runCanvas);
-
- const sendMessage = useCallback(
- async (message: Message) => {
- const params: Record<string, unknown> = {
- id: flowId,
- };
- if (message.content) {
- params.message = message.content;
- params.message_id = message.id;
- }
- const res = await send(params);
-
- if (receiveMessageError(res)) {
- antMessage.error(res?.data?.message);
-
- // cancel loading
- setValue(message.content);
- removeLatestMessage();
- } else {
- refetch(); // pull the message list after sending the message successfully
- }
- },
- [flowId, removeLatestMessage, setValue, send, refetch],
- );
-
- const handleSendMessage = useCallback(
- async (message: Message) => {
- sendMessage(message);
- },
- [sendMessage],
- );
-
- useEffect(() => {
- if (answer.answer) {
- addNewestAnswer(answer);
- }
- }, [answer, addNewestAnswer]);
-
- const handlePressEnter = useCallback(() => {
- if (trim(value) === '') return;
- const id = uuid();
- if (done) {
- setValue('');
- handleSendMessage({ id, content: value.trim(), role: MessageType.User });
- }
- addNewestQuestion({
- content: value,
- id,
- role: MessageType.User,
- });
- }, [addNewestQuestion, handleSendMessage, done, setValue, value]);
-
- return {
- handlePressEnter,
- handleInputChange,
- value,
- loading: !done,
- };
- };
-
- export const useSendNextMessage = () => {
- const {
- reference,
- loading,
- derivedMessages,
- ref,
- addNewestQuestion,
- addNewestAnswer,
- removeLatestMessage,
- removeMessageById,
- } = useSelectNextMessages();
- const { id: flowId } = useParams();
- const { handleInputChange, value, setValue } = useHandleMessageInputChange();
- const { refetch } = useFetchFlow();
-
- const { send, answer, done } = useSendMessageWithSse(api.runCanvas);
-
- const sendMessage = useCallback(
- async ({ message }: { message: Message; messages?: Message[] }) => {
- const params: Record<string, unknown> = {
- id: flowId,
- };
- if (message.content) {
- params.message = message.content;
- params.message_id = message.id;
- }
- const res = await send(params);
-
- if (receiveMessageError(res)) {
- antMessage.error(res?.data?.message);
-
- // cancel loading
- setValue(message.content);
- removeLatestMessage();
- } else {
- refetch(); // pull the message list after sending the message successfully
- }
- },
- [flowId, removeLatestMessage, setValue, send, refetch],
- );
-
- const handleSendMessage = useCallback(
- async (message: Message) => {
- sendMessage({ message });
- },
- [sendMessage],
- );
-
- useEffect(() => {
- if (answer.answer) {
- addNewestAnswer(answer);
- }
- }, [answer, addNewestAnswer]);
-
- const handlePressEnter = useCallback(() => {
- if (trim(value) === '') return;
- const id = uuid();
- if (done) {
- setValue('');
- handleSendMessage({ id, content: value.trim(), role: MessageType.User });
- }
- addNewestQuestion({
- content: value,
- id,
- role: MessageType.User,
- });
- }, [addNewestQuestion, handleSendMessage, done, setValue, value]);
-
- return {
- handlePressEnter,
- handleInputChange,
- value,
- sendLoading: !done,
- reference,
- loading,
- derivedMessages,
- ref,
- removeMessageById,
- };
- };
|