Feat: Share agent dialog box externally #3221 (#9005)

### What problem does this PR solve?

Feat: Share agent dialog box externally #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-07-23 18:10:18 +08:00
committed by GitHub
parent 8345e92671
commit 5f0ec005ba
22 changed files with 351 additions and 431 deletions

View File

@ -1,8 +1,7 @@
import { MessageType } from '@/constants/chat';
import { useGetFileIcon } from '@/pages/chat/hooks';
import { Spin } from 'antd';
import { useSendNextMessage } from './hooks';
import { useSendAgentMessage } from './use-send-agent-message';
import MessageInput from '@/components/message-input';
import MessageItem from '@/components/next-message-item';
@ -25,13 +24,12 @@ const AgentChatBox = () => {
handleInputChange,
handlePressEnter,
value,
loading,
ref,
derivedMessages,
stopOutputMessage,
sendFormMessage,
findReferenceByMessageId,
} = useSendNextMessage();
} = useSendAgentMessage();
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
useClickDrawer();
@ -73,36 +71,36 @@ const AgentChatBox = () => {
<section className="flex flex-1 flex-col px-5 h-[90vh]">
<div className="flex-1 overflow-auto">
<div>
<Spin spinning={loading}>
{derivedMessages?.map((message, i) => {
return (
<MessageItem
loading={
message.role === MessageType.Assistant &&
sendLoading &&
derivedMessages.length - 1 === i
}
key={buildMessageUuidWithRole(message)}
nickname={userInfo.nickname}
avatar={userInfo.avatar}
avatarDialog={canvasInfo.avatar}
item={message}
reference={findReferenceByMessageId(message.id)}
clickDocumentButton={clickDocumentButton}
index={i}
showLikeButton={false}
sendLoading={sendLoading}
>
<DebugContent
parameters={buildInputList(message)}
ok={handleOk(message)}
isNext={false}
btnText={'Submit'}
></DebugContent>
</MessageItem>
);
})}
</Spin>
{/* <Spin spinning={sendLoading}> */}
{derivedMessages?.map((message, i) => {
return (
<MessageItem
loading={
message.role === MessageType.Assistant &&
sendLoading &&
derivedMessages.length - 1 === i
}
key={buildMessageUuidWithRole(message)}
nickname={userInfo.nickname}
avatar={userInfo.avatar}
avatarDialog={canvasInfo.avatar}
item={message}
reference={findReferenceByMessageId(message.id)}
clickDocumentButton={clickDocumentButton}
index={i}
showLikeButton={false}
sendLoading={sendLoading}
>
<DebugContent
parameters={buildInputList(message)}
ok={handleOk(message)}
isNext={false}
btnText={'Submit'}
></DebugContent>
</MessageItem>
);
})}
{/* </Spin> */}
</div>
<div ref={ref} />
</div>

View File

@ -4,7 +4,6 @@ import {
useHandleMessageInputChange,
useSelectDerivedMessages,
} from '@/hooks/logic-hooks';
import { useFetchAgent } from '@/hooks/use-agent-request';
import {
IEventList,
IInputEvent,
@ -30,37 +29,7 @@ import { BeginQuery } from '../interface';
import useGraphStore from '../store';
import { receiveMessageError } from '../utils';
export const useSelectNextMessages = () => {
const { data: flowDetail, loading } = useFetchAgent();
const reference = flowDetail.dsl.retrieval;
const {
derivedMessages,
ref,
addNewestQuestion,
addNewestAnswer,
removeLatestMessage,
removeMessageById,
removeMessagesAfterCurrentMessage,
addNewestOneQuestion,
addNewestOneAnswer,
} = useSelectDerivedMessages();
return {
reference,
loading,
derivedMessages,
ref,
addNewestQuestion,
addNewestAnswer,
removeLatestMessage,
removeMessageById,
addNewestOneQuestion,
addNewestOneAnswer,
removeMessagesAfterCurrentMessage,
};
};
function findMessageFromList(eventList: IEventList) {
export function findMessageFromList(eventList: IEventList) {
const messageEventList = eventList.filter(
(x) => x.event === MessageEventType.Message,
) as IMessageEvent[];
@ -101,7 +70,7 @@ function findMessageFromList(eventList: IEventList) {
};
}
function findInputFromList(eventList: IEventList) {
export function findInputFromList(eventList: IEventList) {
const inputEvent = eventList.find(
(x) => x.event === MessageEventType.UserInputs,
) as IInputEvent;
@ -120,7 +89,7 @@ export function getLatestError(eventList: IEventList) {
return get(eventList.at(-1), 'data.outputs._ERROR');
}
const useGetBeginNodePrologue = () => {
export const useGetBeginNodePrologue = () => {
const getNode = useGraphStore((state) => state.getNode);
return useMemo(() => {
@ -131,31 +100,61 @@ const useGetBeginNodePrologue = () => {
}, [getNode]);
};
export const useSendNextMessage = () => {
export function useFindMessageReference(answerList: IEventList) {
const [messageEndEventList, setMessageEndEventList] = useState<
IMessageEndEvent[]
>([]);
const findReferenceByMessageId = useCallback(
(messageId: string) => {
const event = messageEndEventList.find(
(item) => item.message_id === messageId,
);
if (event) {
return (event?.data as IMessageEndData)?.reference;
}
},
[messageEndEventList],
);
useEffect(() => {
const messageEndEvent = answerList.find(
(x) => x.event === MessageEventType.MessageEnd,
);
if (messageEndEvent) {
setMessageEndEventList((list) => {
const nextList = [...list];
if (
nextList.every((x) => x.message_id !== messageEndEvent.message_id)
) {
nextList.push(messageEndEvent as IMessageEndEvent);
}
return nextList;
});
}
}, [answerList]);
return { findReferenceByMessageId };
}
export const useSendAgentMessage = (url?: string) => {
const { id: agentId } = useParams();
const { handleInputChange, value, setValue } = useHandleMessageInputChange();
const inputs = useSelectBeginNodeDataInputs();
const { send, answerList, done, stopOutputMessage } = useSendMessageBySSE(
url || api.runCanvas,
);
const { findReferenceByMessageId } = useFindMessageReference(answerList);
const prologue = useGetBeginNodePrologue();
const {
reference,
loading,
derivedMessages,
ref,
removeLatestMessage,
removeMessageById,
addNewestOneQuestion,
addNewestOneAnswer,
} = useSelectNextMessages();
const { id: agentId } = useParams();
const { handleInputChange, value, setValue } = useHandleMessageInputChange();
const { refetch } = useFetchAgent();
} = useSelectDerivedMessages();
const { addEventList } = useContext(AgentChatLogContext);
const inputs = useSelectBeginNodeDataInputs();
const [messageEndEventList, setMessageEndEventList] = useState<
IMessageEndEvent[]
>([]);
const { send, answerList, done, stopOutputMessage } = useSendMessageBySSE(
api.runCanvas,
);
const prologue = useGetBeginNodePrologue();
const sendMessage = useCallback(
async ({ message }: { message: Message; messages?: Message[] }) => {
@ -182,62 +181,12 @@ export const useSendNextMessage = () => {
setValue(message.content);
removeLatestMessage();
} else {
refetch(); // pull the message list after sending the message successfully
// refetch(); // pull the message list after sending the message successfully
}
},
[agentId, send, inputs, setValue, removeLatestMessage, refetch],
[agentId, send, inputs, setValue, removeLatestMessage],
);
const handleSendMessage = useCallback(
async (message: Message) => {
sendMessage({ message });
},
[sendMessage],
);
useEffect(() => {
const messageEndEvent = answerList.find(
(x) => x.event === MessageEventType.MessageEnd,
);
if (messageEndEvent) {
setMessageEndEventList((list) => {
const nextList = [...list];
if (
nextList.every((x) => x.message_id !== messageEndEvent.message_id)
) {
nextList.push(messageEndEvent as IMessageEndEvent);
}
return nextList;
});
}
}, [addEventList.length, answerList]);
useEffect(() => {
const { content, id } = findMessageFromList(answerList);
const inputAnswer = findInputFromList(answerList);
if (answerList.length > 0) {
addNewestOneAnswer({
answer: content || getLatestError(answerList),
id: id,
...inputAnswer,
});
}
}, [answerList, addNewestOneAnswer]);
const handlePressEnter = useCallback(() => {
if (trim(value) === '') return;
const id = uuid();
if (done) {
setValue('');
handleSendMessage({ id, content: value.trim(), role: MessageType.User });
}
addNewestOneQuestion({
content: value,
id,
role: MessageType.User,
});
}, [value, done, addNewestOneQuestion, setValue, handleSendMessage]);
const sendFormMessage = useCallback(
(body: { id?: string; inputs: Record<string, BeginQuery> }) => {
send(body);
@ -251,17 +200,33 @@ export const useSendNextMessage = () => {
[addNewestOneQuestion, send],
);
const findReferenceByMessageId = useCallback(
(messageId: string) => {
const event = messageEndEventList.find(
(item) => item.message_id === messageId,
);
if (event) {
return (event?.data as IMessageEndData)?.reference;
}
},
[messageEndEventList],
);
const handlePressEnter = useCallback(() => {
if (trim(value) === '') return;
const id = uuid();
if (done) {
setValue('');
sendMessage({
message: { id, content: value.trim(), role: MessageType.User },
});
}
addNewestOneQuestion({
content: value,
id,
role: MessageType.User,
});
}, [value, done, addNewestOneQuestion, setValue, sendMessage]);
useEffect(() => {
const { content, id } = findMessageFromList(answerList);
const inputAnswer = findInputFromList(answerList);
if (answerList.length > 0) {
addNewestOneAnswer({
answer: content || getLatestError(answerList),
id: id,
...inputAnswer,
});
}
}, [answerList, addNewestOneAnswer]);
useEffect(() => {
if (prologue) {
@ -272,7 +237,9 @@ export const useSendNextMessage = () => {
}, [addNewestOneAnswer, agentId, prologue, send, sendFormMessage]);
useEffect(() => {
addEventList(answerList);
if (typeof addEventList === 'function') {
addEventList(answerList);
}
}, [addEventList, answerList]);
return {
@ -280,8 +247,6 @@ export const useSendNextMessage = () => {
handleInputChange,
value,
sendLoading: !done,
reference,
loading,
derivedMessages,
ref,
removeMessageById,