### What problem does this PR solve? feat: catch errors when sending messages #918 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.8.0
| import { Authorization } from '@/constants/authorization'; | import { Authorization } from '@/constants/authorization'; | ||||
| import { LanguageTranslationMap } from '@/constants/common'; | import { LanguageTranslationMap } from '@/constants/common'; | ||||
| import { Pagination } from '@/interfaces/common'; | import { Pagination } from '@/interfaces/common'; | ||||
| import { ResponseType } from '@/interfaces/database/base'; | |||||
| import { IAnswer } from '@/interfaces/database/chat'; | import { IAnswer } from '@/interfaces/database/chat'; | ||||
| import { IKnowledgeFile } from '@/interfaces/database/knowledge'; | import { IKnowledgeFile } from '@/interfaces/database/knowledge'; | ||||
| import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; | import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; | ||||
| const [done, setDone] = useState(true); | const [done, setDone] = useState(true); | ||||
| const send = useCallback( | const send = useCallback( | ||||
| async (body: any) => { | |||||
| async ( | |||||
| body: any, | |||||
| ): Promise<{ response: Response; data: ResponseType } | undefined> => { | |||||
| try { | try { | ||||
| setDone(false); | setDone(false); | ||||
| const response = await fetch(url, { | const response = await fetch(url, { | ||||
| body: JSON.stringify(body), | body: JSON.stringify(body), | ||||
| }); | }); | ||||
| const res = response.clone().json(); | |||||
| const reader = response?.body | const reader = response?.body | ||||
| ?.pipeThrough(new TextDecoderStream()) | ?.pipeThrough(new TextDecoderStream()) | ||||
| .pipeThrough(new EventSourceParserStream()) | .pipeThrough(new EventSourceParserStream()) | ||||
| } | } | ||||
| console.info('done?'); | console.info('done?'); | ||||
| setDone(true); | setDone(true); | ||||
| return response; | |||||
| return { data: await res, response }; | |||||
| } catch (e) { | } catch (e) { | ||||
| setDone(true); | setDone(true); | ||||
| console.warn(e); | console.warn(e); | 
| export interface ResponseType { | |||||
| retcode: number; | |||||
| data: any; | |||||
| retmsg: string; | |||||
| status: number; | |||||
| } | 
| } from '../hooks'; | } from '../hooks'; | ||||
| import { TextUpdaterNode } from './node'; | import { TextUpdaterNode } from './node'; | ||||
| import ChatDrawer from '../chat/drawer'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const nodeTypes = { textUpdater: TextUpdaterNode }; | const nodeTypes = { textUpdater: TextUpdaterNode }; | ||||
| interface IProps { | interface IProps { | ||||
| sideWidth: number; | sideWidth: number; | ||||
| chatDrawerVisible: boolean; | |||||
| hideChatDrawer(): void; | |||||
| } | } | ||||
| function FlowCanvas({ sideWidth }: IProps) { | |||||
| function FlowCanvas({ sideWidth, chatDrawerVisible, hideChatDrawer }: IProps) { | |||||
| const { | const { | ||||
| nodes, | nodes, | ||||
| edges, | edges, | ||||
| visible={drawerVisible} | visible={drawerVisible} | ||||
| hideModal={hideDrawer} | hideModal={hideDrawer} | ||||
| ></FlowDrawer> | ></FlowDrawer> | ||||
| <ChatDrawer | |||||
| visible={chatDrawerVisible} | |||||
| hideModal={hideChatDrawer} | |||||
| ></ChatDrawer> | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| } | } | 
| onClose={hideModal} | onClose={hideModal} | ||||
| open={visible} | open={visible} | ||||
| width={'50vw'} | width={'50vw'} | ||||
| mask={false} | |||||
| > | > | ||||
| <DocumentPreviewer | <DocumentPreviewer | ||||
| documentId={documentId} | documentId={documentId} | 
| open={visible} | open={visible} | ||||
| getContainer={false} | getContainer={false} | ||||
| width={470} | width={470} | ||||
| mask={false} | |||||
| // zIndex={10000} | // zIndex={10000} | ||||
| > | > | ||||
| <FlowChatBox></FlowChatBox> | <FlowChatBox></FlowChatBox> | 
| import { IAnswer } from '@/interfaces/database/chat'; | import { IAnswer } from '@/interfaces/database/chat'; | ||||
| import { IMessage } from '@/pages/chat/interface'; | import { IMessage } from '@/pages/chat/interface'; | ||||
| import api from '@/utils/api'; | import api from '@/utils/api'; | ||||
| import { message } from 'antd'; | |||||
| import { useCallback, useEffect, useState } from 'react'; | import { useCallback, useEffect, useState } from 'react'; | ||||
| import { useParams } from 'umi'; | import { useParams } from 'umi'; | ||||
| import { v4 as uuid } from 'uuid'; | import { v4 as uuid } from 'uuid'; | ||||
| const antMessage = message; | |||||
| export const useSelectCurrentMessages = () => { | export const useSelectCurrentMessages = () => { | ||||
| const { id: id } = useParams(); | const { id: id } = useParams(); | ||||
| const [currentMessages, setCurrentMessages] = useState<IMessage[]>([]); | const [currentMessages, setCurrentMessages] = useState<IMessage[]>([]); | ||||
| if (message) { | if (message) { | ||||
| params.message = message; | params.message = message; | ||||
| } | } | ||||
| const res: Response | undefined = await send(params); | |||||
| const res = await send(params); | |||||
| if (res?.response.status !== 200 || res?.data?.retcode !== 0) { | |||||
| antMessage.error(res?.data?.retmsg); | |||||
| if (res?.status !== 200) { | |||||
| // cancel loading | // cancel loading | ||||
| setValue(message); | setValue(message); | ||||
| removeLatestMessage(); | removeLatestMessage(); | 
| import { Button, Flex, Space } from 'antd'; | import { Button, Flex, Space } from 'antd'; | ||||
| import { useSetModalState } from '@/hooks/commonHooks'; | |||||
| import { useFetchFlow } from '@/hooks/flow-hooks'; | import { useFetchFlow } from '@/hooks/flow-hooks'; | ||||
| import { ArrowLeftOutlined } from '@ant-design/icons'; | import { ArrowLeftOutlined } from '@ant-design/icons'; | ||||
| import { Link } from 'umi'; | import { Link } from 'umi'; | ||||
| import ChatDrawer from '../chat/drawer'; | |||||
| import { useRunGraph, useSaveGraph } from '../hooks'; | |||||
| import { useSaveGraph } from '../hooks'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const FlowHeader = () => { | |||||
| interface IProps { | |||||
| showChatDrawer(): void; | |||||
| } | |||||
| const FlowHeader = ({ showChatDrawer }: IProps) => { | |||||
| const { saveGraph } = useSaveGraph(); | const { saveGraph } = useSaveGraph(); | ||||
| const { runGraph } = useRunGraph(); | |||||
| const { | |||||
| visible: chatDrawerVisible, | |||||
| hideModal: hideChatDrawer, | |||||
| showModal: showChatDrawer, | |||||
| } = useSetModalState(); | |||||
| const { data } = useFetchFlow(); | const { data } = useFetchFlow(); | ||||
| return ( | return ( | ||||
| </Button> | </Button> | ||||
| </Space> | </Space> | ||||
| </Flex> | </Flex> | ||||
| <ChatDrawer | |||||
| visible={chatDrawerVisible} | |||||
| hideModal={hideChatDrawer} | |||||
| ></ChatDrawer> | |||||
| </> | </> | ||||
| ); | ); | ||||
| }; | }; | 
| import { | import { | ||||
| useFetchFlow, | useFetchFlow, | ||||
| useFetchFlowTemplates, | useFetchFlowTemplates, | ||||
| useRunFlow, | |||||
| useSetFlow, | useSetFlow, | ||||
| } from '@/hooks/flow-hooks'; | } from '@/hooks/flow-hooks'; | ||||
| import { useFetchLlmList } from '@/hooks/llmHooks'; | import { useFetchLlmList } from '@/hooks/llmHooks'; | ||||
| export const useFlowIsFetching = () => { | export const useFlowIsFetching = () => { | ||||
| return useIsFetching({ queryKey: ['flowDetail'] }) > 0; | return useIsFetching({ queryKey: ['flowDetail'] }) > 0; | ||||
| }; | }; | ||||
| export const useRunGraph = () => { | |||||
| const { data } = useFetchFlow(); | |||||
| const { runFlow } = useRunFlow(); | |||||
| const { id } = useParams(); | |||||
| const { nodes, edges } = useGraphStore((state) => state); | |||||
| const runGraph = useCallback(() => { | |||||
| const dslComponents = buildDslComponentsByGraph(nodes, edges); | |||||
| runFlow({ | |||||
| id: id!!, | |||||
| dsl: { ...data.dsl, components: dslComponents }, | |||||
| }); | |||||
| }, [nodes, edges, runFlow, id, data]); | |||||
| return { runGraph }; | |||||
| }; | 
| import { useSetModalState } from '@/hooks/commonHooks'; | |||||
| import { Layout } from 'antd'; | import { Layout } from 'antd'; | ||||
| import { useState } from 'react'; | import { useState } from 'react'; | ||||
| import { ReactFlowProvider } from 'reactflow'; | import { ReactFlowProvider } from 'reactflow'; | ||||
| function RagFlow() { | function RagFlow() { | ||||
| const [collapsed, setCollapsed] = useState(false); | const [collapsed, setCollapsed] = useState(false); | ||||
| const { | |||||
| visible: chatDrawerVisible, | |||||
| hideModal: hideChatDrawer, | |||||
| showModal: showChatDrawer, | |||||
| } = useSetModalState(); | |||||
| useFetchDataOnMount(); | useFetchDataOnMount(); | ||||
| <ReactFlowProvider> | <ReactFlowProvider> | ||||
| <Sider setCollapsed={setCollapsed} collapsed={collapsed}></Sider> | <Sider setCollapsed={setCollapsed} collapsed={collapsed}></Sider> | ||||
| <Layout> | <Layout> | ||||
| <FlowHeader></FlowHeader> | |||||
| <FlowHeader showChatDrawer={showChatDrawer}></FlowHeader> | |||||
| <Content style={{ margin: 0 }}> | <Content style={{ margin: 0 }}> | ||||
| <FlowCanvas sideWidth={collapsed ? 0 : 200}></FlowCanvas> | |||||
| <FlowCanvas | |||||
| sideWidth={collapsed ? 0 : 200} | |||||
| chatDrawerVisible={chatDrawerVisible} | |||||
| hideChatDrawer={hideChatDrawer} | |||||
| ></FlowCanvas> | |||||
| </Content> | </Content> | ||||
| </Layout> | </Layout> | ||||
| </ReactFlowProvider> | </ReactFlowProvider> | 
| import { Authorization } from '@/constants/authorization'; | import { Authorization } from '@/constants/authorization'; | ||||
| import { ResponseType } from '@/interfaces/database/base'; | |||||
| import i18n from '@/locales/config'; | import i18n from '@/locales/config'; | ||||
| import authorizationUtil, { getAuthorization } from '@/utils/authorizationUtil'; | import authorizationUtil, { getAuthorization } from '@/utils/authorizationUtil'; | ||||
| import { message, notification } from 'antd'; | import { message, notification } from 'antd'; | ||||
| | 503 | | 503 | ||||
| | 504; | | 504; | ||||
| interface ResponseType { | |||||
| retcode: number; | |||||
| data: any; | |||||
| retmsg: string; | |||||
| status: number; | |||||
| } | |||||
| const errorHandler = (error: { | const errorHandler = (error: { | ||||
| response: Response; | response: Response; | ||||
| message: string; | message: string; |