feat: admin add custom plugin (#2582)

* feat: admin add custom plugin

* refresh plugins

* plugin input box ui

* fix: run plugin varialbes error

* perf: comment

* fix: ts
This commit is contained in:
Archer
2024-08-30 22:45:35 +08:00
committed by GitHub
parent 9d5fd24085
commit 060492dbf7
18 changed files with 127 additions and 84 deletions

View File

@@ -54,30 +54,31 @@ curl --location --request POST 'https://{{host}}/api/admin/initv4810' \
5. 新增 - 工作流本次编辑记录,取代自动保存 5. 新增 - 工作流本次编辑记录,取代自动保存
6. 新增 - 工作流版本支持重命名 6. 新增 - 工作流版本支持重命名
7. 新增 - 应用调用迁移成单独节点,同时可以传递全局变量和用户的文件。 7. 新增 - 应用调用迁移成单独节点,同时可以传递全局变量和用户的文件。
8. 商业版新增 - 飞书机器人接入 8. 新增 - 插件增加使用说明配置。
9. 商业版新增 - 公众号接入接入 9. 商业版新增 - 飞书机器人接入
10. 商业版新增 - 自助开票申请 10. 商业版新增 - 公众号接入接入
11. 商业版新增 - SSO 定制 11. 商业版新增 - 自助开票申请
12. 优化 - SSE 响应优化。 12. 商业版新增 - SSO 定制
13. 优化 - 无 SSL 证书情况下,优化复制 13. 优化 - SSE 响应优化
14. 优化 - 单选框打开后自动滚动到选中的位置 14. 优化 - 无 SSL 证书情况下,优化复制
15. 优化 - 知识库集合禁用,目录禁用会递归修改其下所有 children 的禁用状态 15. 优化 - 单选框打开后自动滚动到选中的位置
16. 优化 - 节点选择,避免切换 tab 时候path 加载报错 16. 优化 - 知识库集合禁用,目录禁用会递归修改其下所有 children 的禁用状态
17. 优化 - 最新 React Markdown 组件,支持 Base64 图片 17. 优化 - 节点选择,避免切换 tab 时候path 加载报错
18. 优化 - 知识库列表 UI 18. 优化 - 最新 React Markdown 组件,支持 Base64 图片
19. 优化 - 知识库详情页 UI。 19. 优化 - 知识库列表 UI。
20. 优化 - 支持无网络配置情况下运行 20. 优化 - 知识库详情页 UI
21. 优化 - 部分全局变量,增加数据类型约束 21. 优化 - 支持无网络配置情况下运行
22. 修复 - 全局变量 key 可能重复 22. 优化 - 部分全局变量,增加数据类型约束
23. 修复 - Prompt 模式调用工具stream=false 模式下,会携带 0: 开头标记 23. 修复 - 全局变量 key 可能重复
24. 修复 - 对话日志鉴权问题:仅为 APP 管理员的用户,无法查看对话日志详情 24. 修复 - Prompt 模式调用工具stream=false 模式下,会携带 0: 开头标记
25. 修复 - 选择 Milvus 部署时,无法导出知识库。 25. 修复 - 对话日志鉴权问题:仅为 APP 管理员的用户,无法查看对话日志详情。
26. 修复 - 创建 APP 副本,无法复制系统配置。 26. 修复 - 选择 Milvus 部署时,无法导出知识库。
27. 修复 - 图片识别模式下,自动解析图片链接正则不够严谨问题 27. 修复 - 创建 APP 副本,无法复制系统配置
28. 修复 - 内容提取的数据类型与输出数据类型未一致 28. 修复 - 图片识别模式下,自动解析图片链接正则不够严谨问题
29. 修复 - 工作流运行时间统计错误 29. 修复 - 内容提取的数据类型与输出数据类型未一致
30. 修复 - stream 模式下,工具调用有可能出现 undefined 30. 修复 - 工作流运行时间统计错误。
31. 修复 - 全局变量在 API 中无法持久化。 31. 修复 - stream 模式下,工具调用有可能出现 undefined
32. 修复 - OpenAPIdetail=false模式下不应该返回 tool 调用结果,仅返回文字。(可解决 cow 不适配问题) 32. 修复 - 全局变量在 API 中无法持久化。
33. 修复 - 知识库标签重复加载。 33. 修复 - OpenAPIdetail=false模式下不应该返回 tool 调用结果,仅返回文字。(可解决 cow 不适配问题)
34. 修复 - Debug 模式下,循环调用边问题 34. 修复 - 知识库标签重复加载
35. 修复 - Debug 模式下,循环调用边问题。

View File

@@ -169,10 +169,10 @@ export type DispatchNodeResponseType = {
export type DispatchNodeResultType<T> = { export type DispatchNodeResultType<T> = {
[DispatchNodeResponseKeyEnum.skipHandleId]?: string[]; // skip some edge handle id [DispatchNodeResponseKeyEnum.skipHandleId]?: string[]; // skip some edge handle id
[DispatchNodeResponseKeyEnum.nodeResponse]?: DispatchNodeResponseType; // The node response detail [DispatchNodeResponseKeyEnum.nodeResponse]?: DispatchNodeResponseType; // The node response detail
[DispatchNodeResponseKeyEnum.nodeDispatchUsages]?: ChatNodeUsageType[]; // [DispatchNodeResponseKeyEnum.nodeDispatchUsages]?: ChatNodeUsageType[]; // Node total usage
[DispatchNodeResponseKeyEnum.childrenResponses]?: DispatchNodeResultType[]; [DispatchNodeResponseKeyEnum.childrenResponses]?: DispatchNodeResultType[]; // Children node response
[DispatchNodeResponseKeyEnum.toolResponses]?: ToolRunResponseItemType; [DispatchNodeResponseKeyEnum.toolResponses]?: ToolRunResponseItemType; // Tool response
[DispatchNodeResponseKeyEnum.assistantResponses]?: ChatItemValueItemType[]; [DispatchNodeResponseKeyEnum.assistantResponses]?: ChatItemValueItemType[]; // Assistant response(Store to db)
} & T; } & T;
/* Single node props */ /* Single node props */

View File

@@ -13,7 +13,7 @@ import { HttpNode468 } from './system/http468';
import { ToolModule } from './system/tools'; import { ToolModule } from './system/tools';
import { StopToolNode } from './system/stopTool'; import { StopToolNode } from './system/stopTool';
import { RunAppModule } from './system/runApp/index'; import { RunAppModule } from './system/abandoned/runApp/index';
import { PluginInputModule } from './system/pluginInput'; import { PluginInputModule } from './system/pluginInput';
import { PluginOutputModule } from './system/pluginOutput'; import { PluginOutputModule } from './system/pluginOutput';
import { RunPluginModule } from './system/runPlugin'; import { RunPluginModule } from './system/runPlugin';

View File

@@ -3,17 +3,17 @@ import {
FlowNodeInputTypeEnum, FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum, FlowNodeOutputTypeEnum,
FlowNodeTypeEnum FlowNodeTypeEnum
} from '../../../node/constant'; } from '../../../../node/constant';
import { FlowNodeTemplateType } from '../../../type/node.d'; import { FlowNodeTemplateType } from '../../../../type/node';
import { import {
WorkflowIOValueTypeEnum, WorkflowIOValueTypeEnum,
NodeInputKeyEnum, NodeInputKeyEnum,
NodeOutputKeyEnum, NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum FlowNodeTemplateTypeEnum
} from '../../../constants'; } from '../../../../constants';
import { Input_Template_History, Input_Template_UserChatInput } from '../../input'; import { Input_Template_History, Input_Template_UserChatInput } from '../../../input';
import { getHandleConfig } from '../../utils'; import { getHandleConfig } from '../../../utils';
import { i18nT } from '../../../../../../web/i18n/utils'; import { i18nT } from '../../../../../../../web/i18n/utils';
export const RunAppModule: FlowNodeTemplateType = { export const RunAppModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.runApp, id: FlowNodeTypeEnum.runApp,

View File

@@ -28,7 +28,7 @@ export type WorkflowTemplateBasicType = {
}; };
export type WorkflowTemplateType = { export type WorkflowTemplateType = {
id: string; id: string;
parentId?: string; parentId?: ParentIdType;
isFolder?: boolean; isFolder?: boolean;
name: string; name: string;
@@ -62,6 +62,8 @@ export type TemplateMarketListItemType = {
// system plugin // system plugin
export type SystemPluginTemplateItemType = WorkflowTemplateType & { export type SystemPluginTemplateItemType = WorkflowTemplateType & {
customWorkflow?: string;
templateType: FlowNodeTemplateTypeEnum; templateType: FlowNodeTemplateTypeEnum;
isTool?: boolean; isTool?: boolean;

View File

@@ -32,6 +32,7 @@ import { IfElseResultEnum } from './template/system/ifElse/constant';
import { RuntimeNodeItemType } from './runtime/type'; import { RuntimeNodeItemType } from './runtime/type';
import { getReferenceVariableValue } from './runtime/utils'; import { getReferenceVariableValue } from './runtime/utils';
import { Input_Template_History, Input_Template_UserChatInput } from './template/input'; import { Input_Template_History, Input_Template_UserChatInput } from './template/input';
import { i18nT } from '../../../web/i18n/utils';
export const getHandleId = (nodeId: string, type: 'source' | 'target', key: string) => { export const getHandleId = (nodeId: string, type: 'source' | 'target', key: string) => {
return `${nodeId}-${type}-${key}`; return `${nodeId}-${type}-${key}`;
@@ -254,8 +255,8 @@ export const appData2FlowNodeIO = ({
id: NodeOutputKeyEnum.history, id: NodeOutputKeyEnum.history,
key: NodeOutputKeyEnum.history, key: NodeOutputKeyEnum.history,
required: true, required: true,
label: 'core.module.output.label.New context', label: i18nT('common:core.module.output.label.New context'),
description: 'core.module.output.description.New context', description: i18nT('common:core.module.output.description.New context'),
valueType: WorkflowIOValueTypeEnum.chatHistory, valueType: WorkflowIOValueTypeEnum.chatHistory,
valueDesc: chatHistoryValueDesc, valueDesc: chatHistoryValueDesc,
type: FlowNodeOutputTypeEnum.static type: FlowNodeOutputTypeEnum.static
@@ -264,8 +265,8 @@ export const appData2FlowNodeIO = ({
id: NodeOutputKeyEnum.answerText, id: NodeOutputKeyEnum.answerText,
key: NodeOutputKeyEnum.answerText, key: NodeOutputKeyEnum.answerText,
required: false, required: false,
label: 'core.module.output.label.Ai response content', label: i18nT('common:core.module.output.label.Ai response content'),
description: 'core.module.output.description.Ai response content', description: i18nT('common:core.module.output.description.Ai response content'),
valueType: WorkflowIOValueTypeEnum.string, valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static type: FlowNodeOutputTypeEnum.static
} }
@@ -325,6 +326,9 @@ export const updatePluginInputByVariables = (
); );
}; };
/* Remove pluginInput variables from global variables
(completions api: Plugin input get value from global variables)
*/
export const removePluginInputVariables = ( export const removePluginInputVariables = (
variables: Record<string, any>, variables: Record<string, any>,
nodes: RuntimeNodeItemType[] nodes: RuntimeNodeItemType[]

View File

@@ -24,7 +24,8 @@ const SystemPluginSchema = new Schema({
currentCost: { currentCost: {
type: Number, type: Number,
default: 0 default: 0
} },
customConfig: Object
}); });
SystemPluginSchema.index({ pluginId: 1 }); SystemPluginSchema.index({ pluginId: 1 });

View File

@@ -1,4 +1,8 @@
import { SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type'; import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants';
import {
SystemPluginTemplateItemType,
WorkflowTemplateBasicType
} from '@fastgpt/global/core/workflow/type';
export type SystemPluginConfigSchemaType = { export type SystemPluginConfigSchemaType = {
pluginId: string; pluginId: string;
@@ -7,4 +11,14 @@ export type SystemPluginConfigSchemaType = {
currentCost: number; currentCost: number;
isActive: boolean; isActive: boolean;
inputConfig: SystemPluginTemplateItemType['inputConfig']; inputConfig: SystemPluginTemplateItemType['inputConfig'];
customConfig?: {
name: string;
avatar: string;
intro?: string;
version: string;
weight?: number;
workflow: WorkflowTemplateBasicType;
templateType: FlowNodeTemplateTypeEnum;
};
}; };

View File

@@ -1,6 +1,7 @@
/* Abandoned */
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d'; import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type'; import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
import { SelectAppItemType } from '@fastgpt/global/core/workflow/template/system/runApp/type'; import { SelectAppItemType } from '@fastgpt/global/core/workflow/template/system/abandoned/runApp/type';
import { dispatchWorkFlow } from '../index'; import { dispatchWorkFlow } from '../index';
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants'; import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants';

View File

@@ -11,7 +11,7 @@ import {
} from '@fastgpt/global/core/workflow/runtime/utils'; } from '@fastgpt/global/core/workflow/runtime/utils';
import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants'; import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import { getHistories } from '../utils'; import { filterSystemVariables, getHistories } from '../utils';
import { chatValue2RuntimePrompt, runtimePrompt2ChatsValue } from '@fastgpt/global/core/chat/adapt'; import { chatValue2RuntimePrompt, runtimePrompt2ChatsValue } from '@fastgpt/global/core/chat/adapt';
import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type'; import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';
import { authAppByTmbId } from '../../../../support/permission/app/auth'; import { authAppByTmbId } from '../../../../support/permission/app/auth';
@@ -34,10 +34,11 @@ export const dispatchRunAppNode = async (props: Props): Promise<Response> => {
query, query,
node: { pluginId }, node: { pluginId },
workflowStreamResponse, workflowStreamResponse,
params params,
variables
} = props; } = props;
const { userChatInput, history, ...variables } = params; const { userChatInput, history, ...childrenAppVariables } = params;
if (!userChatInput) { if (!userChatInput) {
return Promise.reject('Input is empty'); return Promise.reject('Input is empty');
} }
@@ -63,6 +64,13 @@ export const dispatchRunAppNode = async (props: Props): Promise<Response> => {
const chatHistories = getHistories(history, histories); const chatHistories = getHistories(history, histories);
const { files } = chatValue2RuntimePrompt(query); const { files } = chatValue2RuntimePrompt(query);
// Concat variables
const systemVariables = filterSystemVariables(variables);
const childrenRunVariables = {
...systemVariables,
...childrenAppVariables
};
const { flowResponses, flowUsages, assistantResponses } = await dispatchWorkFlow({ const { flowResponses, flowUsages, assistantResponses } = await dispatchWorkFlow({
...props, ...props,
app: appData, app: appData,
@@ -76,7 +84,7 @@ export const dispatchRunAppNode = async (props: Props): Promise<Response> => {
files, files,
text: userChatInput text: userChatInput
}), }),
variables: variables variables: childrenRunVariables
}); });
const completeMessages = chatHistories.concat([ const completeMessages = chatHistories.concat([

View File

@@ -31,7 +31,7 @@ import { dispatchAnswer } from './tools/answer';
import { dispatchClassifyQuestion } from './agent/classifyQuestion'; import { dispatchClassifyQuestion } from './agent/classifyQuestion';
import { dispatchContentExtract } from './agent/extract'; import { dispatchContentExtract } from './agent/extract';
import { dispatchHttp468Request } from './tools/http468'; import { dispatchHttp468Request } from './tools/http468';
import { dispatchAppRequest } from './tools/runApp'; import { dispatchAppRequest } from './abandoned/runApp';
import { dispatchQueryExtension } from './tools/queryExternsion'; import { dispatchQueryExtension } from './tools/queryExternsion';
import { dispatchRunPlugin } from './plugin/run'; import { dispatchRunPlugin } from './plugin/run';
import { dispatchPluginInput } from './plugin/runInput'; import { dispatchPluginInput } from './plugin/runInput';
@@ -63,7 +63,7 @@ import {
InteractiveNodeResponseItemType, InteractiveNodeResponseItemType,
UserSelectInteractive UserSelectInteractive
} from '@fastgpt/global/core/workflow/template/system/userSelect/type'; } from '@fastgpt/global/core/workflow/template/system/userSelect/type';
import { dispatchRunAppNode } from './agent/runAppModule'; import { dispatchRunAppNode } from './agent/runApp';
const callbackMap: Record<FlowNodeTypeEnum, Function> = { const callbackMap: Record<FlowNodeTypeEnum, Function> = {
[FlowNodeTypeEnum.workflowStart]: dispatchWorkflowStart, [FlowNodeTypeEnum.workflowStart]: dispatchWorkflowStart,
@@ -74,7 +74,6 @@ const callbackMap: Record<FlowNodeTypeEnum, Function> = {
[FlowNodeTypeEnum.classifyQuestion]: dispatchClassifyQuestion, [FlowNodeTypeEnum.classifyQuestion]: dispatchClassifyQuestion,
[FlowNodeTypeEnum.contentExtract]: dispatchContentExtract, [FlowNodeTypeEnum.contentExtract]: dispatchContentExtract,
[FlowNodeTypeEnum.httpRequest468]: dispatchHttp468Request, [FlowNodeTypeEnum.httpRequest468]: dispatchHttp468Request,
[FlowNodeTypeEnum.runApp]: dispatchAppRequest,
[FlowNodeTypeEnum.appModule]: dispatchRunAppNode, [FlowNodeTypeEnum.appModule]: dispatchRunAppNode,
[FlowNodeTypeEnum.pluginModule]: dispatchRunPlugin, [FlowNodeTypeEnum.pluginModule]: dispatchRunPlugin,
[FlowNodeTypeEnum.pluginInput]: dispatchPluginInput, [FlowNodeTypeEnum.pluginInput]: dispatchPluginInput,
@@ -95,7 +94,9 @@ const callbackMap: Record<FlowNodeTypeEnum, Function> = {
[FlowNodeTypeEnum.systemConfig]: dispatchSystemConfig, [FlowNodeTypeEnum.systemConfig]: dispatchSystemConfig,
[FlowNodeTypeEnum.pluginConfig]: () => Promise.resolve(), [FlowNodeTypeEnum.pluginConfig]: () => Promise.resolve(),
[FlowNodeTypeEnum.emptyNode]: () => Promise.resolve(), [FlowNodeTypeEnum.emptyNode]: () => Promise.resolve(),
[FlowNodeTypeEnum.globalVariable]: () => Promise.resolve() [FlowNodeTypeEnum.globalVariable]: () => Promise.resolve(),
[FlowNodeTypeEnum.runApp]: dispatchAppRequest // abandoned
}; };
type Props = ChatDispatchProps & { type Props = ChatDispatchProps & {

View File

@@ -9,10 +9,10 @@ import {
storeNodes2RuntimeNodes storeNodes2RuntimeNodes
} from '@fastgpt/global/core/workflow/runtime/utils'; } from '@fastgpt/global/core/workflow/runtime/utils';
import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type'; import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';
import { updateToolInputValue } from '../agent/runTool/utils';
import { authPluginByTmbId } from '../../../../support/permission/app/auth'; import { authPluginByTmbId } from '../../../../support/permission/app/auth';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { computedPluginUsage } from '../../../app/plugin/utils'; import { computedPluginUsage } from '../../../app/plugin/utils';
import { filterSystemVariables } from '../utils';
type RunPluginProps = ModuleDispatchProps<{ type RunPluginProps = ModuleDispatchProps<{
[key: string]: any; [key: string]: any;
@@ -25,7 +25,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
app: workflowApp, app: workflowApp,
mode, mode,
teamId, teamId,
params: data params: data // Plugin input
} = props; } = props;
if (!pluginId) { if (!pluginId) {
@@ -41,32 +41,31 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
const plugin = await getPluginRuntimeById(pluginId); const plugin = await getPluginRuntimeById(pluginId);
// concat dynamic inputs const runtimeNodes = storeNodes2RuntimeNodes(
const inputModule = plugin.nodes.find( plugin.nodes,
(item) => item.flowNodeType === FlowNodeTypeEnum.pluginInput getWorkflowEntryNodeIds(plugin.nodes)
); ).map((node) => {
if (!inputModule) return Promise.reject('Plugin error, It has no set input.'); // Update plugin input value
if (node.flowNodeType === FlowNodeTypeEnum.pluginInput) {
return {
...node,
showStatus: false,
inputs: node.inputs.map((input) => ({
...input,
value: data[input.key] ?? input.value
}))
};
}
return {
...node,
showStatus: false
};
});
const { flowResponses, flowUsages, assistantResponses } = await dispatchWorkFlow({ const { flowResponses, flowUsages, assistantResponses } = await dispatchWorkFlow({
...props, ...props,
runtimeNodes: storeNodes2RuntimeNodes(plugin.nodes, getWorkflowEntryNodeIds(plugin.nodes)).map( variables: filterSystemVariables(props.variables),
(node) => { runtimeNodes,
if (node.flowNodeType === FlowNodeTypeEnum.pluginInput) {
return {
...node,
showStatus: false,
inputs: updateToolInputValue({
inputs: node.inputs,
params: data
})
};
}
return {
...node,
showStatus: false
};
}
),
runtimeEdges: initWorkflowEdgeStatus(plugin.edges) runtimeEdges: initWorkflowEdgeStatus(plugin.edges)
}); });

View File

@@ -144,6 +144,15 @@ export const removeSystemVariable = (variables: Record<string, any>) => {
return copyVariables; return copyVariables;
}; };
export const filterSystemVariables = (variables: Record<string, any>) => {
return {
appId: variables.appId,
chatId: variables.chatId,
responseChatItemId: variables.responseChatItemId,
histories: variables.histories,
cTime: variables.cTime
};
};
export const formatHttpError = (error: any) => { export const formatHttpError = (error: any) => {
return { return {

View File

@@ -83,6 +83,7 @@ const RenderInput = () => {
rounded={'md'} rounded={'md'}
fontSize={'sm'} fontSize={'sm'}
color={'myGray.600'} color={'myGray.600'}
mb={4}
> >
<Markdown source={chatConfig.instruction} /> <Markdown source={chatConfig.instruction} />
</Box> </Box>

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import { ModalBody, ModalFooter, Button } from '@chakra-ui/react'; import { ModalBody, ModalFooter, Button } from '@chakra-ui/react';
import MyModal from '@fastgpt/web/components/common/MyModal'; import MyModal from '@fastgpt/web/components/common/MyModal';
import { SelectAppItemType } from '@fastgpt/global/core/workflow/template/system/runApp/type'; import type { SelectAppItemType } from '@fastgpt/global/core/workflow/template/system/abandoned/runApp/type';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import SelectOneResource from '@/components/common/folder/SelectOneResource'; import SelectOneResource from '@/components/common/folder/SelectOneResource';
import { import {

View File

@@ -1,7 +1,7 @@
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import type { RenderInputProps } from '../type'; import type { RenderInputProps } from '../type';
import { Box, Button, useDisclosure } from '@chakra-ui/react'; import { Box, Button, useDisclosure } from '@chakra-ui/react';
import { SelectAppItemType } from '@fastgpt/global/core/workflow/template/system/runApp/type'; import type { SelectAppItemType } from '@fastgpt/global/core/workflow/template/system/abandoned/runApp/type';
import Avatar from '@fastgpt/web/components/common/Avatar'; import Avatar from '@fastgpt/web/components/common/Avatar';
import SelectAppModal from '../../../../SelectAppModal'; import SelectAppModal from '../../../../SelectAppModal';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';

View File

@@ -27,8 +27,10 @@ const refetchSystemPlugins = () => {
const changeStream = MongoSystemPluginSchema.watch(); const changeStream = MongoSystemPluginSchema.watch();
changeStream.on('change', async (change) => { changeStream.on('change', async (change) => {
try { setTimeout(() => {
getSystemPlugins(true); try {
} catch (error) {} getSystemPlugins(true);
} catch (error) {}
}, 5000);
}); });
}; };