diff --git a/web/src/constants/agent.ts b/web/src/constants/agent.ts index 28a34111b..3fd17f973 100644 --- a/web/src/constants/agent.ts +++ b/web/src/constants/agent.ts @@ -8,17 +8,14 @@ export const CodeTemplateStrMap = { return f"result: {arg1 + arg2}" `, [ProgrammingLanguage.Javascript]: `const axios = require('axios'); -async function main(args) { +async function main({}) { try { const response = await axios.get('https://github.com/infiniflow/ragflow'); - console.log('Body:', response.data); + return 'Body:' + response.data; } catch (error) { - console.error('Error:', error.message); + return 'Error:' + error.message; } -} - -module.exports = { main }; -`, +}`, }; export enum AgentGlobals { diff --git a/web/src/hooks/use-agent-request.ts b/web/src/hooks/use-agent-request.ts index ea6f2c3df..2eef5cbee 100644 --- a/web/src/hooks/use-agent-request.ts +++ b/web/src/hooks/use-agent-request.ts @@ -6,7 +6,7 @@ import { IDebugSingleRequestBody } from '@/interfaces/request/agent'; import i18n from '@/locales/config'; import { BeginId } from '@/pages/agent/constant'; import { useGetSharedChatSearchParams } from '@/pages/chat/shared-hooks'; -import flowService from '@/services/flow-service'; +import agentService from '@/services/agent-service'; import { buildMessageListWithUuid } from '@/utils/chat'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useDebounce } from 'ahooks'; @@ -85,7 +85,7 @@ export const useFetchAgentTemplates = () => { queryKey: [AgentApiAction.FetchAgentTemplates], initialData: [], queryFn: async () => { - const { data } = await flowService.listTemplates(); + const { data } = await agentService.listTemplates(); if (Array.isArray(data?.data)) { data.data.unshift({ id: uuid(), @@ -121,11 +121,16 @@ export const useFetchAgentListByPage = () => { initialData: { kbs: [], total: 0 }, gcTime: 0, queryFn: async () => { - const { data } = await flowService.listCanvasTeam({ - keywords: debouncedSearchString, - page_size: pagination.pageSize, - page: pagination.current, - }); + const { data } = await agentService.listCanvasTeam( + { + params: { + keywords: debouncedSearchString, + page_size: pagination.pageSize, + page: pagination.current, + }, + }, + true, + ); return data?.data ?? []; }, @@ -159,7 +164,7 @@ export const useUpdateAgentSetting = () => { } = useMutation({ mutationKey: [AgentApiAction.UpdateAgentSetting], mutationFn: async (params: any) => { - const ret = await flowService.settingCanvas(params); + const ret = await agentService.settingCanvas(params); if (ret?.data?.code === 0) { message.success('success'); queryClient.invalidateQueries({ @@ -184,7 +189,7 @@ export const useDeleteAgent = () => { } = useMutation({ mutationKey: [AgentApiAction.DeleteAgent], mutationFn: async (canvasIds: string[]) => { - const { data } = await flowService.removeCanvas({ canvasIds }); + const { data } = await agentService.removeCanvas({ canvasIds }); if (data.code === 0) { queryClient.invalidateQueries({ queryKey: [AgentApiAction.FetchAgentList], @@ -217,7 +222,7 @@ export const useFetchAgent = (): { refetchOnWindowFocus: false, gcTime: 0, queryFn: async () => { - const { data } = await flowService.getCanvas({}, sharedId || id); + const { data } = await agentService.fetchCanvas(sharedId || id); const messageList = buildMessageListWithUuid( get(data, 'data.dsl.messages', []), @@ -240,7 +245,7 @@ export const useResetAgent = () => { } = useMutation({ mutationKey: [AgentApiAction.ResetAgent], mutationFn: async () => { - const { data } = await flowService.resetCanvas({ id }); + const { data } = await agentService.resetCanvas({ id }); return data; }, }); @@ -262,7 +267,7 @@ export const useSetAgent = () => { dsl?: DSL; avatar?: string; }) => { - const { data = {} } = await flowService.setCanvas(params); + const { data = {} } = await agentService.setCanvas(params); if (data.code === 0) { message.success( i18n.t(`message.${params?.id ? 'modified' : 'created'}`), @@ -295,7 +300,7 @@ export const useUploadCanvasFile = () => { }); } - const { data } = await flowService.uploadCanvasFile(nextBody); + const { data } = await agentService.uploadCanvasFile(nextBody); if (data?.code === 0) { message.success(i18n.t('message.uploaded')); } @@ -326,7 +331,7 @@ export const useFetchMessageTrace = () => { enabled: !!id && !!messageId, refetchInterval: 3000, queryFn: async () => { - const { data } = await flowService.trace({ + const { data } = await agentService.trace({ canvas_id: id, message_id: messageId, }); @@ -346,7 +351,7 @@ export const useTestDbConnect = () => { } = useMutation({ mutationKey: [AgentApiAction.TestDbConnect], mutationFn: async (params: any) => { - const ret = await flowService.testDbConnect(params); + const ret = await agentService.testDbConnect(params); if (ret?.data?.code === 0) { message.success(ret?.data?.data); } else { @@ -368,7 +373,7 @@ export const useDebugSingle = () => { } = useMutation({ mutationKey: [AgentApiAction.FetchInputForm], mutationFn: async (params: IDebugSingleRequestBody) => { - const ret = await flowService.debugSingle({ id, ...params }); + const ret = await agentService.debugSingle({ id, ...params }); if (ret?.data?.code !== 0) { message.error(ret?.data?.message); } @@ -387,7 +392,7 @@ export const useFetchInputForm = (componentId?: string) => { initialData: {}, enabled: !!id && !!componentId, queryFn: async () => { - const { data } = await flowService.inputForm({ + const { data } = await agentService.inputForm({ id, component_id: componentId, }); @@ -408,7 +413,7 @@ export const useFetchVersionList = () => { initialData: [], gcTime: 0, queryFn: async () => { - const { data } = await flowService.getListVersion({}, id); + const { data } = await agentService.fetchVersionList(id); return data?.data ?? []; }, @@ -431,7 +436,7 @@ export const useFetchVersion = ( queryFn: async () => { if (!version_id) return undefined; - const { data } = await flowService.getVersion({}, version_id); + const { data } = await agentService.fetchVersion(version_id); return data?.data ?? undefined; }, diff --git a/web/src/pages/agent/form/agent-form/index.tsx b/web/src/pages/agent/form/agent-form/index.tsx index 20966b6f6..8a0a213d9 100644 --- a/web/src/pages/agent/form/agent-form/index.tsx +++ b/web/src/pages/agent/form/agent-form/index.tsx @@ -12,7 +12,6 @@ import { } from '@/components/ui/form'; import { Input, NumberInput } from '@/components/ui/input'; import { RAGFlowSelect } from '@/components/ui/select'; -import { Textarea } from '@/components/ui/textarea'; import { buildOptions } from '@/utils/form'; import { zodResolver } from '@hookform/resolvers/zod'; import { memo, useMemo } from 'react'; @@ -100,23 +99,7 @@ function AgentForm({ node }: INextOperatorForm) { }} > - {isSubAgent && ( - <> - - ( - - Subagent Input - - - - - )} - /> - - )} + {isSubAgent && } (methods); + +export default agentService; diff --git a/web/src/utils/api.ts b/web/src/utils/api.ts index 81142022a..93272175d 100644 --- a/web/src/utils/api.ts +++ b/web/src/utils/api.ts @@ -148,6 +148,9 @@ export default { trace: `${api_host}/canvas/trace`, // agent inputForm: `${api_host}/canvas/input_form`, + fetchVersionList: (id: string) => `${api_host}/canvas/getlistversion/${id}`, + fetchVersion: (id: string) => `${api_host}/canvas/getversion/${id}`, + fetchCanvas: (id: string) => `${api_host}/canvas/get/${id}`, // mcp server listMcpServer: `${api_host}/mcp_server/list`, diff --git a/web/src/utils/next-request.ts b/web/src/utils/next-request.ts new file mode 100644 index 000000000..3b4285646 --- /dev/null +++ b/web/src/utils/next-request.ts @@ -0,0 +1,146 @@ +import message from '@/components/ui/message'; +import { Authorization } from '@/constants/authorization'; +import i18n from '@/locales/config'; +import authorizationUtil, { + getAuthorization, + redirectToLogin, +} from '@/utils/authorization-util'; +import { notification } from 'antd'; +import axios from 'axios'; +import { convertTheKeysOfTheObjectToSnake } from './common-util'; + +const FAILED_TO_FETCH = 'Failed to fetch'; + +export const RetcodeMessage = { + 200: i18n.t('message.200'), + 201: i18n.t('message.201'), + 202: i18n.t('message.202'), + 204: i18n.t('message.204'), + 400: i18n.t('message.400'), + 401: i18n.t('message.401'), + 403: i18n.t('message.403'), + 404: i18n.t('message.404'), + 406: i18n.t('message.406'), + 410: i18n.t('message.410'), + 413: i18n.t('message.413'), + 422: i18n.t('message.422'), + 500: i18n.t('message.500'), + 502: i18n.t('message.502'), + 503: i18n.t('message.503'), + 504: i18n.t('message.504'), +}; +export type ResultCode = + | 200 + | 201 + | 202 + | 204 + | 400 + | 401 + | 403 + | 404 + | 406 + | 410 + | 413 + | 422 + | 500 + | 502 + | 503 + | 504; + +const errorHandler = (error: { + response: Response; + message: string; +}): Response => { + const { response } = error; + if (error.message === FAILED_TO_FETCH) { + notification.error({ + description: i18n.t('message.networkAnomalyDescription'), + message: i18n.t('message.networkAnomaly'), + }); + } else { + if (response && response.status) { + const errorText = + RetcodeMessage[response.status as ResultCode] || response.statusText; + const { status, url } = response; + notification.error({ + message: `${i18n.t('message.requestError')} ${status}: ${url}`, + description: errorText, + }); + } + } + return response ?? { data: { code: 1999 } }; +}; + +const request = axios.create({ + // errorHandler, + timeout: 300000, + // getResponse: true, +}); + +request.interceptors.request.use( + (config) => { + const data = convertTheKeysOfTheObjectToSnake(config.data); + const params = convertTheKeysOfTheObjectToSnake(config.params); + + const newConfig = { ...config, data, params }; + + if (!newConfig.skipToken) { + newConfig.headers.set(Authorization, getAuthorization()); + } + + return newConfig; + }, + function (error) { + return Promise.reject(error); + }, +); + +request.interceptors.response.use( + async (response) => { + if (response?.status === 413 || response?.status === 504) { + message.error(RetcodeMessage[response?.status as ResultCode]); + } + + if (response.config.responseType === 'blob') { + return response; + } + const data = response?.data; + if (data?.code === 100) { + message.error(data?.message); + } else if (data?.code === 401) { + notification.error({ + message: data?.message, + description: data?.message, + duration: 3, + }); + authorizationUtil.removeAll(); + redirectToLogin(); + } else if (data?.code !== 0) { + notification.error({ + message: `${i18n.t('message.hint')} : ${data?.code}`, + description: data?.message, + duration: 3, + }); + } + return response; + }, + function (error) { + console.log('🚀 ~ error:', error); + errorHandler(error); + return Promise.reject(error); + }, +); + +export default request; + +export const get = (url: string) => { + return request.get(url); +}; + +export const post = (url: string, body: any) => { + return request.post(url, { data: body }); +}; + +export const drop = () => {}; + +export const put = () => {}; diff --git a/web/src/utils/register-server.ts b/web/src/utils/register-server.ts index 3aa987538..c70ebaf32 100644 --- a/web/src/utils/register-server.ts +++ b/web/src/utils/register-server.ts @@ -1,5 +1,8 @@ +import { AxiosRequestConfig, AxiosResponse } from 'axios'; +import { isObject } from 'lodash'; import omit from 'lodash/omit'; import { RequestMethod } from 'umi-request'; +import request from './next-request'; type Service = Record< T, @@ -39,3 +42,39 @@ const registerServer = ( }; export default registerServer; + +export function registerNextServer( + requestRecord: Record< + T, + { url: string | ((...args: Array) => string); method: string } + >, +) { + type Server = Record< + T, + ( + config?: + | AxiosRequestConfig + | Record + | string + | number + | boolean + | undefined, + useAxiosNativeConfig?: boolean, + ) => Promise> + >; + const server: Server = {} as Server; + + for (const name in requestRecord) { + if (Object.prototype.hasOwnProperty.call(requestRecord, name)) { + const { url, method } = requestRecord[name]; + server[name] = (config, useAxiosNativeConfig = false) => { + const nextConfig = useAxiosNativeConfig ? config : { data: config }; + const finalConfig = isObject(nextConfig) ? nextConfig : {}; + const nextUrl = typeof url === 'function' ? url(config) : url; + return request({ url: nextUrl, method, ...finalConfig }); + }; + } + } + + return server; +}