The agent directly outputs the results under the task model #9745 (#9746)

### What problem does this PR solve?

The agent directly outputs the results under the task model #9745

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-08-28 11:43:40 +08:00
committed by GitHub
parent 2d101561f8
commit 7332f1d0f3
6 changed files with 153 additions and 73 deletions

View File

@ -18,6 +18,7 @@ import { memo, useCallback } from 'react';
import { useParams } from 'umi'; import { useParams } from 'umi';
import DebugContent from '../debug-content'; import DebugContent from '../debug-content';
import { useAwaitCompentData } from '../hooks/use-chat-logic'; import { useAwaitCompentData } from '../hooks/use-chat-logic';
import { useIsTaskMode } from '../hooks/use-get-begin-query';
function AgentChatBox() { function AgentChatBox() {
const { const {
@ -48,6 +49,8 @@ function AgentChatBox() {
canvasId: canvasId as string, canvasId: canvasId as string,
}); });
const isTaskMode = useIsTaskMode();
const handleUploadFile: NonNullable<FileUploadProps['onUpload']> = const handleUploadFile: NonNullable<FileUploadProps['onUpload']> =
useCallback( useCallback(
async (files, options) => { async (files, options) => {
@ -109,18 +112,20 @@ function AgentChatBox() {
</div> </div>
<div ref={scrollRef} /> <div ref={scrollRef} />
</div> </div>
<NextMessageInput {isTaskMode || (
value={value} <NextMessageInput
sendLoading={sendLoading} value={value}
disabled={isWaitting} sendLoading={sendLoading}
sendDisabled={sendLoading || isWaitting} disabled={isWaitting}
isUploading={loading || isWaitting} sendDisabled={sendLoading || isWaitting}
onPressEnter={handlePressEnter} isUploading={loading || isWaitting}
onInputChange={handleInputChange} onPressEnter={handlePressEnter}
stopOutputMessage={stopOutputMessage} onInputChange={handleInputChange}
onUpload={handleUploadFile} stopOutputMessage={stopOutputMessage}
conversationId="" onUpload={handleUploadFile}
/> conversationId=""
/>
)}
</section> </section>
<PdfDrawer <PdfDrawer
visible={visible} visible={visible}

View File

@ -18,13 +18,23 @@ import i18n from '@/locales/config';
import api from '@/utils/api'; import api from '@/utils/api';
import { get } from 'lodash'; import { get } from 'lodash';
import trim from 'lodash/trim'; import trim from 'lodash/trim';
import { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import {
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { useParams } from 'umi'; import { useParams } from 'umi';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { BeginId } from '../constant'; import { BeginId } from '../constant';
import { AgentChatLogContext } from '../context'; import { AgentChatLogContext } from '../context';
import { transferInputsArrayToObject } from '../form/begin-form/use-watch-change'; import { transferInputsArrayToObject } from '../form/begin-form/use-watch-change';
import { useSelectBeginNodeDataInputs } from '../hooks/use-get-begin-query'; import {
useIsTaskMode,
useSelectBeginNodeDataInputs,
} from '../hooks/use-get-begin-query';
import { BeginQuery } from '../interface'; import { BeginQuery } from '../interface';
import useGraphStore from '../store'; import useGraphStore from '../store';
import { receiveMessageError } from '../utils'; import { receiveMessageError } from '../utils';
@ -173,10 +183,22 @@ export function useSetUploadResponseData() {
}; };
} }
export const buildRequestBody = (value: string = '') => {
const id = uuid();
const msgBody = {
id,
content: value.trim(),
role: MessageType.User,
};
return msgBody;
};
export const useSendAgentMessage = ( export const useSendAgentMessage = (
url?: string, url?: string,
addEventList?: (data: IEventList, messageId: string) => void, addEventList?: (data: IEventList, messageId: string) => void,
beginParams?: any[], beginParams?: any[],
isShared?: boolean,
) => { ) => {
const { id: agentId } = useParams(); const { id: agentId } = useParams();
const { handleInputChange, value, setValue } = useHandleMessageInputChange(); const { handleInputChange, value, setValue } = useHandleMessageInputChange();
@ -188,7 +210,9 @@ export const useSendAgentMessage = (
return answerList[0]?.message_id; return answerList[0]?.message_id;
}, [answerList]); }, [answerList]);
// const { refetch } = useFetchAgent(); const isTaskMode = useIsTaskMode();
// const { refetch } = useFetchAgent(); // This will cause the shared page to also send a request
const { findReferenceByMessageId } = useFindMessageReference(answerList); const { findReferenceByMessageId } = useFindMessageReference(answerList);
const prologue = useGetBeginNodePrologue(); const prologue = useGetBeginNodePrologue();
@ -212,7 +236,14 @@ export const useSendAgentMessage = (
} = useSetUploadResponseData(); } = useSetUploadResponseData();
const sendMessage = useCallback( const sendMessage = useCallback(
async ({ message }: { message: Message; messages?: Message[] }) => { async ({
message,
beginInputs,
}: {
message: Message;
messages?: Message[];
beginInputs?: BeginQuery[];
}) => {
const params: Record<string, unknown> = { const params: Record<string, unknown> = {
id: agentId, id: agentId,
}; };
@ -220,13 +251,13 @@ export const useSendAgentMessage = (
params.running_hint_text = i18n.t('flow.runningHintText', { params.running_hint_text = i18n.t('flow.runningHintText', {
defaultValue: 'is running...🕞', defaultValue: 'is running...🕞',
}); });
if (message.content) { if (typeof message.content === 'string') {
const query = inputs; const query = inputs;
params.query = message.content; params.query = message.content;
// params.message_id = message.id; // params.message_id = message.id;
params.inputs = transferInputsArrayToObject( params.inputs = transferInputsArrayToObject(
beginParams ? beginParams : query, beginInputs || beginParams || query,
); // begin operator inputs ); // begin operator inputs
params.files = uploadResponseList; params.files = uploadResponseList;
@ -289,12 +320,7 @@ export const useSendAgentMessage = (
const handlePressEnter = useCallback(() => { const handlePressEnter = useCallback(() => {
if (trim(value) === '') return; if (trim(value) === '') return;
const id = uuid(); const msgBody = buildRequestBody(value);
const msgBody = {
id,
content: value.trim(),
role: MessageType.User,
};
if (done) { if (done) {
setValue(''); setValue('');
sendMessage({ sendMessage({
@ -315,6 +341,24 @@ export const useSendAgentMessage = (
scrollToBottom, scrollToBottom,
]); ]);
const sendedTaskMessage = useRef<boolean>(false);
const sendMessageInTaskMode = useCallback(() => {
if (isShared || !isTaskMode || sendedTaskMessage.current) {
return;
}
const msgBody = buildRequestBody('');
sendMessage({
message: msgBody,
});
sendedTaskMessage.current = true;
}, [isShared, isTaskMode, sendMessage]);
useEffect(() => {
sendMessageInTaskMode();
}, [sendMessageInTaskMode]);
useEffect(() => { useEffect(() => {
const { content, id } = findMessageFromList(answerList); const { content, id } = findMessageFromList(answerList);
const inputAnswer = findInputFromList(answerList); const inputAnswer = findInputFromList(answerList);
@ -328,12 +372,22 @@ export const useSendAgentMessage = (
}, [answerList, addNewestOneAnswer]); }, [answerList, addNewestOneAnswer]);
useEffect(() => { useEffect(() => {
if (isTaskMode) {
return;
}
if (prologue) { if (prologue) {
addNewestOneAnswer({ addNewestOneAnswer({
answer: prologue, answer: prologue,
}); });
} }
}, [addNewestOneAnswer, agentId, prologue, send, sendFormMessage]); }, [
addNewestOneAnswer,
agentId,
isTaskMode,
prologue,
send,
sendFormMessage,
]);
useEffect(() => { useEffect(() => {
if (typeof addEventList === 'function') { if (typeof addEventList === 'function') {
@ -365,5 +419,6 @@ export const useSendAgentMessage = (
findReferenceByMessageId, findReferenceByMessageId,
appendUploadResponseList, appendUploadResponseList,
addNewestOneAnswer, addNewestOneAnswer,
sendMessage,
}; };
}; };

View File

@ -7,7 +7,13 @@ import { t } from 'i18next';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import get from 'lodash/get'; import get from 'lodash/get';
import { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { BeginId, BeginQueryType, Operator, VariableType } from '../constant'; import {
AgentDialogueMode,
BeginId,
BeginQueryType,
Operator,
VariableType,
} from '../constant';
import { AgentFormContext } from '../context'; import { AgentFormContext } from '../context';
import { buildBeginInputListFromObject } from '../form/begin-form/utils'; import { buildBeginInputListFromObject } from '../form/begin-form/utils';
import { BeginQuery } from '../interface'; import { BeginQuery } from '../interface';
@ -21,6 +27,15 @@ export function useSelectBeginNodeDataInputs() {
); );
} }
export function useIsTaskMode() {
const getNode = useGraphStore((state) => state.getNode);
return useMemo(() => {
const node = getNode(BeginId);
return node?.data?.form?.mode === AgentDialogueMode.Task;
}, [getNode]);
}
export const useGetBeginNodeDataQuery = () => { export const useGetBeginNodeDataQuery = () => {
const getNode = useGraphStore((state) => state.getNode); const getNode = useGraphStore((state) => state.getNode);

View File

@ -1,7 +1,10 @@
import { SharedFrom } from '@/constants/chat'; import { SharedFrom } from '@/constants/chat';
import { useSetModalState } from '@/hooks/common-hooks'; import { useSetModalState } from '@/hooks/common-hooks';
import { IEventList } from '@/hooks/use-send-message'; import { IEventList } from '@/hooks/use-send-message';
import { useSendAgentMessage } from '@/pages/agent/chat/use-send-agent-message'; import {
buildRequestBody,
useSendAgentMessage,
} from '@/pages/agent/chat/use-send-agent-message';
import trim from 'lodash/trim'; import trim from 'lodash/trim';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import { useSearchParams } from 'umi'; import { useSearchParams } from 'umi';
@ -32,6 +35,7 @@ export const useGetSharedChatSearchParams = () => {
export const useSendNextSharedMessage = ( export const useSendNextSharedMessage = (
addEventList: (data: IEventList, messageId: string) => void, addEventList: (data: IEventList, messageId: string) => void,
isTaskMode: boolean,
) => { ) => {
const { from, sharedId: conversationId } = useGetSharedChatSearchParams(); const { from, sharedId: conversationId } = useGetSharedChatSearchParams();
const url = `/api/v1/${from === SharedFrom.Agent ? 'agentbots' : 'chatbots'}/${conversationId}/completions`; const url = `/api/v1/${from === SharedFrom.Agent ? 'agentbots' : 'chatbots'}/${conversationId}/completions`;
@ -44,14 +48,24 @@ export const useSendNextSharedMessage = (
showModal: showParameterDialog, showModal: showParameterDialog,
} = useSetModalState(); } = useSetModalState();
const ret = useSendAgentMessage(url, addEventList, params); const ret = useSendAgentMessage(url, addEventList, params, true);
const ok = useCallback( const ok = useCallback(
(params: any[]) => { (params: any[]) => {
setParams(params); if (isTaskMode) {
const msgBody = buildRequestBody('');
ret.sendMessage({
message: msgBody,
beginInputs: params,
});
} else {
setParams(params);
}
hideParameterDialog(); hideParameterDialog();
}, },
[hideParameterDialog], [hideParameterDialog, isTaskMode, ret],
); );
return { return {

View File

@ -39,4 +39,5 @@ export type IInputs = {
title: string; title: string;
inputs: Record<string, BeginQuery>; inputs: Record<string, BeginQuery>;
prologue: string; prologue: string;
mode: string;
}; };

View File

@ -14,11 +14,11 @@ import i18n from '@/locales/config';
import DebugContent from '@/pages/agent/debug-content'; import DebugContent from '@/pages/agent/debug-content';
import { useCacheChatLog } from '@/pages/agent/hooks/use-cache-chat-log'; import { useCacheChatLog } from '@/pages/agent/hooks/use-cache-chat-log';
import { useAwaitCompentData } from '@/pages/agent/hooks/use-chat-logic'; import { useAwaitCompentData } from '@/pages/agent/hooks/use-chat-logic';
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, useState } from 'react'; import React, { forwardRef, useCallback } from 'react';
import { AgentDialogueMode } from '../constant';
import { import {
useGetSharedChatSearchParams, useGetSharedChatSearchParams,
useSendNextSharedMessage, useSendNextSharedMessage,
@ -42,6 +42,10 @@ const ChatContainer = () => {
currentEventListWithoutMessageById, currentEventListWithoutMessageById,
clearEventList, clearEventList,
} = useCacheChatLog(); } = useCacheChatLog();
const { data: inputsData } = useFetchExternalAgentInputs();
const isTaskMode = inputsData.mode === AgentDialogueMode.Task;
const { const {
handlePressEnter, handlePressEnter,
handleInputChange, handleInputChange,
@ -60,20 +64,14 @@ const ChatContainer = () => {
addNewestOneAnswer, addNewestOneAnswer,
ok, ok,
resetSession, resetSession,
} = useSendNextSharedMessage(addEventList); } = useSendNextSharedMessage(addEventList, isTaskMode);
const { buildInputList, handleOk, isWaitting } = useAwaitCompentData({ const { buildInputList, handleOk, isWaitting } = useAwaitCompentData({
derivedMessages, derivedMessages,
sendFormMessage, sendFormMessage,
canvasId: conversationId as string, canvasId: conversationId as string,
}); });
const sendDisabled = useSendButtonDisabled(value); const sendDisabled = useSendButtonDisabled(value);
const { data: inputsData } = useFetchExternalAgentInputs();
const [agentInfo, setAgentInfo] = useState<IInputs>({
avatar: '',
title: '',
inputs: {},
prologue: '',
});
const handleUploadFile: NonNullable<FileUploadProps['onUpload']> = const handleUploadFile: NonNullable<FileUploadProps['onUpload']> =
useCallback( useCallback(
async (files, options) => { async (files, options) => {
@ -90,22 +88,12 @@ const ChatContainer = () => {
}, [locale, visibleAvatar]); }, [locale, visibleAvatar]);
React.useEffect(() => { React.useEffect(() => {
const { avatar, title, inputs } = inputsData; if (!isTaskMode && inputsData.prologue) {
setAgentInfo({
avatar,
title,
inputs: inputs,
prologue: '',
});
}, [inputsData, setAgentInfo]);
React.useEffect(() => {
if (inputsData.prologue) {
addNewestOneAnswer({ addNewestOneAnswer({
answer: inputsData.prologue, answer: inputsData.prologue,
}); });
} }
}, [inputsData.prologue, addNewestOneAnswer]); }, [inputsData.prologue, addNewestOneAnswer, isTaskMode]);
React.useEffect(() => { React.useEffect(() => {
if (inputsData && inputsData.inputs && !isEmpty(inputsData.inputs)) { if (inputsData && inputsData.inputs && !isEmpty(inputsData.inputs)) {
@ -126,8 +114,8 @@ const ChatContainer = () => {
return ( return (
<> <>
<EmbedContainer <EmbedContainer
title={agentInfo.title} title={inputsData.title}
avatar={agentInfo.avatar} avatar={inputsData.avatar}
handleReset={handleReset} handleReset={handleReset}
> >
<div className="flex flex-1 flex-col p-2.5 h-[90vh] m-3"> <div className="flex flex-1 flex-col p-2.5 h-[90vh] m-3">
@ -157,8 +145,8 @@ const ChatContainer = () => {
derivedMessages?.length - 1 === i derivedMessages?.length - 1 === i
} }
isShare={true} isShare={true}
avatarDialog={agentInfo.avatar} avatarDialog={inputsData.avatar}
agentName={agentInfo.title} agentName={inputsData.title}
index={i} index={i}
clickDocumentButton={clickDocumentButton} clickDocumentButton={clickDocumentButton}
showLikeButton={false} showLikeButton={false}
@ -192,23 +180,25 @@ const ChatContainer = () => {
</div> </div>
<div ref={scrollRef} /> <div ref={scrollRef} />
</div> </div>
<div className="flex w-full justify-center mb-8"> {isTaskMode || (
<div className="w-5/6"> <div className="flex w-full justify-center mb-8">
<NextMessageInput <div className="w-5/6">
isShared <NextMessageInput
value={value} isShared
disabled={hasError || isWaitting} value={value}
sendDisabled={sendDisabled || isWaitting} disabled={hasError || isWaitting}
conversationId={conversationId} sendDisabled={sendDisabled || isWaitting}
onInputChange={handleInputChange} conversationId={conversationId}
onPressEnter={handlePressEnter} onInputChange={handleInputChange}
sendLoading={sendLoading} onPressEnter={handlePressEnter}
stopOutputMessage={stopOutputMessage} sendLoading={sendLoading}
onUpload={handleUploadFile} stopOutputMessage={stopOutputMessage}
isUploading={loading || isWaitting} onUpload={handleUploadFile}
></NextMessageInput> isUploading={loading || isWaitting}
></NextMessageInput>
</div>
</div> </div>
</div> )}
</div> </div>
</EmbedContainer> </EmbedContainer>
{visible && ( {visible && (
@ -223,7 +213,7 @@ const ChatContainer = () => {
<ParameterDialog <ParameterDialog
// hideModal={hideParameterDialog} // hideModal={hideParameterDialog}
ok={handleInputsModalOk} ok={handleInputsModalOk}
data={agentInfo.inputs} data={inputsData.inputs}
></ParameterDialog> ></ParameterDialog>
)} )}
</> </>