### 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)tags/v0.20.0
| showLikeButton: boolean; | showLikeButton: boolean; | ||||
| audioBinary?: string; | audioBinary?: string; | ||||
| showLoudspeaker?: boolean; | showLoudspeaker?: boolean; | ||||
| showLog?: boolean; | |||||
| } | } | ||||
| export const AssistantGroupButton = ({ | export const AssistantGroupButton = ({ | ||||
| audioBinary, | audioBinary, | ||||
| showLikeButton, | showLikeButton, | ||||
| showLoudspeaker = true, | showLoudspeaker = true, | ||||
| showLog = true, | |||||
| }: IProps) => { | }: IProps) => { | ||||
| const { visible, hideModal, showModal, onFeedbackOk, loading } = | const { visible, hideModal, showModal, onFeedbackOk, loading } = | ||||
| useSendFeedback(messageId); | useSendFeedback(messageId); | ||||
| <PromptIcon style={{ fontSize: '16px' }} /> | <PromptIcon style={{ fontSize: '16px' }} /> | ||||
| </Radio.Button> | </Radio.Button> | ||||
| )} | )} | ||||
| <ToggleGroupItem value="f" onClick={handleShowLogSheet}> | |||||
| <NotebookText className="size-4" /> | |||||
| </ToggleGroupItem> | |||||
| {showLog && ( | |||||
| <ToggleGroupItem value="f" onClick={handleShowLogSheet}> | |||||
| <NotebookText className="size-4" /> | |||||
| </ToggleGroupItem> | |||||
| )} | |||||
| </ToggleGroup> | </ToggleGroup> | ||||
| {visible && ( | {visible && ( | ||||
| <FeedbackModal | <FeedbackModal |
| index: number; | index: number; | ||||
| showLikeButton?: boolean; | showLikeButton?: boolean; | ||||
| showLoudspeaker?: boolean; | showLoudspeaker?: boolean; | ||||
| showLog?: boolean; | |||||
| } | } | ||||
| function MessageItem({ | function MessageItem({ | ||||
| showLoudspeaker = true, | showLoudspeaker = true, | ||||
| visibleAvatar = true, | visibleAvatar = true, | ||||
| children, | children, | ||||
| showLog, | |||||
| }: IProps) { | }: IProps) { | ||||
| const { theme } = useTheme(); | const { theme } = useTheme(); | ||||
| const isAssistant = item.role === MessageType.Assistant; | const isAssistant = item.role === MessageType.Assistant; | ||||
| showLikeButton={showLikeButton} | showLikeButton={showLikeButton} | ||||
| audioBinary={item.audio_binary} | audioBinary={item.audio_binary} | ||||
| showLoudspeaker={showLoudspeaker} | showLoudspeaker={showLoudspeaker} | ||||
| showLog={showLog} | |||||
| ></AssistantGroupButton> | ></AssistantGroupButton> | ||||
| ) : ( | ) : ( | ||||
| <UserGroupButton | <UserGroupButton |
| System = 'system', | System = 'system', | ||||
| Api = 'api', | Api = 'api', | ||||
| Team = 'team', | Team = 'team', | ||||
| MCP = 'mcp', | |||||
| Logout = 'logout', | Logout = 'logout', | ||||
| } | } | ||||
| navigate(Routes.Chat); | navigate(Routes.Chat); | ||||
| }, [navigate]); | }, [navigate]); | ||||
| const navigateToAgentList = useCallback(() => { | |||||
| const navigateToAgents = useCallback(() => { | |||||
| navigate(Routes.Agents); | navigate(Routes.Agents); | ||||
| }, [navigate]); | }, [navigate]); | ||||
| const navigateToAgentList = useCallback(() => { | |||||
| navigate(Routes.AgentList); | |||||
| }, [navigate]); | |||||
| const navigateToAgent = useCallback( | const navigateToAgent = useCallback( | ||||
| (id: string) => () => { | (id: string) => () => { | ||||
| navigate(`${Routes.Agent}/${id}`); | navigate(`${Routes.Agent}/${id}`); | ||||
| navigateToChunkParsedResult, | navigateToChunkParsedResult, | ||||
| getQueryString, | getQueryString, | ||||
| navigateToChunk, | navigateToChunk, | ||||
| navigateToAgentList, | |||||
| navigateToAgents, | |||||
| navigateToAgent, | navigateToAgent, | ||||
| navigateToAgentTemplates, | navigateToAgentTemplates, | ||||
| navigateToSearchList, | navigateToSearchList, | ||||
| navigateToSearch, | navigateToSearch, | ||||
| navigateToFiles, | navigateToFiles, | ||||
| navigateToAgentList, | |||||
| }; | }; | ||||
| }; | }; |
| FetchInputForm = 'fetchInputForm', | FetchInputForm = 'fetchInputForm', | ||||
| FetchVersionList = 'fetchVersionList', | FetchVersionList = 'fetchVersionList', | ||||
| FetchVersion = 'fetchVersion', | FetchVersion = 'fetchVersion', | ||||
| FetchAgentAvatar = 'fetchAgentAvatar', | |||||
| } | } | ||||
| export const EmptyDsl = { | export const EmptyDsl = { | ||||
| return { data, loading }; | return { data, loading }; | ||||
| }; | }; | ||||
| export const useFetchAgentAvatar = (): { | |||||
| data: IFlow; | |||||
| loading: boolean; | |||||
| refetch: () => void; | |||||
| } => { | |||||
| const { sharedId } = useGetSharedChatSearchParams(); | |||||
| const { | |||||
| data, | |||||
| isFetching: loading, | |||||
| refetch, | |||||
| } = useQuery({ | |||||
| queryKey: [AgentApiAction.FetchAgentAvatar], | |||||
| initialData: {} as IFlow, | |||||
| refetchOnReconnect: false, | |||||
| refetchOnMount: false, | |||||
| refetchOnWindowFocus: false, | |||||
| gcTime: 0, | |||||
| queryFn: async () => { | |||||
| if (!sharedId) return {}; | |||||
| const { data } = await agentService.fetchAgentAvatar(sharedId); | |||||
| return data?.data ?? {}; | |||||
| }, | |||||
| }); | |||||
| return { data, loading, refetch }; | |||||
| }; |
| { path: '/knowledge', name: t('knowledgeBase'), icon: KnowledgeBaseIcon }, | { path: '/knowledge', name: t('knowledgeBase'), icon: KnowledgeBaseIcon }, | ||||
| { path: '/chat', name: t('chat'), icon: MessageOutlined }, | { path: '/chat', name: t('chat'), icon: MessageOutlined }, | ||||
| { path: '/search', name: t('search'), icon: SearchOutlined }, | { path: '/search', name: t('search'), icon: SearchOutlined }, | ||||
| { path: '/flow', name: t('flow'), icon: GraphIcon }, | |||||
| { path: '/agent-list', name: t('flow'), icon: GraphIcon }, | |||||
| { path: '/file', name: t('fileManager'), icon: FileIcon }, | { path: '/file', name: t('fileManager'), icon: FileIcon }, | ||||
| ], | ], | ||||
| [t], | [t], |
| view: 'View', | view: 'View', | ||||
| modelsToBeAddedTooltip: | modelsToBeAddedTooltip: | ||||
| 'If your model provider is not listed but claims to be "OpenAI-compatible", select the OpenAI-API-compatible card to add the relevant model(s). ', | 'If your model provider is not listed but claims to be "OpenAI-compatible", select the OpenAI-API-compatible card to add the relevant model(s). ', | ||||
| mcp: 'MCP', | |||||
| }, | }, | ||||
| message: { | message: { | ||||
| registered: 'Registered!', | registered: 'Registered!', |
| import { MessageType } from '@/constants/chat'; | import { MessageType } from '@/constants/chat'; | ||||
| import { useGetFileIcon } from '@/pages/chat/hooks'; | 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 MessageInput from '@/components/message-input'; | ||||
| import MessageItem from '@/components/next-message-item'; | import MessageItem from '@/components/next-message-item'; | ||||
| handleInputChange, | handleInputChange, | ||||
| handlePressEnter, | handlePressEnter, | ||||
| value, | value, | ||||
| loading, | |||||
| ref, | ref, | ||||
| derivedMessages, | derivedMessages, | ||||
| stopOutputMessage, | stopOutputMessage, | ||||
| sendFormMessage, | sendFormMessage, | ||||
| findReferenceByMessageId, | findReferenceByMessageId, | ||||
| } = useSendNextMessage(); | |||||
| } = useSendAgentMessage(); | |||||
| const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } = | const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } = | ||||
| useClickDrawer(); | useClickDrawer(); | ||||
| <section className="flex flex-1 flex-col px-5 h-[90vh]"> | <section className="flex flex-1 flex-col px-5 h-[90vh]"> | ||||
| <div className="flex-1 overflow-auto"> | <div className="flex-1 overflow-auto"> | ||||
| <div> | <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> | ||||
| <div ref={ref} /> | <div ref={ref} /> | ||||
| </div> | </div> |
| useHandleMessageInputChange, | useHandleMessageInputChange, | ||||
| useSelectDerivedMessages, | useSelectDerivedMessages, | ||||
| } from '@/hooks/logic-hooks'; | } from '@/hooks/logic-hooks'; | ||||
| import { useFetchAgent } from '@/hooks/use-agent-request'; | |||||
| import { | import { | ||||
| IEventList, | IEventList, | ||||
| IInputEvent, | IInputEvent, | ||||
| import useGraphStore from '../store'; | import useGraphStore from '../store'; | ||||
| import { receiveMessageError } from '../utils'; | 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( | const messageEventList = eventList.filter( | ||||
| (x) => x.event === MessageEventType.Message, | (x) => x.event === MessageEventType.Message, | ||||
| ) as IMessageEvent[]; | ) as IMessageEvent[]; | ||||
| }; | }; | ||||
| } | } | ||||
| function findInputFromList(eventList: IEventList) { | |||||
| export function findInputFromList(eventList: IEventList) { | |||||
| const inputEvent = eventList.find( | const inputEvent = eventList.find( | ||||
| (x) => x.event === MessageEventType.UserInputs, | (x) => x.event === MessageEventType.UserInputs, | ||||
| ) as IInputEvent; | ) as IInputEvent; | ||||
| return get(eventList.at(-1), 'data.outputs._ERROR'); | return get(eventList.at(-1), 'data.outputs._ERROR'); | ||||
| } | } | ||||
| const useGetBeginNodePrologue = () => { | |||||
| export const useGetBeginNodePrologue = () => { | |||||
| const getNode = useGraphStore((state) => state.getNode); | const getNode = useGraphStore((state) => state.getNode); | ||||
| return useMemo(() => { | return useMemo(() => { | ||||
| }, [getNode]); | }, [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 { | const { | ||||
| reference, | |||||
| loading, | |||||
| derivedMessages, | derivedMessages, | ||||
| ref, | ref, | ||||
| removeLatestMessage, | removeLatestMessage, | ||||
| removeMessageById, | removeMessageById, | ||||
| addNewestOneQuestion, | addNewestOneQuestion, | ||||
| addNewestOneAnswer, | addNewestOneAnswer, | ||||
| } = useSelectNextMessages(); | |||||
| const { id: agentId } = useParams(); | |||||
| const { handleInputChange, value, setValue } = useHandleMessageInputChange(); | |||||
| const { refetch } = useFetchAgent(); | |||||
| } = useSelectDerivedMessages(); | |||||
| const { addEventList } = useContext(AgentChatLogContext); | 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( | const sendMessage = useCallback( | ||||
| async ({ message }: { message: Message; messages?: Message[] }) => { | async ({ message }: { message: Message; messages?: Message[] }) => { | ||||
| setValue(message.content); | setValue(message.content); | ||||
| removeLatestMessage(); | removeLatestMessage(); | ||||
| } else { | } 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 }); | |||||
| const sendFormMessage = useCallback( | |||||
| (body: { id?: string; inputs: Record<string, BeginQuery> }) => { | |||||
| send(body); | |||||
| addNewestOneQuestion({ | |||||
| content: Object.entries(body.inputs) | |||||
| .map(([key, val]) => `${key}: ${val.value}`) | |||||
| .join('<br/>'), | |||||
| role: MessageType.User, | |||||
| }); | |||||
| }, | }, | ||||
| [sendMessage], | |||||
| [addNewestOneQuestion, send], | |||||
| ); | ); | ||||
| 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; | |||||
| const handlePressEnter = useCallback(() => { | |||||
| if (trim(value) === '') return; | |||||
| const id = uuid(); | |||||
| if (done) { | |||||
| setValue(''); | |||||
| sendMessage({ | |||||
| message: { id, content: value.trim(), role: MessageType.User }, | |||||
| }); | }); | ||||
| } | } | ||||
| }, [addEventList.length, answerList]); | |||||
| addNewestOneQuestion({ | |||||
| content: value, | |||||
| id, | |||||
| role: MessageType.User, | |||||
| }); | |||||
| }, [value, done, addNewestOneQuestion, setValue, sendMessage]); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| const { content, id } = findMessageFromList(answerList); | const { content, id } = findMessageFromList(answerList); | ||||
| } | } | ||||
| }, [answerList, addNewestOneAnswer]); | }, [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); | |||||
| addNewestOneQuestion({ | |||||
| content: Object.entries(body.inputs) | |||||
| .map(([key, val]) => `${key}: ${val.value}`) | |||||
| .join('<br/>'), | |||||
| role: MessageType.User, | |||||
| }); | |||||
| }, | |||||
| [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], | |||||
| ); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| if (prologue) { | if (prologue) { | ||||
| addNewestOneAnswer({ | addNewestOneAnswer({ | ||||
| }, [addNewestOneAnswer, agentId, prologue, send, sendFormMessage]); | }, [addNewestOneAnswer, agentId, prologue, send, sendFormMessage]); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| addEventList(answerList); | |||||
| if (typeof addEventList === 'function') { | |||||
| addEventList(answerList); | |||||
| } | |||||
| }, [addEventList, answerList]); | }, [addEventList, answerList]); | ||||
| return { | return { | ||||
| handleInputChange, | handleInputChange, | ||||
| value, | value, | ||||
| sendLoading: !done, | sendLoading: !done, | ||||
| reference, | |||||
| loading, | |||||
| derivedMessages, | derivedMessages, | ||||
| ref, | ref, | ||||
| removeMessageById, | removeMessageById, |
| const generateIframeSrc = useCallback(() => { | const generateIframeSrc = useCallback(() => { | ||||
| const { visibleAvatar, locale } = values; | const { visibleAvatar, locale } = values; | ||||
| let src = `${location.origin}/chat/share?shared_id=${token}&from=${from}&auth=${beta}`; | |||||
| let src = `${location.origin}/next-chat/share?shared_id=${token}&from=${from}&auth=${beta}`; | |||||
| if (visibleAvatar) { | if (visibleAvatar) { | ||||
| src += '&visible_avatar=1'; | src += '&visible_avatar=1'; | ||||
| } | } |
| import { SharedFrom } from '@/constants/chat'; | import { SharedFrom } from '@/constants/chat'; | ||||
| import { useSetModalState } from '@/hooks/common-hooks'; | import { useSetModalState } from '@/hooks/common-hooks'; | ||||
| import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; | import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; | ||||
| import { useFetchUserInfo } from '@/hooks/user-setting-hooks'; | |||||
| import { ReactFlowProvider } from '@xyflow/react'; | import { ReactFlowProvider } from '@xyflow/react'; | ||||
| import { | import { | ||||
| ChevronDown, | ChevronDown, | ||||
| import EmbedDialog from './embed-dialog'; | import EmbedDialog from './embed-dialog'; | ||||
| import { useHandleExportOrImportJsonFile } from './hooks/use-export-json'; | import { useHandleExportOrImportJsonFile } from './hooks/use-export-json'; | ||||
| import { useFetchDataOnMount } from './hooks/use-fetch-data'; | import { useFetchDataOnMount } from './hooks/use-fetch-data'; | ||||
| import { useGetBeginNodeDataInputs } from './hooks/use-get-begin-query'; | |||||
| import { | |||||
| useGetBeginNodeDataInputs, | |||||
| useGetBeginNodeDataQueryIsSafe, | |||||
| } from './hooks/use-get-begin-query'; | |||||
| import { useOpenDocument } from './hooks/use-open-document'; | import { useOpenDocument } from './hooks/use-open-document'; | ||||
| import { | import { | ||||
| useSaveGraph, | useSaveGraph, | ||||
| showModal: showChatDrawer, | showModal: showChatDrawer, | ||||
| } = useSetModalState(); | } = useSetModalState(); | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const { data: userInfo } = useFetchUserInfo(); | |||||
| const openDocument = useOpenDocument(); | const openDocument = useOpenDocument(); | ||||
| const { | const { | ||||
| handleExportJson, | handleExportJson, | ||||
| hideFileUploadModal, | hideFileUploadModal, | ||||
| } = useHandleExportOrImportJsonFile(); | } = useHandleExportOrImportJsonFile(); | ||||
| const { saveGraph, loading } = useSaveGraph(); | const { saveGraph, loading } = useSaveGraph(); | ||||
| const { flowDetail } = useFetchDataOnMount(); | |||||
| const { flowDetail: agentDetail } = useFetchDataOnMount(); | |||||
| const inputs = useGetBeginNodeDataInputs(); | const inputs = useGetBeginNodeDataInputs(); | ||||
| const { handleRun } = useSaveGraphBeforeOpeningDebugDrawer(showChatDrawer); | const { handleRun } = useSaveGraphBeforeOpeningDebugDrawer(showChatDrawer); | ||||
| const handleRunAgent = useCallback(() => { | const handleRunAgent = useCallback(() => { | ||||
| const { showEmbedModal, hideEmbedModal, embedVisible, beta } = | const { showEmbedModal, hideEmbedModal, embedVisible, beta } = | ||||
| useShowEmbedModal(); | useShowEmbedModal(); | ||||
| const isBeginNodeDataQuerySafe = useGetBeginNodeDataQueryIsSafe(); | |||||
| return ( | return ( | ||||
| <section className="h-full"> | <section className="h-full"> | ||||
| <PageHeader> | <PageHeader> | ||||
| </BreadcrumbItem> | </BreadcrumbItem> | ||||
| <BreadcrumbSeparator /> | <BreadcrumbSeparator /> | ||||
| <BreadcrumbItem> | <BreadcrumbItem> | ||||
| <BreadcrumbPage>{flowDetail.title}</BreadcrumbPage> | |||||
| <BreadcrumbPage>{agentDetail.title}</BreadcrumbPage> | |||||
| </BreadcrumbItem> | </BreadcrumbItem> | ||||
| </BreadcrumbList> | </BreadcrumbList> | ||||
| </Breadcrumb> | </Breadcrumb> | ||||
| {t('flow.export')} | {t('flow.export')} | ||||
| </AgentDropdownMenuItem> | </AgentDropdownMenuItem> | ||||
| <DropdownMenuSeparator /> | <DropdownMenuSeparator /> | ||||
| <AgentDropdownMenuItem onClick={showEmbedModal}> | |||||
| <AgentDropdownMenuItem | |||||
| onClick={showEmbedModal} | |||||
| disabled={ | |||||
| !isBeginNodeDataQuerySafe || | |||||
| userInfo.nickname !== agentDetail.nickname | |||||
| } | |||||
| > | |||||
| <ScreenShare /> | <ScreenShare /> | ||||
| {t('common.embedIntoSite')} | {t('common.embedIntoSite')} | ||||
| </AgentDropdownMenuItem> | </AgentDropdownMenuItem> |
| import { PageHeader } from '@/components/page-header'; | import { PageHeader } from '@/components/page-header'; | ||||
| import { | |||||
| Breadcrumb, | |||||
| BreadcrumbItem, | |||||
| BreadcrumbLink, | |||||
| BreadcrumbList, | |||||
| BreadcrumbPage, | |||||
| BreadcrumbSeparator, | |||||
| } from '@/components/ui/breadcrumb'; | |||||
| import { useSetModalState } from '@/hooks/common-hooks'; | import { useSetModalState } from '@/hooks/common-hooks'; | ||||
| import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; | import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; | ||||
| import { useFetchAgentTemplates, useSetAgent } from '@/hooks/use-agent-request'; | import { useFetchAgentTemplates, useSetAgent } from '@/hooks/use-agent-request'; | ||||
| return ( | return ( | ||||
| <section> | <section> | ||||
| <PageHeader | |||||
| back={navigateToAgentList} | |||||
| title={t('flow.createGraph')} | |||||
| ></PageHeader> | |||||
| <PageHeader> | |||||
| <Breadcrumb> | |||||
| <BreadcrumbList> | |||||
| <BreadcrumbItem> | |||||
| <BreadcrumbLink onClick={navigateToAgentList}> | |||||
| Agent | |||||
| </BreadcrumbLink> | |||||
| </BreadcrumbItem> | |||||
| <BreadcrumbSeparator /> | |||||
| <BreadcrumbItem> | |||||
| <BreadcrumbPage>{t('flow.createGraph')}</BreadcrumbPage> | |||||
| </BreadcrumbItem> | |||||
| </BreadcrumbList> | |||||
| </Breadcrumb> | |||||
| </PageHeader> | |||||
| <div className="grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6 2xl:grid-cols-8 max-h-[94vh] overflow-auto px-8"> | <div className="grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6 2xl:grid-cols-8 max-h-[94vh] overflow-auto px-8"> | ||||
| {list?.map((x) => { | {list?.map((x) => { | ||||
| return ( | return ( |
| import { MessageType, SharedFrom } from '@/constants/chat'; | |||||
| import { useCreateNextSharedConversation } from '@/hooks/chat-hooks'; | |||||
| import { | |||||
| useHandleMessageInputChange, | |||||
| useSelectDerivedMessages, | |||||
| useSendMessageWithSse, | |||||
| } from '@/hooks/logic-hooks'; | |||||
| import { Message } from '@/interfaces/database/chat'; | |||||
| import { message } from 'antd'; | |||||
| import { get } from 'lodash'; | |||||
| import { SharedFrom } from '@/constants/chat'; | |||||
| import { useSendAgentMessage } from '@/pages/agent/chat/use-send-agent-message'; | |||||
| import trim from 'lodash/trim'; | import trim from 'lodash/trim'; | ||||
| import { useCallback, useEffect, useState } from 'react'; | |||||
| import { useSearchParams } from 'umi'; | import { useSearchParams } from 'umi'; | ||||
| import { v4 as uuid } from 'uuid'; | |||||
| const isCompletionError = (res: any) => | |||||
| res && (res?.response.status !== 200 || res?.data?.code !== 0); | |||||
| export const useSendButtonDisabled = (value: string) => { | export const useSendButtonDisabled = (value: string) => { | ||||
| return trim(value) === ''; | return trim(value) === ''; | ||||
| }; | }; | ||||
| }; | }; | ||||
| export const useSendSharedMessage = () => { | |||||
| const { | |||||
| from, | |||||
| sharedId: conversationId, | |||||
| data: data, | |||||
| } = useGetSharedChatSearchParams(); | |||||
| const { createSharedConversation: setConversation } = | |||||
| useCreateNextSharedConversation(); | |||||
| const { handleInputChange, value, setValue } = useHandleMessageInputChange(); | |||||
| const { send, answer, done, stopOutputMessage } = useSendMessageWithSse( | |||||
| `/api/v1/${from === SharedFrom.Agent ? 'agentbots' : 'chatbots'}/${conversationId}/completions`, | |||||
| ); | |||||
| const { | |||||
| derivedMessages, | |||||
| ref, | |||||
| removeLatestMessage, | |||||
| addNewestAnswer, | |||||
| addNewestQuestion, | |||||
| } = useSelectDerivedMessages(); | |||||
| const [hasError, setHasError] = useState(false); | |||||
| const sendMessage = useCallback( | |||||
| async (message: Message, id?: string) => { | |||||
| const res = await send({ | |||||
| conversation_id: id ?? conversationId, | |||||
| quote: true, | |||||
| question: message.content, | |||||
| session_id: get(derivedMessages, '0.session_id'), | |||||
| }); | |||||
| export function useSendNextSharedMessage() { | |||||
| const { from, sharedId: conversationId } = useGetSharedChatSearchParams(); | |||||
| const url = `/api/v1/${from === SharedFrom.Agent ? 'agentbots' : 'chatbots'}/${conversationId}/completions`; | |||||
| if (isCompletionError(res)) { | |||||
| // cancel loading | |||||
| setValue(message.content); | |||||
| removeLatestMessage(); | |||||
| } | |||||
| }, | |||||
| [send, conversationId, derivedMessages, setValue, removeLatestMessage], | |||||
| ); | |||||
| const handleSendMessage = useCallback( | |||||
| async (message: Message) => { | |||||
| if (conversationId !== '') { | |||||
| sendMessage(message); | |||||
| } else { | |||||
| const data = await setConversation('user id'); | |||||
| if (data.code === 0) { | |||||
| const id = data.data.id; | |||||
| sendMessage(message, id); | |||||
| } | |||||
| } | |||||
| }, | |||||
| [conversationId, setConversation, sendMessage], | |||||
| ); | |||||
| const fetchSessionId = useCallback(async () => { | |||||
| const payload = { question: '' }; | |||||
| const ret = await send({ ...payload, ...data }); | |||||
| if (isCompletionError(ret)) { | |||||
| message.error(ret?.data.message); | |||||
| setHasError(true); | |||||
| } | |||||
| }, [data, send]); | |||||
| useEffect(() => { | |||||
| fetchSessionId(); | |||||
| }, [fetchSessionId, send]); | |||||
| useEffect(() => { | |||||
| if (answer.answer) { | |||||
| addNewestAnswer(answer); | |||||
| } | |||||
| }, [answer, addNewestAnswer]); | |||||
| const handlePressEnter = useCallback( | |||||
| (documentIds: string[]) => { | |||||
| if (trim(value) === '') return; | |||||
| const id = uuid(); | |||||
| if (done) { | |||||
| setValue(''); | |||||
| addNewestQuestion({ | |||||
| content: value, | |||||
| doc_ids: documentIds, | |||||
| id, | |||||
| role: MessageType.User, | |||||
| }); | |||||
| handleSendMessage({ | |||||
| content: value.trim(), | |||||
| id, | |||||
| role: MessageType.User, | |||||
| }); | |||||
| } | |||||
| }, | |||||
| [addNewestQuestion, done, handleSendMessage, setValue, value], | |||||
| ); | |||||
| const ret = useSendAgentMessage(url); | |||||
| return { | return { | ||||
| handlePressEnter, | |||||
| handleInputChange, | |||||
| value, | |||||
| sendLoading: !done, | |||||
| ref, | |||||
| loading: false, | |||||
| derivedMessages, | |||||
| hasError, | |||||
| stopOutputMessage, | |||||
| ...ret, | |||||
| hasError: false, | |||||
| }; | }; | ||||
| }; | |||||
| } |
| .chatWrapper { | |||||
| height: 100vh; | |||||
| } | |||||
| .chatContainer { | |||||
| padding: 10px; | |||||
| box-sizing: border-box; | |||||
| height: 100%; | |||||
| .messageContainer { | |||||
| overflow-y: auto; | |||||
| padding-right: 6px; | |||||
| } | |||||
| } |
| import ChatContainer from './large'; | |||||
| import MessageInput from '@/components/message-input'; | |||||
| import MessageItem from '@/components/next-message-item'; | |||||
| import PdfDrawer from '@/components/pdf-drawer'; | |||||
| import { useClickDrawer } from '@/components/pdf-drawer/hooks'; | |||||
| import { MessageType, SharedFrom } from '@/constants/chat'; | |||||
| import { useFetchNextConversationSSE } from '@/hooks/chat-hooks'; | |||||
| import { useFetchAgentAvatar } from '@/hooks/use-agent-request'; | |||||
| import { cn } from '@/lib/utils'; | |||||
| import i18n from '@/locales/config'; | |||||
| import { useSendButtonDisabled } from '@/pages/chat/hooks'; | |||||
| import { buildMessageUuidWithRole } from '@/utils/chat'; | |||||
| import React, { forwardRef, useMemo } from 'react'; | |||||
| import { | |||||
| useGetSharedChatSearchParams, | |||||
| useSendNextSharedMessage, | |||||
| } from '../hooks/use-send-shared-message'; | |||||
| import styles from './index.less'; | |||||
| const ChatContainer = () => { | |||||
| const { | |||||
| sharedId: conversationId, | |||||
| from, | |||||
| locale, | |||||
| visibleAvatar, | |||||
| } = useGetSharedChatSearchParams(); | |||||
| const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } = | |||||
| useClickDrawer(); | |||||
| const { | |||||
| handlePressEnter, | |||||
| handleInputChange, | |||||
| value, | |||||
| sendLoading, | |||||
| ref, | |||||
| derivedMessages, | |||||
| hasError, | |||||
| stopOutputMessage, | |||||
| findReferenceByMessageId, | |||||
| } = useSendNextSharedMessage(); | |||||
| const sendDisabled = useSendButtonDisabled(value); | |||||
| const useFetchAvatar = useMemo(() => { | |||||
| return from === SharedFrom.Agent | |||||
| ? useFetchAgentAvatar | |||||
| : useFetchNextConversationSSE; | |||||
| }, [from]); | |||||
| React.useEffect(() => { | |||||
| if (locale && i18n.language !== locale) { | |||||
| i18n.changeLanguage(locale); | |||||
| } | |||||
| }, [locale, visibleAvatar]); | |||||
| const { data: avatarData } = useFetchAvatar(); | |||||
| if (!conversationId) { | |||||
| return <div>empty</div>; | |||||
| } | |||||
| const SharedChat = () => { | |||||
| return ( | return ( | ||||
| <div className={styles.chatWrapper}> | |||||
| <ChatContainer></ChatContainer> | |||||
| </div> | |||||
| <section className="h-[100vh]"> | |||||
| <section className={cn('flex flex-1 flex-col p-2.5 h-full')}> | |||||
| <div className={cn('flex flex-1 flex-col overflow-auto pr-2')}> | |||||
| <div> | |||||
| {derivedMessages?.map((message, i) => { | |||||
| return ( | |||||
| <MessageItem | |||||
| visibleAvatar={visibleAvatar} | |||||
| key={buildMessageUuidWithRole(message)} | |||||
| avatarDialog={avatarData.avatar} | |||||
| item={message} | |||||
| nickname="You" | |||||
| reference={findReferenceByMessageId(message.id)} | |||||
| loading={ | |||||
| message.role === MessageType.Assistant && | |||||
| sendLoading && | |||||
| derivedMessages?.length - 1 === i | |||||
| } | |||||
| index={i} | |||||
| clickDocumentButton={clickDocumentButton} | |||||
| showLikeButton={false} | |||||
| showLoudspeaker={false} | |||||
| showLog={false} | |||||
| ></MessageItem> | |||||
| ); | |||||
| })} | |||||
| </div> | |||||
| <div ref={ref} /> | |||||
| </div> | |||||
| <MessageInput | |||||
| isShared | |||||
| value={value} | |||||
| disabled={hasError} | |||||
| sendDisabled={sendDisabled} | |||||
| conversationId={conversationId} | |||||
| onInputChange={handleInputChange} | |||||
| onPressEnter={handlePressEnter} | |||||
| sendLoading={sendLoading} | |||||
| uploadMethod="external_upload_and_parse" | |||||
| showUploadIcon={false} | |||||
| stopOutputMessage={stopOutputMessage} | |||||
| ></MessageInput> | |||||
| </section> | |||||
| {visible && ( | |||||
| <PdfDrawer | |||||
| visible={visible} | |||||
| hideModal={hideModal} | |||||
| documentId={documentId} | |||||
| chunk={selectedChunk} | |||||
| ></PdfDrawer> | |||||
| )} | |||||
| </section> | |||||
| ); | ); | ||||
| }; | }; | ||||
| export default SharedChat; | |||||
| export default forwardRef(ChatContainer); |
| import MessageInput from '@/components/message-input'; | |||||
| import MessageItem from '@/components/message-item'; | |||||
| import PdfDrawer from '@/components/pdf-drawer'; | |||||
| import { useClickDrawer } from '@/components/pdf-drawer/hooks'; | |||||
| import { MessageType, SharedFrom } from '@/constants/chat'; | |||||
| import { useFetchNextConversationSSE } from '@/hooks/chat-hooks'; | |||||
| import { useFetchFlowSSE } from '@/hooks/flow-hooks'; | |||||
| import i18n from '@/locales/config'; | |||||
| import { useSendButtonDisabled } from '@/pages/chat/hooks'; | |||||
| import { buildMessageUuidWithRole } from '@/utils/chat'; | |||||
| import { Flex, Spin } from 'antd'; | |||||
| import React, { forwardRef, useMemo } from 'react'; | |||||
| import { | |||||
| useGetSharedChatSearchParams, | |||||
| useSendSharedMessage, | |||||
| } from '../hooks/use-send-shared-message'; | |||||
| import { buildMessageItemReference } from '../utils'; | |||||
| import styles from './index.less'; | |||||
| const ChatContainer = () => { | |||||
| const { | |||||
| sharedId: conversationId, | |||||
| from, | |||||
| locale, | |||||
| visibleAvatar, | |||||
| } = useGetSharedChatSearchParams(); | |||||
| const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } = | |||||
| useClickDrawer(); | |||||
| const { | |||||
| handlePressEnter, | |||||
| handleInputChange, | |||||
| value, | |||||
| sendLoading, | |||||
| loading, | |||||
| ref, | |||||
| derivedMessages, | |||||
| hasError, | |||||
| stopOutputMessage, | |||||
| } = useSendSharedMessage(); | |||||
| const sendDisabled = useSendButtonDisabled(value); | |||||
| const useFetchAvatar = useMemo(() => { | |||||
| return from === SharedFrom.Agent | |||||
| ? useFetchFlowSSE | |||||
| : useFetchNextConversationSSE; | |||||
| }, [from]); | |||||
| React.useEffect(() => { | |||||
| if (locale && i18n.language !== locale) { | |||||
| i18n.changeLanguage(locale); | |||||
| } | |||||
| }, [locale, visibleAvatar]); | |||||
| const { data: avatarData } = useFetchAvatar(); | |||||
| if (!conversationId) { | |||||
| return <div>empty</div>; | |||||
| } | |||||
| return ( | |||||
| <> | |||||
| <Flex flex={1} className={styles.chatContainer} vertical> | |||||
| <Flex flex={1} vertical className={styles.messageContainer}> | |||||
| <div> | |||||
| <Spin spinning={loading}> | |||||
| {derivedMessages?.map((message, i) => { | |||||
| return ( | |||||
| <MessageItem | |||||
| visibleAvatar={visibleAvatar} | |||||
| key={buildMessageUuidWithRole(message)} | |||||
| avatarDialog={avatarData?.avatar} | |||||
| item={message} | |||||
| nickname="You" | |||||
| reference={buildMessageItemReference( | |||||
| { | |||||
| message: derivedMessages, | |||||
| reference: [], | |||||
| }, | |||||
| message, | |||||
| )} | |||||
| loading={ | |||||
| message.role === MessageType.Assistant && | |||||
| sendLoading && | |||||
| derivedMessages?.length - 1 === i | |||||
| } | |||||
| index={i} | |||||
| clickDocumentButton={clickDocumentButton} | |||||
| showLikeButton={false} | |||||
| showLoudspeaker={false} | |||||
| ></MessageItem> | |||||
| ); | |||||
| })} | |||||
| </Spin> | |||||
| </div> | |||||
| <div ref={ref} /> | |||||
| </Flex> | |||||
| <MessageInput | |||||
| isShared | |||||
| value={value} | |||||
| disabled={hasError} | |||||
| sendDisabled={sendDisabled} | |||||
| conversationId={conversationId} | |||||
| onInputChange={handleInputChange} | |||||
| onPressEnter={handlePressEnter} | |||||
| sendLoading={sendLoading} | |||||
| uploadMethod="external_upload_and_parse" | |||||
| showUploadIcon={false} | |||||
| stopOutputMessage={stopOutputMessage} | |||||
| ></MessageInput> | |||||
| </Flex> | |||||
| {visible && ( | |||||
| <PdfDrawer | |||||
| visible={visible} | |||||
| hideModal={hideModal} | |||||
| documentId={documentId} | |||||
| chunk={selectedChunk} | |||||
| ></PdfDrawer> | |||||
| )} | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| export default forwardRef(ChatContainer); |
| import { MessageType } from '@/constants/chat'; | |||||
| import { EmptyConversationId, MessageType } from '@/constants/chat'; | |||||
| import { IConversation, IReference } from '@/interfaces/database/chat'; | import { IConversation, IReference } from '@/interfaces/database/chat'; | ||||
| import { isEmpty } from 'lodash'; | import { isEmpty } from 'lodash'; | ||||
| import { EmptyConversationId } from './constants'; | |||||
| import { IMessage } from './interface'; | |||||
| import { IMessage } from '../chat/interface'; | |||||
| export const isConversationIdExist = (conversationId: string) => { | export const isConversationIdExist = (conversationId: string) => { | ||||
| return conversationId !== EmptyConversationId && conversationId !== ''; | return conversationId !== EmptyConversationId && conversationId !== ''; |
| ProfileIcon, | ProfileIcon, | ||||
| TeamIcon, | TeamIcon, | ||||
| } from '@/assets/icon/Icon'; | } from '@/assets/icon/Icon'; | ||||
| import { IconFont } from '@/components/icon-font'; | |||||
| import { LLMFactory } from '@/constants/llm'; | import { LLMFactory } from '@/constants/llm'; | ||||
| import { UserSettingRouteKey } from '@/constants/setting'; | import { UserSettingRouteKey } from '@/constants/setting'; | ||||
| import { MonitorOutlined } from '@ant-design/icons'; | import { MonitorOutlined } from '@ant-design/icons'; | ||||
| [UserSettingRouteKey.Team]: <TeamIcon />, | [UserSettingRouteKey.Team]: <TeamIcon />, | ||||
| [UserSettingRouteKey.Logout]: <LogOutIcon />, | [UserSettingRouteKey.Logout]: <LogOutIcon />, | ||||
| [UserSettingRouteKey.Api]: <ApiIcon />, | [UserSettingRouteKey.Api]: <ApiIcon />, | ||||
| [UserSettingRouteKey.MCP]: ( | |||||
| <IconFont name="mcp" className="size-6"></IconFont> | |||||
| ), | |||||
| }; | }; | ||||
| export * from '@/constants/setting'; | export * from '@/constants/setting'; |
| Agent = '/agent', | Agent = '/agent', | ||||
| AgentTemplates = '/agent-templates', | AgentTemplates = '/agent-templates', | ||||
| Agents = '/agents', | Agents = '/agents', | ||||
| AgentList = '/agent-list', | |||||
| Searches = '/next-searches', | Searches = '/next-searches', | ||||
| Search = '/next-search', | Search = '/next-search', | ||||
| Chats = '/next-chats', | Chats = '/next-chats', | ||||
| component: '@/pages/chat/share', | component: '@/pages/chat/share', | ||||
| layout: false, | layout: false, | ||||
| }, | }, | ||||
| { | |||||
| path: '/next-chat/share', | |||||
| component: '@/pages/next-chats/share', | |||||
| layout: false, | |||||
| }, | |||||
| { | { | ||||
| path: '/', | path: '/', | ||||
| component: '@/layouts', | component: '@/layouts', | ||||
| path: '/user-setting/api', | path: '/user-setting/api', | ||||
| component: '@/pages/user-setting/setting-api', | component: '@/pages/user-setting/setting-api', | ||||
| }, | }, | ||||
| { | |||||
| path: `/user-setting${Routes.Mcp}`, | |||||
| component: `@/pages${Routes.ProfileMcp}`, | |||||
| }, | |||||
| ], | ], | ||||
| }, | }, | ||||
| { | { | ||||
| path: '/flow', | path: '/flow', | ||||
| component: '@/pages/flow/list', | component: '@/pages/flow/list', | ||||
| }, | }, | ||||
| { | |||||
| path: Routes.AgentList, | |||||
| component: `@/pages/${Routes.Agents}`, | |||||
| }, | |||||
| { | { | ||||
| path: '/flow/:id', | path: '/flow/:id', | ||||
| component: '@/pages/flow', | component: '@/pages/flow', |
| fetchVersionList, | fetchVersionList, | ||||
| fetchVersion, | fetchVersion, | ||||
| fetchCanvas, | fetchCanvas, | ||||
| fetchAgentAvatar, | |||||
| } = api; | } = api; | ||||
| const methods = { | const methods = { | ||||
| url: inputForm, | url: inputForm, | ||||
| method: 'get', | method: 'get', | ||||
| }, | }, | ||||
| fetchAgentAvatar: { | |||||
| url: fetchAgentAvatar, | |||||
| method: 'get', | |||||
| }, | |||||
| } as const; | } as const; | ||||
| const agentService = registerNextServer<keyof typeof methods>(methods); | const agentService = registerNextServer<keyof typeof methods>(methods); |
| fetchVersionList: (id: string) => `${api_host}/canvas/getlistversion/${id}`, | fetchVersionList: (id: string) => `${api_host}/canvas/getlistversion/${id}`, | ||||
| fetchVersion: (id: string) => `${api_host}/canvas/getversion/${id}`, | fetchVersion: (id: string) => `${api_host}/canvas/getversion/${id}`, | ||||
| fetchCanvas: (id: string) => `${api_host}/canvas/get/${id}`, | fetchCanvas: (id: string) => `${api_host}/canvas/get/${id}`, | ||||
| fetchAgentAvatar: (id: string) => `${api_host}/canvas/getsse/${id}`, | |||||
| // mcp server | // mcp server | ||||
| listMcpServer: `${api_host}/mcp_server/list`, | listMcpServer: `${api_host}/mcp_server/list`, |