diff --git a/packages/service/core/plugin/type.d.ts b/packages/service/core/plugin/type.d.ts index 9f092972b..68f2753e4 100644 --- a/packages/service/core/plugin/type.d.ts +++ b/packages/service/core/plugin/type.d.ts @@ -1,5 +1,6 @@ import { PluginTemplateType } from '@fastgpt/global/core/plugin/type.d'; declare global { + var communityPluginsV1: PluginTemplateType[]; var communityPlugins: PluginTemplateType[]; } diff --git a/packages/service/core/workflow/dispatchV1/index.ts b/packages/service/core/workflow/dispatchV1/index.ts index e03b7196c..ee997adab 100644 --- a/packages/service/core/workflow/dispatchV1/index.ts +++ b/packages/service/core/workflow/dispatchV1/index.ts @@ -279,7 +279,7 @@ export async function dispatchWorkFlowV1({ )?.targets?.length; return moduleOutput(module, { - [NodeOutputKeyEnum.finish]: true, + finish: true, [NodeOutputKeyEnum.userChatInput]: hasUserChatInputTarget ? params[NodeOutputKeyEnum.userChatInput] : undefined, @@ -295,7 +295,7 @@ export async function dispatchWorkFlowV1({ modules.forEach((item) => { item.isEntry = false; }); - + // console.log(JSON.stringify(runningModules, null, 2)); initModules.map((module) => moduleInput(module, { ...startParams, diff --git a/packages/service/core/workflow/dispatchV1/plugin/run.ts b/packages/service/core/workflow/dispatchV1/plugin/run.ts index 860d6c277..350f23919 100644 --- a/packages/service/core/workflow/dispatchV1/plugin/run.ts +++ b/packages/service/core/workflow/dispatchV1/plugin/run.ts @@ -1,13 +1,20 @@ // @ts-nocheck + import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/type'; import { dispatchWorkFlowV1 } from '../index'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; -import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; +import { + FlowNodeTemplateTypeEnum, + NodeInputKeyEnum +} from '@fastgpt/global/core/workflow/constants'; import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants'; -import { getPluginRuntimeById } from '../../../plugin/controller'; +import { splitCombinePluginId } from '../../../plugin/controller'; import { authPluginCanUse } from '../../../../support/permission/auth/plugin'; import { setEntryEntries, DYNAMIC_INPUT_KEY } from '../utils'; import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type'; +import { PluginRuntimeType, PluginTemplateType } from '@fastgpt/global/core/plugin/type'; +import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; +import { MongoPlugin } from '../../../plugin/schema'; type RunPluginProps = ModuleDispatchProps<{ [NodeInputKeyEnum.pluginId]: string; @@ -15,6 +22,45 @@ type RunPluginProps = ModuleDispatchProps<{ }>; type RunPluginResponse = DispatchNodeResultType<{}>; +const getPluginTemplateById = async (id: string): Promise => { + const { source, pluginId } = await splitCombinePluginId(id); + if (source === PluginSourceEnum.community) { + const item = global.communityPluginsV1?.find((plugin) => plugin.id === pluginId); + + if (!item) return Promise.reject('plugin not found'); + + return item; + } + if (source === PluginSourceEnum.personal) { + const item = await MongoPlugin.findById(id).lean(); + if (!item) return Promise.reject('plugin not found'); + return { + id: String(item._id), + teamId: String(item.teamId), + name: item.name, + avatar: item.avatar, + intro: item.intro, + showStatus: true, + source: PluginSourceEnum.personal, + modules: item.modules, + templateType: FlowNodeTemplateTypeEnum.personalPlugin + }; + } + return Promise.reject('plugin not found'); +}; + +const getPluginRuntimeById = async (id: string): Promise => { + const plugin = await getPluginTemplateById(id); + + return { + teamId: plugin.teamId, + name: plugin.name, + avatar: plugin.avatar, + showStatus: plugin.showStatus, + modules: plugin.modules + }; +}; + export const dispatchRunPlugin = async (props: RunPluginProps): Promise => { const { mode, @@ -31,7 +77,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise item.flowType === FlowNodeTypeEnum.pluginInput); + const inputModule = plugin.modules.find((item) => item.flowType === FlowNodeTypeEnum.pluginInput); if (!inputModule) return Promise.reject('Plugin error, It has no set input.'); const hasDynamicInput = inputModule.inputs.find((input) => input.key === DYNAMIC_INPUT_KEY); @@ -56,7 +102,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise ({ + modules: setEntryEntries(plugin.modules).map((module) => ({ ...module, showStatus: false })), diff --git a/packages/service/core/workflow/dispatchV1/tools/answer.ts b/packages/service/core/workflow/dispatchV1/tools/answer.ts index 928970794..e7b42d75a 100644 --- a/packages/service/core/workflow/dispatchV1/tools/answer.ts +++ b/packages/service/core/workflow/dispatchV1/tools/answer.ts @@ -32,6 +32,6 @@ export const dispatchAnswer = (props: Record): AnswerResponse => { } return { - [NodeOutputKeyEnum.answerText]: formatText + [NodeOutputKeyEnum.answerText]: `\n${formatText}` }; }; diff --git a/projects/app/data/pluginTemplates/customFeedback.json b/projects/app/data/pluginTemplates/customFeedback.json index 7933b4b33..778211e9d 100644 --- a/projects/app/data/pluginTemplates/customFeedback.json +++ b/projects/app/data/pluginTemplates/customFeedback.json @@ -142,7 +142,7 @@ "description": "core.module.input.description.Http Request Url", "placeholder": "https://api.ai.com/getInventory", "required": false, - "value": "/api/plugins/customFeedback" + "value": "/api/plugins/customFeedback/v2" }, { "key": "system_httpHeader", diff --git a/projects/app/data/pluginTemplates/textEditor.json b/projects/app/data/pluginTemplates/textEditor.json index c280dd5ca..0a8caa597 100644 --- a/projects/app/data/pluginTemplates/textEditor.json +++ b/projects/app/data/pluginTemplates/textEditor.json @@ -167,7 +167,7 @@ "description": "core.module.input.description.Http Request Url", "placeholder": "https://api.ai.com/getInventory", "required": false, - "value": "/api/plugins/textEditor" + "value": "/api/plugins/textEditor/v2" }, { "key": "system_httpHeader", diff --git a/projects/app/data/pluginTemplates/v1/customFeedback.json b/projects/app/data/pluginTemplates/v1/customFeedback.json new file mode 100644 index 000000000..9ef9e35f2 --- /dev/null +++ b/projects/app/data/pluginTemplates/v1/customFeedback.json @@ -0,0 +1,342 @@ +{ + "author": "FastGPT Team", + "templateType": "other", + "name": "自定义反馈", + "avatar": "/imgs/module/customFeedback.svg", + "intro": "该模块被触发时,会给当前的对话记录增加一条反馈。可用于自动记录对话效果等。", + "showStatus": false, + "isTool": false, + "weight": 0, + "modules": [ + { + "moduleId": "w90mfp", + "name": "定义插件输入", + "flowType": "pluginInput", + "showStatus": false, + "position": { + "x": 515.1887815471657, + "y": -169.04905809653783 + }, + "inputs": [ + { + "key": "defaultFeedback", + "valueType": "string", + "label": "默认反馈内容", + "type": "textarea", + "required": false, + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true, + "inputType": true + }, + "connected": true + }, + { + "key": "customFeedback", + "valueType": "string", + "label": "自定义反馈内容", + "type": "target", + "required": false, + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true, + "inputType": true + }, + "connected": true + } + ], + "outputs": [ + { + "key": "defaultFeedback", + "valueType": "string", + "label": "默认反馈内容", + "type": "source", + "edit": true, + "targets": [ + { + "moduleId": "49de3g", + "key": "defaultFeedback" + } + ] + }, + { + "key": "customFeedback", + "valueType": "string", + "label": "自定义反馈内容", + "type": "source", + "edit": true, + "targets": [ + { + "moduleId": "49de3g", + "key": "customFeedback" + } + ] + } + ] + }, + { + "moduleId": "49de3g", + "name": "HTTP模块", + "flowType": "httpRequest468", + "showStatus": true, + "position": { + "x": 1086.8929621216014, + "y": -451.7550009773506 + }, + "inputs": [ + { + "key": "switch", + "type": "target", + "label": "core.module.input.label.switch", + "description": "core.module.input.description.Trigger", + "valueType": "any", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "system_httpMethod", + "type": "custom", + "valueType": "string", + "label": "", + "value": "POST", + "list": [ + { + "label": "GET", + "value": "GET" + }, + { + "label": "POST", + "value": "POST" + } + ], + "required": true, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpReqUrl", + "type": "hidden", + "valueType": "string", + "label": "", + "description": "core.module.input.description.Http Request Url", + "placeholder": "https://api.ai.com/getInventory", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "value": "/api/plugins/customFeedback", + "connected": false + }, + { + "key": "system_httpHeader", + "type": "custom", + "valueType": "any", + "value": "", + "label": "", + "description": "core.module.input.description.Http Request Header", + "placeholder": "core.module.input.description.Http Request Header", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpParams", + "type": "hidden", + "valueType": "any", + "value": [], + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpJsonBody", + "type": "hidden", + "valueType": "any", + "value": "{\r\n \"appId\": \"{{appId}}\",\r\n \"chatId\": \"{{chatId}}\",\r\n \"responseChatItemId\": \"{{responseChatItemId}}\",\r\n \"defaultFeedback\": \"{{defaultFeedback}}\",\r\n \"customFeedback\": \"{{customFeedback}}\"\r\n}", + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "DYNAMIC_INPUT_KEY", + "type": "target", + "valueType": "any", + "label": "core.module.inputType.dynamicTargetInput", + "description": "core.module.input.description.dynamic input", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": true, + "hideInApp": true, + "connected": false + }, + { + "valueType": "string", + "label": "defaultFeedback", + "type": "target", + "required": true, + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true + }, + "connected": true, + "key": "defaultFeedback" + }, + { + "key": "customFeedback", + "valueType": "string", + "label": "customFeedback", + "type": "target", + "required": true, + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true + }, + "connected": true + }, + { + "key": "system_addInputParam", + "type": "addInputParam", + "valueType": "any", + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "inputType": "target", + "valueType": "string", + "required": true + }, + "connected": false + } + ], + "outputs": [ + { + "key": "finish", + "label": "core.module.output.label.running done", + "description": "core.module.output.description.running done", + "valueType": "boolean", + "type": "hidden", + "targets": [] + }, + { + "key": "system_addOutputParam", + "type": "addOutputParam", + "valueType": "any", + "label": "", + "targets": [], + "editField": { + "key": true, + "name": true, + "description": true, + "dataType": true + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "outputType": "source", + "valueType": "string" + } + }, + { + "type": "source", + "valueType": "string", + "label": "response", + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "dataType": true + }, + "targets": [ + { + "moduleId": "s15f3v", + "key": "text" + } + ], + "key": "response" + } + ] + }, + { + "moduleId": "s15f3v", + "name": "指定回复", + "flowType": "answerNode", + "position": { + "x": 1705.6337348182756, + "y": -37.53826066726282 + }, + "inputs": [ + { + "key": "switch", + "type": "target", + "label": "core.module.input.label.switch", + "description": "core.module.input.description.Trigger", + "valueType": "any", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "text", + "type": "textarea", + "valueType": "any", + "label": "core.module.input.label.Response content", + "description": "core.module.input.description.Response content", + "placeholder": "core.module.input.description.Response content", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": true + } + ], + "outputs": [ + { + "key": "finish", + "label": "core.module.output.label.running done", + "description": "core.module.output.description.running done", + "valueType": "boolean", + "type": "hidden", + "targets": [] + } + ] + } + ] +} diff --git a/projects/app/data/pluginTemplates/v1/getCurrentTime.json b/projects/app/data/pluginTemplates/v1/getCurrentTime.json new file mode 100644 index 000000000..235b1f9c6 --- /dev/null +++ b/projects/app/data/pluginTemplates/v1/getCurrentTime.json @@ -0,0 +1,195 @@ +{ + "author": "FastGPT Team", + "templateType": "tools", + "name": "获取当前时间", + "avatar": "/imgs/module/getCurrentTime.svg", + "intro": "获取用户当前时区的时间。", + "showStatus": false, + "isTool": true, + "weight": 10, + "modules": [ + { + "moduleId": "m8dupj", + "name": "定义插件输入", + "intro": "自定义配置外部输入,使用插件时,仅暴露自定义配置的输入", + "avatar": "/imgs/module/input.png", + "flowType": "pluginInput", + "showStatus": false, + "position": { + "x": 187.94161749205568, + "y": 179.78772129776746 + }, + "inputs": [ + { + "key": "pluginStart", + "type": "hidden", + "valueType": "boolean", + "label": "插件开始运行", + "description": "插件开始运行时,会输出一个 True 的标识。有时候,插件不会有额外的的输入,为了顺利的进入下一个阶段,你可以将该值连接到下一个节点的触发器中。", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": true + } + ], + "outputs": [ + { + "key": "pluginStart", + "label": "插件开始运行", + "type": "source", + "valueType": "boolean", + "targets": [ + { + "moduleId": "cv13yt", + "key": "switch" + } + ] + } + ] + }, + { + "moduleId": "bjsa7r", + "name": "定义插件输出", + "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", + "avatar": "/imgs/module/output.png", + "flowType": "pluginOutput", + "showStatus": false, + "position": { + "x": 1176.9471084832217, + "y": 138.94098316727695 + }, + "inputs": [ + { + "key": "time", + "valueType": "string", + "label": "time", + "type": "target", + "required": true, + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": false, + "dataType": true, + "inputType": false + }, + "connected": true + } + ], + "outputs": [ + { + "key": "time", + "valueType": "string", + "label": "time", + "type": "source", + "edit": true, + "targets": [] + } + ] + }, + { + "moduleId": "cv13yt", + "name": "文本加工", + "intro": "可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。", + "avatar": "/imgs/module/textEditor.svg", + "flowType": "pluginModule", + "showStatus": false, + "position": { + "x": 600.7190079155914, + "y": 1.4754510232677944 + }, + "inputs": [ + { + "key": "pluginId", + "type": "hidden", + "label": "", + "value": "community-textEditor", + "valueType": "string", + "connected": false, + "showTargetInApp": false, + "showTargetInPlugin": false + }, + { + "key": "switch", + "type": "triggerAndFinish", + "label": "", + "description": "core.module.input.description.Trigger", + "valueType": "any", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": true + }, + { + "key": "textarea", + "valueType": "string", + "label": "文本内容", + "type": "textarea", + "required": true, + "description": "可以通过 {{key}} 的方式引用传入的变量。变量仅支持字符串或数字。", + "edit": false, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true, + "inputType": true + }, + "connected": false, + "placeholder": "可以通过 {{key}} 的方式引用传入的变量。变量仅支持字符串或数字。", + "value": "{{cTime}}" + }, + { + "key": "DYNAMIC_INPUT_KEY", + "valueType": "any", + "label": "需要加工的输入", + "type": "addInputParam", + "required": false, + "description": "可动态的添加字符串类型变量,在文本编辑中通过 {{key}} 使用变量。非字符串类型,会自动转成字符串类型。", + "edit": false, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true, + "inputType": false + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "inputType": "target", + "valueType": "string", + "required": true + }, + "connected": false + } + ], + "outputs": [ + { + "key": "text", + "valueType": "string", + "label": "core.module.output.label.text", + "type": "source", + "edit": false, + "targets": [ + { + "moduleId": "bjsa7r", + "key": "time" + } + ] + }, + { + "key": "finish", + "label": "", + "description": "", + "valueType": "boolean", + "type": "hidden", + "targets": [] + } + ] + } + ] +} diff --git a/projects/app/data/pluginTemplates/v1/textEditor.json b/projects/app/data/pluginTemplates/v1/textEditor.json new file mode 100644 index 000000000..f562f3ec2 --- /dev/null +++ b/projects/app/data/pluginTemplates/v1/textEditor.json @@ -0,0 +1,331 @@ +{ + "author": "FastGPT Team", + "templateType": "tools", + "name": "文本加工", + "avatar": "/imgs/module/textEditor.svg", + "intro": "可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。", + "showStatus": false, + "isTool": false, + "weight": 100, + "modules": [ + { + "moduleId": "w90mfp", + "name": "定义插件输入", + "flowType": "pluginInput", + "showStatus": false, + "position": { + "x": 616.4226348688949, + "y": -165.05298493910115 + }, + "inputs": [ + { + "key": "textarea", + "valueType": "string", + "label": "文本内容", + "type": "textarea", + "required": true, + "description": "可以通过 {{key}} 的方式引用传入的变量。变量仅支持字符串或数字。", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true, + "inputType": true + }, + "connected": true + }, + { + "key": "DYNAMIC_INPUT_KEY", + "valueType": "any", + "label": "需要加工的输入", + "type": "addInputParam", + "required": false, + "description": "可动态的添加字符串类型变量,在文本编辑中通过 {{key}} 使用变量。非字符串类型,会自动转成字符串类型。", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true, + "inputType": false + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "inputType": "target", + "valueType": "string", + "required": true + }, + "connected": true + } + ], + "outputs": [ + { + "key": "textarea", + "valueType": "string", + "label": "文本内容", + "type": "source", + "edit": true, + "targets": [ + { + "moduleId": "49de3g", + "key": "text" + } + ] + }, + { + "key": "DYNAMIC_INPUT_KEY", + "valueType": "any", + "label": "需要加工的输入", + "type": "source", + "edit": true, + "targets": [ + { + "moduleId": "49de3g", + "key": "DYNAMIC_INPUT_KEY" + } + ] + } + ] + }, + { + "moduleId": "tze1ju", + "name": "定义插件输出", + "flowType": "pluginOutput", + "showStatus": false, + "position": { + "x": 1607.7142331269126, + "y": -145.93201540017395 + }, + "inputs": [ + { + "key": "text", + "valueType": "string", + "label": "core.module.output.label.text", + "type": "target", + "required": true, + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": false, + "dataType": true, + "inputType": false + }, + "connected": true + } + ], + "outputs": [ + { + "key": "text", + "valueType": "string", + "label": "core.module.output.label.text", + "type": "source", + "edit": true, + "targets": [] + } + ] + }, + { + "moduleId": "49de3g", + "name": "HTTP模块", + "flowType": "httpRequest468", + "showStatus": true, + "position": { + "x": 1086.8929621216014, + "y": -451.7550009773506 + }, + "inputs": [ + { + "key": "switch", + "type": "target", + "label": "core.module.input.label.switch", + "description": "core.module.input.description.Trigger", + "valueType": "any", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "system_httpMethod", + "type": "custom", + "valueType": "string", + "label": "", + "value": "POST", + "list": [ + { + "label": "GET", + "value": "GET" + }, + { + "label": "POST", + "value": "POST" + } + ], + "required": true, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpReqUrl", + "type": "hidden", + "valueType": "string", + "label": "", + "description": "core.module.input.description.Http Request Url", + "placeholder": "https://api.ai.com/getInventory", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "value": "/api/plugins/textEditor", + "connected": false + }, + { + "key": "system_httpHeader", + "type": "custom", + "valueType": "any", + "value": "", + "label": "", + "description": "core.module.input.description.Http Request Header", + "placeholder": "core.module.input.description.Http Request Header", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpParams", + "type": "hidden", + "valueType": "any", + "value": [], + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpJsonBody", + "type": "hidden", + "valueType": "any", + "value": "{\r\n \"text\": \"{{text}}\"\r\n}", + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "DYNAMIC_INPUT_KEY", + "type": "target", + "valueType": "any", + "label": "core.module.inputType.dynamicTargetInput", + "description": "core.module.input.description.dynamic input", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": true, + "hideInApp": true, + "connected": true + }, + { + "key": "text", + "valueType": "string", + "label": "text", + "type": "target", + "required": true, + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true + }, + "connected": true + }, + { + "key": "system_addInputParam", + "type": "addInputParam", + "valueType": "any", + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "inputType": "target", + "valueType": "string", + "required": true + }, + "connected": false + } + ], + "outputs": [ + { + "key": "finish", + "label": "core.module.output.label.running done", + "description": "core.module.output.description.running done", + "valueType": "boolean", + "type": "hidden", + "targets": [] + }, + { + "key": "system_addOutputParam", + "type": "addOutputParam", + "valueType": "any", + "label": "", + "targets": [], + "editField": { + "key": true, + "name": true, + "description": true, + "dataType": true + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "outputType": "source", + "valueType": "string" + } + }, + { + "type": "source", + "valueType": "string", + "key": "text", + "label": "core.module.output.label.text", + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "dataType": true + }, + "targets": [ + { + "moduleId": "tze1ju", + "key": "text" + } + ] + } + ] + } + ] +} diff --git a/projects/app/data/pluginTemplates/v1/tfSwitch.json b/projects/app/data/pluginTemplates/v1/tfSwitch.json new file mode 100644 index 000000000..fe06dc07f --- /dev/null +++ b/projects/app/data/pluginTemplates/v1/tfSwitch.json @@ -0,0 +1,369 @@ +{ + "abandon": true, + "author": "FastGPT Team", + "templateType": "tools", + "name": "判断器", + "avatar": "/imgs/module/tfSwitch.svg", + "intro": "根据传入的内容进行 True False 输出。默认情况下,当传入的内容为 false, undefined, null, 0, none 时,会输出 false。你也可以增加一些自定义的字符串来补充输出 false 的内容。非字符、非数字、非布尔类型,直接输出 True。", + "showStatus": false, + "isTool": false, + "weight": 10, + "modules": [ + { + "moduleId": "w90mfp", + "name": "定义插件输入", + "flowType": "pluginInput", + "showStatus": false, + "position": { + "x": 616.4226348688949, + "y": -165.05298493910115 + }, + "inputs": [ + { + "key": "input", + "valueType": "any", + "type": "target", + "label": "core.module.input.label.TFSwitch input tip", + "required": true, + "edit": true, + "connected": true + }, + { + "key": "rule", + "valueType": "string", + "label": "core.module.input.label.TFSwitch textarea", + "type": "textarea", + "required": false, + "description": "core.module.input.description.TFSwitch textarea", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true, + "inputType": true + }, + "connected": true + } + ], + "outputs": [ + { + "key": "input", + "valueType": "any", + "label": "core.module.input.label.TFSwitch input tip", + "type": "source", + "edit": true, + "targets": [ + { + "moduleId": "8kld99", + "key": "input" + } + ] + }, + { + "key": "rule", + "valueType": "string", + "label": "core.module.input.label.TFSwitch textarea", + "type": "source", + "edit": true, + "targets": [ + { + "moduleId": "8kld99", + "key": "rule" + } + ] + } + ] + }, + { + "moduleId": "tze1ju", + "name": "定义插件输出", + "flowType": "pluginOutput", + "showStatus": false, + "position": { + "x": 1985.3791673445353, + "y": -144.90535546692078 + }, + "inputs": [ + { + "key": "true", + "type": "target", + "valueType": "boolean", + "label": "True", + "required": true, + "edit": true, + "connected": true, + "description": "" + }, + { + "key": "false", + "valueType": "boolean", + "label": "False", + "type": "target", + "required": true, + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": false, + "dataType": true, + "inputType": false + }, + "connected": true + } + ], + "outputs": [ + { + "key": "true", + "valueType": "boolean", + "label": "True", + "type": "source", + "edit": true, + "targets": [] + }, + { + "key": "false", + "valueType": "boolean", + "label": "False", + "type": "source", + "edit": true, + "targets": [] + } + ] + }, + { + "moduleId": "8kld99", + "name": "HTTP模块", + "flowType": "httpRequest468", + "showStatus": true, + "position": { + "x": 1210.560012858087, + "y": -387.62433050951756 + }, + "inputs": [ + { + "key": "switch", + "type": "target", + "label": "core.module.input.label.switch", + "description": "core.module.input.description.Trigger", + "valueType": "any", + "showTargetInApp": true, + "showTargetInPlugin": true, + "connected": false + }, + { + "key": "system_httpMethod", + "type": "custom", + "valueType": "string", + "label": "", + "value": "POST", + "list": [ + { + "label": "GET", + "value": "GET" + }, + { + "label": "POST", + "value": "POST" + } + ], + "required": true, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpReqUrl", + "type": "hidden", + "valueType": "string", + "label": "", + "description": "core.module.input.description.Http Request Url", + "placeholder": "https://api.ai.com/getInventory", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "value": "/api/plugins/TFSwitch", + "connected": false + }, + { + "key": "system_httpHeader", + "type": "custom", + "valueType": "any", + "label": "", + "description": "core.module.input.description.Http Request Header", + "placeholder": "core.module.input.description.Http Request Header", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpParams", + "type": "hidden", + "valueType": "any", + "value": [], + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "system_httpJsonBody", + "type": "hidden", + "valueType": "any", + "value": "{\r\n \"input\": \"{{input}}\",\r\n \"rule\": \"{{rule}}\"\r\n}", + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "connected": false + }, + { + "key": "DYNAMIC_INPUT_KEY", + "type": "target", + "valueType": "any", + "label": "core.module.inputType.dynamicTargetInput", + "description": "core.module.input.description.dynamic input", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": true, + "hideInApp": true, + "connected": false + }, + { + "key": "input", + "valueType": "any", + "label": "input", + "type": "target", + "required": true, + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true + }, + "connected": true + }, + { + "key": "rule", + "valueType": "string", + "label": "rule", + "type": "target", + "required": false, + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true + }, + "connected": true + }, + { + "key": "system_addInputParam", + "type": "addInputParam", + "valueType": "any", + "label": "", + "required": false, + "showTargetInApp": false, + "showTargetInPlugin": false, + "editField": { + "key": true, + "name": true, + "description": true, + "required": true, + "dataType": true + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "inputType": "target", + "valueType": "string", + "required": true + }, + "connected": false + } + ], + "outputs": [ + { + "key": "finish", + "label": "core.module.output.label.running done", + "description": "core.module.output.description.running done", + "valueType": "boolean", + "type": "hidden", + "targets": [] + }, + { + "key": "system_addOutputParam", + "type": "addOutputParam", + "valueType": "any", + "label": "", + "targets": [], + "editField": { + "key": true, + "name": true, + "description": true, + "dataType": true + }, + "defaultEditField": { + "label": "", + "key": "", + "description": "", + "outputType": "source", + "valueType": "string" + } + }, + { + "type": "source", + "valueType": "boolean", + "key": "true", + "label": "true", + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "dataType": true + }, + "targets": [ + { + "moduleId": "tze1ju", + "key": "true" + } + ] + }, + { + "type": "source", + "valueType": "boolean", + "key": "false", + "label": "false", + "description": "", + "edit": true, + "editField": { + "key": true, + "name": true, + "description": true, + "dataType": true + }, + "targets": [ + { + "moduleId": "tze1ju", + "key": "false" + } + ] + } + ] + } + ] +} diff --git a/projects/app/src/pages/api/common/system/getInitData.ts b/projects/app/src/pages/api/common/system/getInitData.ts index 0c11a8abe..62c783535 100644 --- a/projects/app/src/pages/api/common/system/getInitData.ts +++ b/projects/app/src/pages/api/common/system/getInitData.ts @@ -63,7 +63,10 @@ export async function getInitConfig() { initSystemConfig(), // getSimpleModeTemplates(), getSystemVersion(), - getSystemPlugin() + getSystemPlugin(), + + // abandon + getSystemPluginV1() ]); console.log({ @@ -164,3 +167,29 @@ function getSystemPlugin() { global.communityPlugins = fileTemplates; } +function getSystemPluginV1() { + if (global.communityPluginsV1 && global.communityPluginsV1.length > 0) return; + + const basePath = + process.env.NODE_ENV === 'development' + ? 'data/pluginTemplates/v1' + : '/app/data/pluginTemplates/v1'; + // read data/pluginTemplates directory, get all json file + const files = readdirSync(basePath); + // filter json file + const filterFiles = files.filter((item) => item.endsWith('.json')); + + // read json file + const fileTemplates: (PluginTemplateType & { weight: number })[] = filterFiles.map((filename) => { + const content = readFileSync(`${basePath}/${filename}`, 'utf-8'); + return { + ...JSON.parse(content), + id: `${PluginSourceEnum.community}-${filename.replace('.json', '')}`, + source: PluginSourceEnum.community + }; + }); + + fileTemplates.sort((a, b) => b.weight - a.weight); + + global.communityPluginsV1 = fileTemplates; +} diff --git a/projects/app/src/pages/api/plugins/TFSwitch/index.ts b/projects/app/src/pages/api/plugins/TFSwitch/index.ts new file mode 100644 index 000000000..e77be0ec0 --- /dev/null +++ b/projects/app/src/pages/api/plugins/TFSwitch/index.ts @@ -0,0 +1,72 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; +// @ts-ignore +import type { HttpBodyType } from '@fastgpt/global/core/module/api.d'; +import { getErrText } from '@fastgpt/global/common/error/utils'; +import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common'; + +type Props = HttpBodyType<{ + input: string; + rule?: string; +}>; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + try { + const { input, rule = '' } = req.body as Props; + + await authRequestFromLocal({ req }); + + const result = (() => { + if (typeof input === 'string') { + const defaultReg: any[] = [ + '', + undefined, + 'undefined', + null, + 'null', + false, + 'false', + 0, + '0', + 'none' + ]; + const customReg = rule.split('\n'); + defaultReg.push(...customReg); + + return !defaultReg.find((item) => { + const reg = typeof item === 'string' ? stringToRegex(item) : null; + if (reg) { + return reg.test(input); + } + return input === item; + }); + } + + return !!input; + })(); + + res.json({ + ...(result + ? { + true: true + } + : { + false: false + }) + }); + } catch (err) { + console.log(err); + res.status(500).send(getErrText(err)); + } +} + +function stringToRegex(str: string) { + const regexFormat = /^\/(.+)\/([gimuy]*)$/; + const match = str.match(regexFormat); + + if (match) { + const [, pattern, flags] = match; + return new RegExp(pattern, flags); + } else { + return null; + } +} diff --git a/projects/app/src/pages/api/plugins/customFeedback/index.ts b/projects/app/src/pages/api/plugins/customFeedback/index.ts index 2e1555c6c..7f67bff1b 100644 --- a/projects/app/src/pages/api/plugins/customFeedback/index.ts +++ b/projects/app/src/pages/api/plugins/customFeedback/index.ts @@ -1,25 +1,36 @@ import type { NextApiRequest, NextApiResponse } from 'next'; -import type { HttpBodyType } from '@fastgpt/global/core/workflow/api.d'; +//@ts-ignore +import type { HttpBodyType } from '@fastgpt/global/core/module/api.d'; import { getErrText } from '@fastgpt/global/common/error/utils'; import { addCustomFeedbacks } from '@fastgpt/service/core/chat/controller'; import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common'; -import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; type Props = HttpBodyType<{ + appId: string; + chatId?: string; + responseChatItemId?: string; + defaultFeedback: string; customFeedback: string; }>; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { const { - customFeedback, - system_addInputParam: { appId, chatId, responseChatItemId: chatItemId } + appId, + chatId, + responseChatItemId: chatItemId, + defaultFeedback, + customFeedback } = req.body as Props; await authRequestFromLocal({ req }); - if (!customFeedback) { - return res.json({}); + const feedback = customFeedback || defaultFeedback; + + if (!feedback) { + return res.json({ + response: '' + }); } // wait the chat finish @@ -28,17 +39,19 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< appId, chatId, chatItemId, - feedbacks: [customFeedback] + feedbacks: [feedback] }); }, 60000); if (!chatId || !chatItemId) { return res.json({ - [NodeOutputKeyEnum.answerText]: `\\n\\n**自动反馈调试**: "${customFeedback}"\\n\\n` + response: `\\n\\n**自动反馈调试**: ${feedback}\\n\\n` }); } - return res.json({}); + return res.json({ + response: '' + }); } catch (err) { console.log(err); res.status(500).send(getErrText(err)); diff --git a/projects/app/src/pages/api/plugins/customFeedback/v2/index.ts b/projects/app/src/pages/api/plugins/customFeedback/v2/index.ts new file mode 100644 index 000000000..c04c73b86 --- /dev/null +++ b/projects/app/src/pages/api/plugins/customFeedback/v2/index.ts @@ -0,0 +1,46 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; +import type { HttpBodyType } from '@fastgpt/global/core/workflow/api.d'; +import { getErrText } from '@fastgpt/global/common/error/utils'; +import { addCustomFeedbacks } from '@fastgpt/service/core/chat/controller'; +import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common'; +import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; + +type Props = HttpBodyType<{ + customFeedback: string; +}>; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + try { + const { + customFeedback, + [NodeInputKeyEnum.addInputParam]: { appId, chatId, responseChatItemId: chatItemId } + } = req.body as Props; + + await authRequestFromLocal({ req }); + + if (!customFeedback) { + return res.json({}); + } + + // wait the chat finish + setTimeout(() => { + addCustomFeedbacks({ + appId, + chatId, + chatItemId, + feedbacks: [customFeedback] + }); + }, 60000); + + if (!chatId || !chatItemId) { + return res.json({ + [NodeOutputKeyEnum.answerText]: `\\n\\n**自动反馈调试**: "${customFeedback}"\\n\\n` + }); + } + + return res.json({}); + } catch (err) { + console.log(err); + res.status(500).send(getErrText(err)); + } +} diff --git a/projects/app/src/pages/api/plugins/textEditor/index.ts b/projects/app/src/pages/api/plugins/textEditor/index.ts index 57af18e60..07d564110 100644 --- a/projects/app/src/pages/api/plugins/textEditor/index.ts +++ b/projects/app/src/pages/api/plugins/textEditor/index.ts @@ -1,9 +1,9 @@ import type { NextApiRequest, NextApiResponse } from 'next'; -import type { HttpBodyType } from '@fastgpt/global/core/workflow/api.d'; +//@ts-ignore +import type { HttpBodyType } from '@fastgpt/global/core/module/api.d'; import { getErrText } from '@fastgpt/global/common/error/utils'; import { replaceVariable } from '@fastgpt/global/common/string/tools'; import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common'; -import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; type Props = HttpBodyType<{ text: string; @@ -12,7 +12,10 @@ type Props = HttpBodyType<{ export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { - const { text, [NodeInputKeyEnum.addInputParam]: obj } = req.body as Props; + const { + text, + DYNAMIC_INPUT_KEY: { ...obj } + } = req.body as Props; await authRequestFromLocal({ req }); diff --git a/projects/app/src/pages/api/plugins/textEditor/v2/index.ts b/projects/app/src/pages/api/plugins/textEditor/v2/index.ts new file mode 100644 index 000000000..57af18e60 --- /dev/null +++ b/projects/app/src/pages/api/plugins/textEditor/v2/index.ts @@ -0,0 +1,42 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; +import type { HttpBodyType } from '@fastgpt/global/core/workflow/api.d'; +import { getErrText } from '@fastgpt/global/common/error/utils'; +import { replaceVariable } from '@fastgpt/global/common/string/tools'; +import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common'; +import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; + +type Props = HttpBodyType<{ + text: string; + [key: string]: any; +}>; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + try { + const { text, [NodeInputKeyEnum.addInputParam]: obj } = req.body as Props; + + await authRequestFromLocal({ req }); + + // string all value + Object.keys(obj).forEach((key) => { + let val = obj[key]; + + if (typeof val === 'object') { + val = JSON.stringify(val); + } else if (typeof val === 'number') { + val = String(val); + } else if (typeof val === 'boolean') { + val = val ? 'true' : 'false'; + } + + obj[key] = val; + }); + + const textResult = replaceVariable(text, obj); + res.json({ + text: textResult + }); + } catch (err) { + console.log(err); + res.status(500).send(getErrText(err)); + } +}