Fix: Fix share-chat bugs (#9150)

### 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)
This commit is contained in:
chanx
2025-08-01 12:38:29 +08:00
committed by GitHub
parent 5ccdb95008
commit ac53ef6216
10 changed files with 143 additions and 57 deletions

View File

@ -44,6 +44,7 @@ interface IProps
nickname?: string; nickname?: string;
avatar?: string; avatar?: string;
avatarDialog?: string | null; avatarDialog?: string | null;
agentName?: string;
clickDocumentButton?: (documentId: string, chunk: IReferenceChunk) => void; clickDocumentButton?: (documentId: string, chunk: IReferenceChunk) => void;
index: number; index: number;
showLikeButton?: boolean; showLikeButton?: boolean;
@ -60,6 +61,7 @@ function MessageItem({
loading = false, loading = false,
avatar, avatar,
avatarDialog, avatarDialog,
agentName,
sendLoading = false, sendLoading = false,
clickDocumentButton, clickDocumentButton,
removeMessageById, removeMessageById,
@ -120,8 +122,8 @@ function MessageItem({
{visibleAvatar && {visibleAvatar &&
(item.role === MessageType.User ? ( (item.role === MessageType.User ? (
<RAGFlowAvatar avatar={avatar ?? '/logo.svg'} /> <RAGFlowAvatar avatar={avatar ?? '/logo.svg'} />
) : avatarDialog ? ( ) : avatarDialog || agentName ? (
<RAGFlowAvatar avatar={avatarDialog} /> <RAGFlowAvatar avatar={avatarDialog} name={agentName} isPerson />
) : ( ) : (
<AssistantIcon /> <AssistantIcon />
))} ))}

View File

@ -487,6 +487,10 @@ export const useSelectDerivedMessages = () => {
[setDerivedMessages], [setDerivedMessages],
); );
const removeAllMessages = useCallback(() => {
setDerivedMessages([]);
}, [setDerivedMessages]);
return { return {
ref, ref,
derivedMessages, derivedMessages,
@ -498,6 +502,7 @@ export const useSelectDerivedMessages = () => {
addNewestOneQuestion, addNewestOneQuestion,
addNewestOneAnswer, addNewestOneAnswer,
removeMessagesAfterCurrentMessage, removeMessagesAfterCurrentMessage,
removeAllMessages,
}; };
}; };

View File

@ -10,7 +10,7 @@ import { DSL, IFlow, IFlowTemplate } from '@/interfaces/database/flow';
import { IDebugSingleRequestBody } from '@/interfaces/request/agent'; import { IDebugSingleRequestBody } from '@/interfaces/request/agent';
import i18n from '@/locales/config'; import i18n from '@/locales/config';
import { BeginId } from '@/pages/agent/constant'; 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 { useGetSharedChatSearchParams } from '@/pages/chat/shared-hooks';
import agentService, { import agentService, {
fetchAgentLogsByCanvasId, fetchAgentLogsByCanvasId,
@ -596,9 +596,9 @@ export const useFetchExternalAgentInputs = () => {
data, data,
isFetching: loading, isFetching: loading,
refetch, refetch,
} = useQuery<Record<string, BeginQuery>>({ } = useQuery<IInputs>({
queryKey: [AgentApiAction.FetchExternalAgentInputs], queryKey: [AgentApiAction.FetchExternalAgentInputs],
initialData: {} as Record<string, BeginQuery>, initialData: {} as IInputs,
refetchOnReconnect: false, refetchOnReconnect: false,
refetchOnMount: false, refetchOnMount: false,
refetchOnWindowFocus: false, refetchOnWindowFocus: false,

View File

@ -182,9 +182,8 @@ export const useSendAgentMessage = (
const { handleInputChange, value, setValue } = useHandleMessageInputChange(); const { handleInputChange, value, setValue } = useHandleMessageInputChange();
const inputs = useSelectBeginNodeDataInputs(); const inputs = useSelectBeginNodeDataInputs();
const [sessionId, setSessionId] = useState<string | null>(null); const [sessionId, setSessionId] = useState<string | null>(null);
const { send, answerList, done, stopOutputMessage } = useSendMessageBySSE( const { send, answerList, done, stopOutputMessage, resetAnswerList } =
url || api.runCanvas, useSendMessageBySSE(url || api.runCanvas);
);
const messageId = useMemo(() => { const messageId = useMemo(() => {
return answerList[0]?.message_id; return answerList[0]?.message_id;
}, [answerList]); }, [answerList]);
@ -204,6 +203,7 @@ export const useSendAgentMessage = (
removeMessageById, removeMessageById,
addNewestOneQuestion, addNewestOneQuestion,
addNewestOneAnswer, addNewestOneAnswer,
removeAllMessages,
} = useSelectDerivedMessages(); } = useSelectDerivedMessages();
const { addEventList: addEventListFun } = useContext(AgentChatLogContext); const { addEventList: addEventListFun } = useContext(AgentChatLogContext);
const { const {
@ -280,6 +280,14 @@ export const useSendAgentMessage = (
[addNewestOneQuestion, send], [addNewestOneQuestion, send],
); );
// reset session
const resetSession = useCallback(() => {
stopOutputMessage();
resetAnswerList();
setSessionId(null);
removeAllMessages();
}, [resetAnswerList, removeAllMessages, stopOutputMessage]);
const handlePressEnter = useCallback(() => { const handlePressEnter = useCallback(() => {
if (trim(value) === '') return; if (trim(value) === '') return;
const id = uuid(); const id = uuid();
@ -336,6 +344,7 @@ export const useSendAgentMessage = (
stopOutputMessage, stopOutputMessage,
send, send,
sendFormMessage, sendFormMessage,
resetSession,
findReferenceByMessageId, findReferenceByMessageId,
appendUploadResponseList, appendUploadResponseList,
}; };

View File

@ -237,14 +237,16 @@ const DebugContent = ({
{parameters.map((x, idx) => { {parameters.map((x, idx) => {
return <div key={idx}>{renderWidget(x, idx.toString())}</div>; return <div key={idx}>{renderWidget(x, idx.toString())}</div>;
})} })}
<ButtonLoading <div>
type="submit" <ButtonLoading
loading={loading} type="submit"
disabled={!submittable || submitButtonDisabled} loading={loading}
className="w-full" disabled={!submittable || submitButtonDisabled}
> className="w-full mt-8"
{btnText || t(isNext ? 'common.next' : 'flow.run')} >
</ButtonLoading> {btnText || t(isNext ? 'common.next' : 'flow.run')}
</ButtonLoading>
</div>
</form> </form>
</Form> </Form>
</section> </section>

View File

@ -41,6 +41,7 @@ export function useCacheChatLog() {
const clearEventList = useCallback(() => { const clearEventList = useCallback(() => {
setEventList([]); setEventList([]);
setMessageIdPool({});
}, []); }, []);
const addEventList = useCallback((events: IEventList, message_id: string) => { const addEventList = useCallback((events: IEventList, message_id: string) => {

View File

@ -33,3 +33,9 @@ export interface BeginQuery {
name: string; name: string;
options: (number | string | boolean)[]; options: (number | string | boolean)[];
} }
export type IInputs = {
avatar: string;
title: string;
inputs: Record<string, BeginQuery>;
};

View File

@ -5,7 +5,7 @@ import { useFetchUserInfo } from '@/hooks/user-setting-hooks';
import { IAgentLogMessage } from '@/interfaces/database/agent'; import { IAgentLogMessage } from '@/interfaces/database/agent';
import { IReferenceObject, Message } from '@/interfaces/database/chat'; import { IReferenceObject, Message } from '@/interfaces/database/chat';
import { buildMessageUuidWithRole } from '@/utils/chat'; import { buildMessageUuidWithRole } from '@/utils/chat';
import React from 'react'; import React, { useMemo } from 'react';
import { IMessage } from '../chat/interface'; import { IMessage } from '../chat/interface';
interface CustomModalProps { interface CustomModalProps {
@ -23,13 +23,32 @@ export const AgentLogDetailModal: React.FC<CustomModalProps> = ({
}) => { }) => {
const { data: userInfo } = useFetchUserInfo(); const { data: userInfo } = useFetchUserInfo();
const { data: canvasInfo } = useFetchAgent(); 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 ( return (
<Modal <Modal
open={isOpen} open={isOpen}
onCancel={onClose} onCancel={onClose}
showfooter={false} showfooter={false}
footer={null} footer={null}
title={derivedMessages?.length ? derivedMessages[0]?.content : ''} title={shortMessage || ''}
className="!w-[900px]" className="!w-[900px]"
> >
<div className="flex items-start mb-4 flex-col gap-4 justify-start"> <div className="flex items-start mb-4 flex-col gap-4 justify-start">

View File

@ -3,8 +3,11 @@ import { NextMessageInput } from '@/components/message-input/next';
import MessageItem from '@/components/next-message-item'; import MessageItem from '@/components/next-message-item';
import PdfDrawer from '@/components/pdf-drawer'; import PdfDrawer from '@/components/pdf-drawer';
import { useClickDrawer } from '@/components/pdf-drawer/hooks'; import { useClickDrawer } from '@/components/pdf-drawer/hooks';
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
import { useSwitchToDarkThemeOnMount } from '@/components/theme-provider'; import { useSwitchToDarkThemeOnMount } from '@/components/theme-provider';
import { Button } from '@/components/ui/button';
import { MessageType } from '@/constants/chat'; import { MessageType } from '@/constants/chat';
import { useFetchAppConf } from '@/hooks/logic-hooks';
import { import {
useFetchExternalAgentInputs, useFetchExternalAgentInputs,
useUploadCanvasFileWithProgress, useUploadCanvasFileWithProgress,
@ -12,10 +15,12 @@ import {
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import i18n from '@/locales/config'; import i18n from '@/locales/config';
import { useCacheChatLog } from '@/pages/agent/hooks/use-cache-chat-log'; import { useCacheChatLog } from '@/pages/agent/hooks/use-cache-chat-log';
import { IInputs } from '@/pages/agent/interface';
import { useSendButtonDisabled } from '@/pages/chat/hooks'; import { useSendButtonDisabled } from '@/pages/chat/hooks';
import { buildMessageUuidWithRole } from '@/utils/chat'; import { buildMessageUuidWithRole } from '@/utils/chat';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import React, { forwardRef, useCallback } from 'react'; import { RefreshCcw } from 'lucide-react';
import React, { forwardRef, useCallback, useState } from 'react';
import { import {
useGetSharedChatSearchParams, useGetSharedChatSearchParams,
useSendNextSharedMessage, useSendNextSharedMessage,
@ -38,6 +43,7 @@ const ChatContainer = () => {
addEventList, addEventList,
setCurrentMessageId, setCurrentMessageId,
currentEventListWithoutMessageById, currentEventListWithoutMessageById,
clearEventList,
} = useCacheChatLog(); } = useCacheChatLog();
const { const {
handlePressEnter, handlePressEnter,
@ -51,26 +57,20 @@ const ChatContainer = () => {
findReferenceByMessageId, findReferenceByMessageId,
appendUploadResponseList, appendUploadResponseList,
parameterDialogVisible, parameterDialogVisible,
hideParameterDialog,
showParameterDialog, showParameterDialog,
ok, ok,
resetSession,
} = useSendNextSharedMessage(addEventList); } = useSendNextSharedMessage(addEventList);
const { data } = useFetchExternalAgentInputs(); // const { data } = useFetchExternalAgentInputs();
const sendDisabled = useSendButtonDisabled(value); const sendDisabled = useSendButtonDisabled(value);
const appConf = useFetchAppConf();
// useEffect(() => { const { data: inputsData } = useFetchExternalAgentInputs();
// if (derivedMessages.length) { const [agentInfo, setAgentInfo] = useState<IInputs>({
// const derivedMessagesFilter = derivedMessages.filter( avatar: '',
// (message) => message.role === MessageType.Assistant, title: '',
// ); inputs: {},
// if (derivedMessagesFilter.length) { });
// const message = derivedMessagesFilter[derivedMessagesFilter.length - 1];
// setCurrentMessageId(message.id);
// }
// }
// }, [derivedMessages, setCurrentMessageId]);
const handleUploadFile: NonNullable<FileUploadProps['onUpload']> = const handleUploadFile: NonNullable<FileUploadProps['onUpload']> =
useCallback( useCallback(
async (files, options) => { async (files, options) => {
@ -87,20 +87,62 @@ const ChatContainer = () => {
}, [locale, visibleAvatar]); }, [locale, visibleAvatar]);
React.useEffect(() => { React.useEffect(() => {
if (!isEmpty(data)) { const { avatar, title, inputs } = inputsData;
setAgentInfo({
avatar,
title,
inputs: inputs,
});
}, [inputsData, setAgentInfo]);
React.useEffect(() => {
if (!isEmpty(inputsData)) {
showParameterDialog(); showParameterDialog();
} }
}, [data, showParameterDialog]); }, [inputsData, showParameterDialog]);
useSwitchToDarkThemeOnMount(); useSwitchToDarkThemeOnMount();
const handleInputsModalOk = (params: any[]) => {
ok(params);
};
const handleReset = () => {
resetSession();
clearEventList();
};
if (!conversationId) { if (!conversationId) {
return <div>empty</div>; return <div>empty</div>;
} }
return ( return (
<section className="h-[100vh] flex justify-center items-center"> <section className="h-[100vh] flex justify-center items-center">
<div className=" w-[80vw]"> <div className="w-40 flex gap-2 absolute left-3 top-12 items-center">
<div className="flex flex-1 flex-col p-2.5 h-[90vh] border rounded-lg"> <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 <div
className={cn('flex flex-1 flex-col overflow-auto m-auto w-5/6')} className={cn('flex flex-1 flex-col overflow-auto m-auto w-5/6')}
> >
@ -123,6 +165,8 @@ const ChatContainer = () => {
sendLoading && sendLoading &&
derivedMessages?.length - 1 === i derivedMessages?.length - 1 === i
} }
avatarDialog={agentInfo.avatar}
agentName={agentInfo.title}
index={i} index={i}
clickDocumentButton={clickDocumentButton} clickDocumentButton={clickDocumentButton}
showLikeButton={false} showLikeButton={false}
@ -164,8 +208,9 @@ const ChatContainer = () => {
)} )}
{parameterDialogVisible && ( {parameterDialogVisible && (
<ParameterDialog <ParameterDialog
hideModal={hideParameterDialog} // hideModal={hideParameterDialog}
ok={ok} ok={handleInputsModalOk}
data={agentInfo.inputs}
></ParameterDialog> ></ParameterDialog>
)} )}
</section> </section>

View File

@ -1,33 +1,30 @@
import { import { Modal } from '@/components/ui/modal';
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { useFetchExternalAgentInputs } from '@/hooks/use-agent-request';
import { IModalProps } from '@/interfaces/common'; import { IModalProps } from '@/interfaces/common';
import DebugContent from '@/pages/agent/debug-content'; import DebugContent from '@/pages/agent/debug-content';
import { buildBeginInputListFromObject } from '@/pages/agent/form/begin-form/utils'; import { buildBeginInputListFromObject } from '@/pages/agent/form/begin-form/utils';
import { BeginQuery } from '@/pages/agent/interface';
interface IProps extends IModalProps<any> { interface IProps extends IModalProps<any> {
ok(parameters: any[]): void; ok(parameters: any[]): void;
data: Record<string, Omit<BeginQuery, 'key'>>;
} }
export function ParameterDialog({ hideModal, ok }: IProps) { export function ParameterDialog({ ok, data }: IProps) {
const { data } = useFetchExternalAgentInputs();
return ( return (
<Dialog open onOpenChange={hideModal}> <Modal
<DialogContent> open
<DialogHeader> title={'Parameter'}
<DialogTitle>Parameter</DialogTitle> closable={false}
</DialogHeader> showfooter={false}
maskClosable={false}
>
<div className="mb-8">
<DebugContent <DebugContent
parameters={buildBeginInputListFromObject(data)} parameters={buildBeginInputListFromObject(data)}
ok={ok} ok={ok}
isNext={false} isNext={false}
btnText={'Submit'} btnText={'Submit'}
></DebugContent> ></DebugContent>
</DialogContent> </div>
</Dialog> </Modal>
); );
} }