### What problem does this PR solve? Fix: Fix share-chat bugs #3221 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)tags/v0.20.0
| @@ -44,6 +44,7 @@ interface IProps | |||
| nickname?: string; | |||
| avatar?: string; | |||
| avatarDialog?: string | null; | |||
| agentName?: string; | |||
| clickDocumentButton?: (documentId: string, chunk: IReferenceChunk) => void; | |||
| index: number; | |||
| showLikeButton?: boolean; | |||
| @@ -60,6 +61,7 @@ function MessageItem({ | |||
| loading = false, | |||
| avatar, | |||
| avatarDialog, | |||
| agentName, | |||
| sendLoading = false, | |||
| clickDocumentButton, | |||
| removeMessageById, | |||
| @@ -120,8 +122,8 @@ function MessageItem({ | |||
| {visibleAvatar && | |||
| (item.role === MessageType.User ? ( | |||
| <RAGFlowAvatar avatar={avatar ?? '/logo.svg'} /> | |||
| ) : avatarDialog ? ( | |||
| <RAGFlowAvatar avatar={avatarDialog} /> | |||
| ) : avatarDialog || agentName ? ( | |||
| <RAGFlowAvatar avatar={avatarDialog} name={agentName} isPerson /> | |||
| ) : ( | |||
| <AssistantIcon /> | |||
| ))} | |||
| @@ -487,6 +487,10 @@ export const useSelectDerivedMessages = () => { | |||
| [setDerivedMessages], | |||
| ); | |||
| const removeAllMessages = useCallback(() => { | |||
| setDerivedMessages([]); | |||
| }, [setDerivedMessages]); | |||
| return { | |||
| ref, | |||
| derivedMessages, | |||
| @@ -498,6 +502,7 @@ export const useSelectDerivedMessages = () => { | |||
| addNewestOneQuestion, | |||
| addNewestOneAnswer, | |||
| removeMessagesAfterCurrentMessage, | |||
| removeAllMessages, | |||
| }; | |||
| }; | |||
| @@ -10,7 +10,7 @@ import { DSL, IFlow, IFlowTemplate } from '@/interfaces/database/flow'; | |||
| import { IDebugSingleRequestBody } from '@/interfaces/request/agent'; | |||
| import i18n from '@/locales/config'; | |||
| import { BeginId } from '@/pages/agent/constant'; | |||
| import { BeginQuery } from '@/pages/agent/interface'; | |||
| import { IInputs } from '@/pages/agent/interface'; | |||
| import { useGetSharedChatSearchParams } from '@/pages/chat/shared-hooks'; | |||
| import agentService, { | |||
| fetchAgentLogsByCanvasId, | |||
| @@ -596,9 +596,9 @@ export const useFetchExternalAgentInputs = () => { | |||
| data, | |||
| isFetching: loading, | |||
| refetch, | |||
| } = useQuery<Record<string, BeginQuery>>({ | |||
| } = useQuery<IInputs>({ | |||
| queryKey: [AgentApiAction.FetchExternalAgentInputs], | |||
| initialData: {} as Record<string, BeginQuery>, | |||
| initialData: {} as IInputs, | |||
| refetchOnReconnect: false, | |||
| refetchOnMount: false, | |||
| refetchOnWindowFocus: false, | |||
| @@ -182,9 +182,8 @@ export const useSendAgentMessage = ( | |||
| const { handleInputChange, value, setValue } = useHandleMessageInputChange(); | |||
| const inputs = useSelectBeginNodeDataInputs(); | |||
| const [sessionId, setSessionId] = useState<string | null>(null); | |||
| const { send, answerList, done, stopOutputMessage } = useSendMessageBySSE( | |||
| url || api.runCanvas, | |||
| ); | |||
| const { send, answerList, done, stopOutputMessage, resetAnswerList } = | |||
| useSendMessageBySSE(url || api.runCanvas); | |||
| const messageId = useMemo(() => { | |||
| return answerList[0]?.message_id; | |||
| }, [answerList]); | |||
| @@ -204,6 +203,7 @@ export const useSendAgentMessage = ( | |||
| removeMessageById, | |||
| addNewestOneQuestion, | |||
| addNewestOneAnswer, | |||
| removeAllMessages, | |||
| } = useSelectDerivedMessages(); | |||
| const { addEventList: addEventListFun } = useContext(AgentChatLogContext); | |||
| const { | |||
| @@ -280,6 +280,14 @@ export const useSendAgentMessage = ( | |||
| [addNewestOneQuestion, send], | |||
| ); | |||
| // reset session | |||
| const resetSession = useCallback(() => { | |||
| stopOutputMessage(); | |||
| resetAnswerList(); | |||
| setSessionId(null); | |||
| removeAllMessages(); | |||
| }, [resetAnswerList, removeAllMessages, stopOutputMessage]); | |||
| const handlePressEnter = useCallback(() => { | |||
| if (trim(value) === '') return; | |||
| const id = uuid(); | |||
| @@ -336,6 +344,7 @@ export const useSendAgentMessage = ( | |||
| stopOutputMessage, | |||
| send, | |||
| sendFormMessage, | |||
| resetSession, | |||
| findReferenceByMessageId, | |||
| appendUploadResponseList, | |||
| }; | |||
| @@ -237,14 +237,16 @@ const DebugContent = ({ | |||
| {parameters.map((x, idx) => { | |||
| return <div key={idx}>{renderWidget(x, idx.toString())}</div>; | |||
| })} | |||
| <ButtonLoading | |||
| type="submit" | |||
| loading={loading} | |||
| disabled={!submittable || submitButtonDisabled} | |||
| className="w-full" | |||
| > | |||
| {btnText || t(isNext ? 'common.next' : 'flow.run')} | |||
| </ButtonLoading> | |||
| <div> | |||
| <ButtonLoading | |||
| type="submit" | |||
| loading={loading} | |||
| disabled={!submittable || submitButtonDisabled} | |||
| className="w-full mt-8" | |||
| > | |||
| {btnText || t(isNext ? 'common.next' : 'flow.run')} | |||
| </ButtonLoading> | |||
| </div> | |||
| </form> | |||
| </Form> | |||
| </section> | |||
| @@ -41,6 +41,7 @@ export function useCacheChatLog() { | |||
| const clearEventList = useCallback(() => { | |||
| setEventList([]); | |||
| setMessageIdPool({}); | |||
| }, []); | |||
| const addEventList = useCallback((events: IEventList, message_id: string) => { | |||
| @@ -33,3 +33,9 @@ export interface BeginQuery { | |||
| name: string; | |||
| options: (number | string | boolean)[]; | |||
| } | |||
| export type IInputs = { | |||
| avatar: string; | |||
| title: string; | |||
| inputs: Record<string, BeginQuery>; | |||
| }; | |||
| @@ -5,7 +5,7 @@ import { useFetchUserInfo } from '@/hooks/user-setting-hooks'; | |||
| import { IAgentLogMessage } from '@/interfaces/database/agent'; | |||
| import { IReferenceObject, Message } from '@/interfaces/database/chat'; | |||
| import { buildMessageUuidWithRole } from '@/utils/chat'; | |||
| import React from 'react'; | |||
| import React, { useMemo } from 'react'; | |||
| import { IMessage } from '../chat/interface'; | |||
| interface CustomModalProps { | |||
| @@ -23,13 +23,32 @@ export const AgentLogDetailModal: React.FC<CustomModalProps> = ({ | |||
| }) => { | |||
| const { data: userInfo } = useFetchUserInfo(); | |||
| const { data: canvasInfo } = useFetchAgent(); | |||
| const shortMessage = useMemo(() => { | |||
| const content = derivedMessages[0]?.content || ''; | |||
| const chineseCharCount = (content.match(/[\u4e00-\u9fa5]/g) || []).length; | |||
| const totalLength = content.length; | |||
| if (chineseCharCount > 0) { | |||
| if (totalLength > 15) { | |||
| return content.substring(0, 15) + '...'; | |||
| } | |||
| } else { | |||
| if (totalLength > 30) { | |||
| return content.substring(0, 30) + '...'; | |||
| } | |||
| } | |||
| return content; | |||
| }, [derivedMessages]); | |||
| return ( | |||
| <Modal | |||
| open={isOpen} | |||
| onCancel={onClose} | |||
| showfooter={false} | |||
| footer={null} | |||
| title={derivedMessages?.length ? derivedMessages[0]?.content : ''} | |||
| title={shortMessage || ''} | |||
| className="!w-[900px]" | |||
| > | |||
| <div className="flex items-start mb-4 flex-col gap-4 justify-start"> | |||
| @@ -3,8 +3,11 @@ import { NextMessageInput } from '@/components/message-input/next'; | |||
| import MessageItem from '@/components/next-message-item'; | |||
| import PdfDrawer from '@/components/pdf-drawer'; | |||
| import { useClickDrawer } from '@/components/pdf-drawer/hooks'; | |||
| import { RAGFlowAvatar } from '@/components/ragflow-avatar'; | |||
| import { useSwitchToDarkThemeOnMount } from '@/components/theme-provider'; | |||
| import { Button } from '@/components/ui/button'; | |||
| import { MessageType } from '@/constants/chat'; | |||
| import { useFetchAppConf } from '@/hooks/logic-hooks'; | |||
| import { | |||
| useFetchExternalAgentInputs, | |||
| useUploadCanvasFileWithProgress, | |||
| @@ -12,10 +15,12 @@ import { | |||
| import { cn } from '@/lib/utils'; | |||
| import i18n from '@/locales/config'; | |||
| import { useCacheChatLog } from '@/pages/agent/hooks/use-cache-chat-log'; | |||
| import { IInputs } from '@/pages/agent/interface'; | |||
| import { useSendButtonDisabled } from '@/pages/chat/hooks'; | |||
| import { buildMessageUuidWithRole } from '@/utils/chat'; | |||
| import { isEmpty } from 'lodash'; | |||
| import React, { forwardRef, useCallback } from 'react'; | |||
| import { RefreshCcw } from 'lucide-react'; | |||
| import React, { forwardRef, useCallback, useState } from 'react'; | |||
| import { | |||
| useGetSharedChatSearchParams, | |||
| useSendNextSharedMessage, | |||
| @@ -38,6 +43,7 @@ const ChatContainer = () => { | |||
| addEventList, | |||
| setCurrentMessageId, | |||
| currentEventListWithoutMessageById, | |||
| clearEventList, | |||
| } = useCacheChatLog(); | |||
| const { | |||
| handlePressEnter, | |||
| @@ -51,26 +57,20 @@ const ChatContainer = () => { | |||
| findReferenceByMessageId, | |||
| appendUploadResponseList, | |||
| parameterDialogVisible, | |||
| hideParameterDialog, | |||
| showParameterDialog, | |||
| ok, | |||
| resetSession, | |||
| } = useSendNextSharedMessage(addEventList); | |||
| const { data } = useFetchExternalAgentInputs(); | |||
| // const { data } = useFetchExternalAgentInputs(); | |||
| const sendDisabled = useSendButtonDisabled(value); | |||
| // useEffect(() => { | |||
| // if (derivedMessages.length) { | |||
| // const derivedMessagesFilter = derivedMessages.filter( | |||
| // (message) => message.role === MessageType.Assistant, | |||
| // ); | |||
| // if (derivedMessagesFilter.length) { | |||
| // const message = derivedMessagesFilter[derivedMessagesFilter.length - 1]; | |||
| // setCurrentMessageId(message.id); | |||
| // } | |||
| // } | |||
| // }, [derivedMessages, setCurrentMessageId]); | |||
| const appConf = useFetchAppConf(); | |||
| const { data: inputsData } = useFetchExternalAgentInputs(); | |||
| const [agentInfo, setAgentInfo] = useState<IInputs>({ | |||
| avatar: '', | |||
| title: '', | |||
| inputs: {}, | |||
| }); | |||
| const handleUploadFile: NonNullable<FileUploadProps['onUpload']> = | |||
| useCallback( | |||
| async (files, options) => { | |||
| @@ -87,20 +87,62 @@ const ChatContainer = () => { | |||
| }, [locale, visibleAvatar]); | |||
| React.useEffect(() => { | |||
| if (!isEmpty(data)) { | |||
| const { avatar, title, inputs } = inputsData; | |||
| setAgentInfo({ | |||
| avatar, | |||
| title, | |||
| inputs: inputs, | |||
| }); | |||
| }, [inputsData, setAgentInfo]); | |||
| React.useEffect(() => { | |||
| if (!isEmpty(inputsData)) { | |||
| showParameterDialog(); | |||
| } | |||
| }, [data, showParameterDialog]); | |||
| }, [inputsData, showParameterDialog]); | |||
| useSwitchToDarkThemeOnMount(); | |||
| const handleInputsModalOk = (params: any[]) => { | |||
| ok(params); | |||
| }; | |||
| const handleReset = () => { | |||
| resetSession(); | |||
| clearEventList(); | |||
| }; | |||
| if (!conversationId) { | |||
| return <div>empty</div>; | |||
| } | |||
| return ( | |||
| <section className="h-[100vh] flex justify-center items-center"> | |||
| <div className=" w-[80vw]"> | |||
| <div className="flex flex-1 flex-col p-2.5 h-[90vh] border rounded-lg"> | |||
| <div className="w-40 flex gap-2 absolute left-3 top-12 items-center"> | |||
| <img src="/logo.svg" alt="" /> | |||
| <span className="text-2xl font-bold">{appConf.appName}</span> | |||
| </div> | |||
| <div className=" w-[80vw] border rounded-lg"> | |||
| <div className="flex justify-between items-center border-b p-3"> | |||
| <div className="flex gap-2 items-center"> | |||
| <RAGFlowAvatar | |||
| avatar={agentInfo.avatar} | |||
| name={agentInfo.title} | |||
| isPerson | |||
| /> | |||
| <div className="text-xl text-foreground">{agentInfo.title}</div> | |||
| </div> | |||
| <Button | |||
| variant={'secondary'} | |||
| className="text-sm text-foreground cursor-pointer" | |||
| onClick={() => { | |||
| handleReset(); | |||
| }} | |||
| > | |||
| <div className="flex gap-1 items-center"> | |||
| <RefreshCcw size={14} /> | |||
| <span className="text-lg ">Reset</span> | |||
| </div> | |||
| </Button> | |||
| </div> | |||
| <div className="flex flex-1 flex-col p-2.5 h-[90vh] m-3"> | |||
| <div | |||
| className={cn('flex flex-1 flex-col overflow-auto m-auto w-5/6')} | |||
| > | |||
| @@ -123,6 +165,8 @@ const ChatContainer = () => { | |||
| sendLoading && | |||
| derivedMessages?.length - 1 === i | |||
| } | |||
| avatarDialog={agentInfo.avatar} | |||
| agentName={agentInfo.title} | |||
| index={i} | |||
| clickDocumentButton={clickDocumentButton} | |||
| showLikeButton={false} | |||
| @@ -164,8 +208,9 @@ const ChatContainer = () => { | |||
| )} | |||
| {parameterDialogVisible && ( | |||
| <ParameterDialog | |||
| hideModal={hideParameterDialog} | |||
| ok={ok} | |||
| // hideModal={hideParameterDialog} | |||
| ok={handleInputsModalOk} | |||
| data={agentInfo.inputs} | |||
| ></ParameterDialog> | |||
| )} | |||
| </section> | |||
| @@ -1,33 +1,30 @@ | |||
| import { | |||
| Dialog, | |||
| DialogContent, | |||
| DialogHeader, | |||
| DialogTitle, | |||
| } from '@/components/ui/dialog'; | |||
| import { useFetchExternalAgentInputs } from '@/hooks/use-agent-request'; | |||
| import { Modal } from '@/components/ui/modal'; | |||
| import { IModalProps } from '@/interfaces/common'; | |||
| import DebugContent from '@/pages/agent/debug-content'; | |||
| import { buildBeginInputListFromObject } from '@/pages/agent/form/begin-form/utils'; | |||
| import { BeginQuery } from '@/pages/agent/interface'; | |||
| interface IProps extends IModalProps<any> { | |||
| ok(parameters: any[]): void; | |||
| data: Record<string, Omit<BeginQuery, 'key'>>; | |||
| } | |||
| export function ParameterDialog({ hideModal, ok }: IProps) { | |||
| const { data } = useFetchExternalAgentInputs(); | |||
| export function ParameterDialog({ ok, data }: IProps) { | |||
| return ( | |||
| <Dialog open onOpenChange={hideModal}> | |||
| <DialogContent> | |||
| <DialogHeader> | |||
| <DialogTitle>Parameter</DialogTitle> | |||
| </DialogHeader> | |||
| <Modal | |||
| open | |||
| title={'Parameter'} | |||
| closable={false} | |||
| showfooter={false} | |||
| maskClosable={false} | |||
| > | |||
| <div className="mb-8"> | |||
| <DebugContent | |||
| parameters={buildBeginInputListFromObject(data)} | |||
| ok={ok} | |||
| isNext={false} | |||
| btnText={'Submit'} | |||
| ></DebugContent> | |||
| </DialogContent> | |||
| </Dialog> | |||
| </div> | |||
| </Modal> | |||
| ); | |||
| } | |||