From 33d40fd07732f31f97b9da8de6d97cc366898b25 Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Wed, 2 Jul 2025 18:15:00 +0800 Subject: [PATCH] feature: System plugin (#5131) * feat: system Tool (#4959) * feat: independent system tool * chore: use ToolNode instead of PluginModule * chore: tools * chore: tools templateDir * refactor: templates * feat: flush code * chore: update template * refactor: migrate delay * feat: worker pool * chore: Dockerfile * docs: add tools.template.json * feat: auto flush system tools * fix: ts error * chore: create new pool temporarily * chore: system tool migration * chore: migration * fix: fix pnpm-workspace.yaml * chore: update pnpm-lock.yaml to integrate tool * chore(systemTool): chore * chore: add system plugin * chore(deps): update @fastgpt-sdk/plugin * fix: type error * chore: remove plugin package * chore: move pro plugins code to open source * feat: support system tool config input * fix: type error * perf: i18n * fix: cr * chore: update sdk * feat: system plugin cache * update mcp server (#5076) * update mcp server * fix: action * fix: dockerfile * fix: dockerfile * fix: dockerfile * fix: dockerfile * fix: dockerfile * fix: dockerfile * feat: system Tool (#4959) * feat: independent system tool * chore: use ToolNode instead of PluginModule * chore: tools * chore: tools templateDir * refactor: templates * feat: flush code * chore: update template * refactor: migrate delay * feat: worker pool * chore: Dockerfile * docs: add tools.template.json * feat: auto flush system tools * fix: ts error * chore: create new pool temporarily * chore: system tool migration * chore: migration * fix: fix pnpm-workspace.yaml * chore: update pnpm-lock.yaml to integrate tool * chore(systemTool): chore * chore: add system plugin * chore(deps): update @fastgpt-sdk/plugin * fix: type error * chore: remove plugin package * chore: move pro plugins code to open source * feat: support system tool config input * fix: type error * perf: i18n * fix: cr * chore: update sdk * feat: system plugin cache * perf: run tool * update package * perf: config key * fix: tool ini * tool config params * perf: workflow type * rename tools to agent * version list * perf: tool error * config secret ux * perf: config secret ux * fix: tool config field * add course to secret input * feat: support inputConfig switch (#5099) * feat: support inputConfig switch * deps: update @fastgpt-sdk/plugin * chore: update workflows * fix: inputType * fix: secret * add default value to node * update i18n * eslint * add precision to number input * feat: add number input and select * perf: number ux * fix: code * Proxies image requests to plugin service (#5111) * Proxies image requests to plugin service Adds a rewrite rule and API endpoint to proxy image requests to the plugin service. This allows the app to fetch images from the plugin's tools directory. It also adds the plugin base URL to the service's constants, so that it can use the plugin URL when proxying requests. * fix: update FastGPTPluginUrl to remove unnecessary API path * feat: update image proxy destination and add plugin image handler * Adapt plugin id * replace avatar * remove rewrite * fix: plugin avatar * update system tool doc * feat: system tool type * yml sh * yml sh * update doc * fix: simple app tool select * fix: switch ui * update pacakge * Yamljs (#5129) * update docker-compose configuration: bump fastgpt and fastgpt-plugin images, change minio host to service name, and adjust service dependencies * refactor: comment out port exposure in docker-compose configuration * update: uncomment port exposure in docker-compose configuration * update: change MINIO_HOST to use specific IP address in docker configuration * update: modify fastgpt-plugin image version in docker configuration * update readme * doc * remove --------- Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com> Co-authored-by: Theresa <63280168+sd0ric4@users.noreply.github.com> --- .eslintignore | 1 + .github/workflows/docs-preview.yml | 31 +- .github/workflows/fastgpt-preview-image.yml | 20 +- README.md | 1 + docSite/assets/imgs/plugin-openapi.png | Bin 0 -> 77477 bytes docSite/assets/imgs/plugin-openapi2.png | Bin 0 -> 230965 bytes docSite/assets/imgs/sealos-s3.png | Bin 0 -> 445315 bytes .../content/zh-cn/docs/development/docker.md | 47 +- .../zh-cn/docs/development/upgrading/4100.md | 64 ++ .../zh-cn/docs/development/upgrading/4914.md | 1 + .../zh-cn/docs/guide/plugins/design_plugin.md | 23 + .../docs/guide/plugins/dev_system_tool.md | 200 +++++ .../plugins/how_to_submit_system_plugin.md | 118 --- package.json | 5 +- packages/global/common/error/utils.ts | 1 + .../global/common/i18n/type.ts | 11 +- packages/global/common/i18n/utils.ts | 6 + packages/global/core/app/httpPlugin/utils.ts | 2 +- packages/global/core/app/mcpTools/utils.ts | 2 +- packages/global/core/app/plugin/constants.ts | 7 + packages/global/core/app/plugin/type.d.ts | 63 ++ .../global/core/app/systemTool/constants.ts | 18 + packages/global/core/app/type.d.ts | 2 +- packages/global/core/app/utils.ts | 2 +- packages/global/core/chat/utils.ts | 2 +- packages/global/core/plugin/constants.ts | 25 - packages/global/core/plugin/controller.d.ts | 42 -- packages/global/core/plugin/type.d.ts | 54 -- packages/global/core/workflow/api.d.ts | 27 - packages/global/core/workflow/constants.ts | 15 +- .../global/core/workflow/node/constant.ts | 4 +- .../global/core/workflow/node/io/utils.ts | 17 - .../global/core/workflow/runtime/type.d.ts | 7 +- .../global/core/workflow/runtime/utils.ts | 39 +- .../core/workflow/template/constants.ts | 42 +- .../template/system/abandoned/runApp/index.ts | 5 +- .../template/system/{tools.ts => agent.ts} | 17 +- .../workflow/template/system/aiChat/index.ts | 5 +- .../template/system/assignedAnswer.ts | 5 +- .../template/system/classifyQuestion/index.ts | 5 +- .../core/workflow/template/system/comment.ts | 5 +- .../template/system/contextExtract/index.ts | 5 +- .../template/system/customFeedback.ts | 5 +- .../workflow/template/system/datasetConcat.ts | 5 +- .../workflow/template/system/datasetSearch.ts | 5 +- .../workflow/template/system/emptyNode.ts | 5 +- .../core/workflow/template/system/http468.ts | 5 +- .../workflow/template/system/ifElse/index.ts | 5 +- .../template/system/interactive/formInput.ts | 5 +- .../template/system/interactive/userSelect.ts | 5 +- .../core/workflow/template/system/laf.ts | 5 +- .../workflow/template/system/loop/loop.ts | 5 +- .../workflow/template/system/loop/loopEnd.ts | 5 +- .../template/system/loop/loopStart.ts | 5 +- .../workflow/template/system/pluginConfig.ts | 5 +- .../workflow/template/system/pluginInput.ts | 5 +- .../workflow/template/system/pluginOutput.ts | 5 +- .../template/system/queryExtension.ts | 6 +- .../template/system/readFiles/index.tsx | 5 +- .../core/workflow/template/system/runApp.ts | 5 +- .../workflow/template/system/runPlugin.ts | 5 +- .../core/workflow/template/system/runTool.ts | 5 +- .../workflow/template/system/runToolSet.ts | 7 +- .../workflow/template/system/sandbox/index.ts | 5 +- .../core/workflow/template/system/stopTool.ts | 5 +- .../workflow/template/system/systemConfig.ts | 5 +- .../workflow/template/system/textEditor.ts | 6 +- .../workflow/template/system/toolParams.ts | 5 +- .../template/system/variableUpdate/index.tsx | 5 +- .../workflow/template/system/workflowStart.ts | 5 +- packages/global/core/workflow/template/tip.ts | 6 +- .../global/core/workflow/template/utils.ts | 6 - packages/global/core/workflow/type/fe.d.ts | 47 -- packages/global/core/workflow/type/index.d.ts | 58 +- packages/global/core/workflow/type/io.d.ts | 37 +- packages/global/core/workflow/type/node.d.ts | 21 +- packages/global/core/workflow/utils.ts | 7 +- packages/plugins/README.md | 3 - packages/plugins/package.json | 27 - packages/plugins/register.ts | 106 --- packages/plugins/runtime/worker.ts | 24 - .../plugins/src/DingTalkWebhook/template.json | 535 -------------- packages/plugins/src/Doc2X/PDF2text/index.ts | 256 ------- .../plugins/src/Doc2X/PDF2text/template.json | 462 ------------ packages/plugins/src/Doc2X/template.json | 16 - .../plugins/src/WeWorkWebhook/template.json | 385 ---------- packages/plugins/src/bing/template.json | 511 ------------- packages/plugins/src/bocha/template.json | 489 ------------- .../plugins/src/databaseConnection/index.ts | 87 --- .../src/databaseConnection/template.json | 692 ------------------ packages/plugins/src/delay/index.ts | 18 - packages/plugins/src/delay/template.json | 317 -------- .../plugins/src/drawing/baseChart/index.ts | 99 --- .../src/drawing/baseChart/template.json | 406 ---------- packages/plugins/src/drawing/template.json | 16 - .../plugins/src/duckduckgo/search/index.ts | 48 -- .../src/duckduckgo/search/template.json | 319 -------- .../plugins/src/duckduckgo/searchImg/index.ts | 46 -- .../src/duckduckgo/searchImg/template.json | 319 -------- .../src/duckduckgo/searchNews/index.ts | 47 -- .../src/duckduckgo/searchNews/template.json | 319 -------- .../src/duckduckgo/searchVideo/index.ts | 47 -- .../src/duckduckgo/searchVideo/template.json | 319 -------- packages/plugins/src/duckduckgo/template.json | 16 - packages/plugins/src/feishu/template.json | 539 -------------- packages/plugins/src/fetchUrl/index.ts | 30 - packages/plugins/src/fetchUrl/template.json | 340 --------- packages/plugins/src/getTime/index.ts | 14 - packages/plugins/src/getTime/template.json | 214 ------ packages/plugins/src/google/template.json | 560 -------------- packages/plugins/src/mathExprVal/index.ts | 39 - .../plugins/src/mathExprVal/template.json | 252 ------- packages/plugins/src/searchXNG/index.ts | 76 -- packages/plugins/src/searchXNG/template.json | 412 ----------- packages/plugins/src/smtpEmail/index.ts | 122 --- packages/plugins/src/smtpEmail/template.json | 650 ---------------- packages/plugins/src/template/index.ts | 21 - packages/plugins/src/template/template.json | 16 - packages/plugins/src/wiki/index.ts | 43 -- packages/plugins/src/wiki/template.json | 342 --------- packages/plugins/tsconfig.json | 21 - packages/plugins/type.d.ts | 17 - packages/service/common/middle/i18n.ts | 15 + packages/service/common/secret/utils.ts | 57 +- packages/service/common/system/constants.ts | 1 + .../core/ai/config/provider/Doubao.json | 12 +- packages/service/core/app/controller.ts | 14 +- .../service/core/app/plugin/controller.ts | 419 ++++++++--- .../core/app/plugin/systemPluginSchema.ts | 10 +- packages/service/core/app/plugin/type.d.ts | 17 +- packages/service/core/app/plugin/utils.ts | 8 +- packages/service/core/app/tool/api.ts | 51 ++ packages/service/core/app/utils.ts | 14 +- packages/service/core/plugin/schema.ts | 86 --- packages/service/core/plugin/type.d.ts | 6 - .../{agent/runTool => ai/agent}/constants.ts | 0 .../runTool => ai/agent}/functionCall.ts | 6 +- .../{agent/runTool => ai/agent}/index.ts | 2 +- .../{agent/runTool => ai/agent}/promptCall.ts | 6 +- .../{agent/runTool => ai/agent}/stopTool.ts | 0 .../{agent/runTool => ai/agent}/toolChoice.ts | 6 +- .../{agent/runTool => ai/agent}/toolParams.ts | 0 .../{agent/runTool => ai/agent}/type.d.ts | 2 +- .../{agent/runTool => ai/agent}/utils.ts | 0 .../dispatch/{chat/oneapi.ts => ai/chat.ts} | 0 .../{agent => ai}/classifyQuestion.ts | 0 .../dispatch/{agent => ai}/extract.ts | 0 .../core/workflow/dispatch/dataset/search.ts | 2 +- .../service/core/workflow/dispatch/index.ts | 120 +-- .../core/workflow/dispatch/plugin/run.ts | 32 +- .../core/workflow/dispatch/plugin/runTool.ts | 157 +++- .../core/workflow/dispatch/tools/http468.ts | 72 +- packages/service/package.json | 2 + .../service/support/permission/app/auth.ts | 8 +- packages/service/worker/utils.ts | 6 +- packages/templates/register.ts | 2 +- .../common/Input/NumberInput/index.tsx | 11 +- .../web/components/common/Radio/LeftRadio.tsx | 110 +-- packages/web/core/workflow/constants.ts | 119 +-- packages/web/hooks/useI18n.ts | 2 +- packages/web/i18n/en/account.json | 1 + packages/web/i18n/en/account_team.json | 2 + packages/web/i18n/en/app.json | 27 +- packages/web/i18n/en/common.json | 6 +- packages/web/i18n/en/dataset.json | 6 +- packages/web/i18n/en/file.json | 3 +- packages/web/i18n/en/user.json | 1 - packages/web/i18n/en/workflow.json | 6 +- packages/web/i18n/zh-CN/app.json | 21 +- packages/web/i18n/zh-CN/common.json | 6 +- packages/web/i18n/zh-CN/user.json | 1 - packages/web/i18n/zh-CN/workflow.json | 6 +- packages/web/i18n/zh-Hant/account.json | 1 + packages/web/i18n/zh-Hant/account_team.json | 3 + packages/web/i18n/zh-Hant/app.json | 25 +- packages/web/i18n/zh-Hant/common.json | 6 +- packages/web/i18n/zh-Hant/dataset.json | 2 + packages/web/i18n/zh-Hant/file.json | 8 +- packages/web/i18n/zh-Hant/user.json | 1 - packages/web/i18n/zh-Hant/workflow.json | 6 +- pnpm-lock.yaml | 597 ++------------- projects/app/.env.template | 26 +- projects/app/next.config.js | 9 +- projects/app/package.json | 1 - projects/app/src/components/Markdown/utils.ts | 9 +- .../src/components/Select/I18nLngSelector.tsx | 2 +- .../common/secret/HeaderAuthConfig.tsx | 1 - .../core/app/DatasetSelectModal.tsx | 2 +- .../ChatBox/components/ContextModal.tsx | 2 +- .../components/renderPluginInput.tsx | 66 +- projects/app/src/global/core/chat/utils.ts | 2 +- projects/app/src/instrumentation.ts | 4 +- .../SimpleApp/components/ConfigToolModal.tsx | 7 +- .../SimpleApp/components/ToolSelectModal.tsx | 62 +- .../Flow/NodeTemplatesModal.tsx | 13 +- .../Flow/components/HelperLines.tsx | 2 +- .../Flow/components/IOTitle.tsx | 15 +- .../Flow/components/NodeTemplates/list.tsx | 24 +- .../NodeTemplates/useNodeTemplates.tsx | 2 +- .../Flow/components/ToolParamConfig.tsx | 76 ++ .../Flow/hooks/useWorkflow.tsx | 4 +- .../detail/WorkflowComponents/Flow/index.tsx | 27 +- .../Flow/nodes/NodeDatasetConcat.tsx | 2 +- .../Flow/nodes/NodeSimple.tsx | 5 +- .../Flow/nodes/NodeToolSet.tsx | 1 - .../Flow/nodes/NodeTools.tsx | 2 +- .../nodes/render/Handle/ConnectionHandle.tsx | 4 +- .../Flow/nodes/render/NodeCard.tsx | 80 +- .../templates/DynamicInputs/index.tsx | 2 +- .../RenderInput/templates/NumberInput.tsx | 1 + .../RenderInput/templates/SelectDataset.tsx | 2 +- .../templates/SelectDatasetParams.tsx | 2 +- .../WorkflowComponents/context/index.tsx | 53 +- .../app/detail/WorkflowComponents/utils.tsx | 5 +- .../app/plugin/SecretInputModal.tsx | 247 +++++++ projects/app/src/pages/api/admin/initv47.ts | 40 - projects/app/src/pages/api/admin/initv485.ts | 197 ----- projects/app/src/pages/api/core/app/detail.ts | 1 + .../pages/api/core/app/httpPlugin/create.ts | 1 - .../api/core/app/plugin/getPreviewNode.ts | 19 +- .../app/plugin/getSystemPluginTemplates.ts | 66 +- .../api/core/app/plugin/getVersionList.ts | 36 +- .../app/src/pages/api/core/app/plugin/path.ts | 7 +- .../src/pages/api/plugins/TFSwitch/index.ts | 72 -- .../pages/api/plugins/customFeedback/index.ts | 59 -- .../api/plugins/customFeedback/v2/index.ts | 59 -- .../src/pages/api/plugins/textEditor/index.ts | 45 -- .../pages/api/plugins/textEditor/v2/index.ts | 51 -- .../pages/api/system/pluginImgs/[...path].ts | 56 ++ .../app/src/service/common/system/cronTask.ts | 6 +- .../app/src/service/common/system/index.ts | 1 - .../service/common/system/volumnMongoWatch.ts | 20 +- projects/app/src/service/core/app/plugin.ts | 80 -- projects/app/src/service/core/app/utils.ts | 9 - projects/app/src/web/core/app/utils.ts | 18 +- projects/app/src/web/core/chat/utils.ts | 2 +- projects/app/src/web/core/workflow/adapt.ts | 10 +- projects/app/src/web/core/workflow/type.d.ts | 13 + projects/app/src/web/core/workflow/utils.ts | 195 +++-- .../app/test/cases/web/workflow/utils.test.ts | 102 +-- test/cases/global/core/chat/utils.test.ts | 4 +- 241 files changed, 2507 insertions(+), 12443 deletions(-) create mode 100644 docSite/assets/imgs/plugin-openapi.png create mode 100644 docSite/assets/imgs/plugin-openapi2.png create mode 100644 docSite/assets/imgs/sealos-s3.png create mode 100644 docSite/content/zh-cn/docs/development/upgrading/4100.md create mode 100644 docSite/content/zh-cn/docs/guide/plugins/design_plugin.md create mode 100644 docSite/content/zh-cn/docs/guide/plugins/dev_system_tool.md delete mode 100644 docSite/content/zh-cn/docs/guide/plugins/how_to_submit_system_plugin.md rename projects/app/src/web/common/utils/i18n.ts => packages/global/common/i18n/type.ts (66%) create mode 100644 packages/global/common/i18n/utils.ts create mode 100644 packages/global/core/app/plugin/constants.ts create mode 100644 packages/global/core/app/plugin/type.d.ts create mode 100644 packages/global/core/app/systemTool/constants.ts delete mode 100644 packages/global/core/plugin/constants.ts delete mode 100644 packages/global/core/plugin/controller.d.ts delete mode 100644 packages/global/core/plugin/type.d.ts delete mode 100644 packages/global/core/workflow/api.d.ts delete mode 100644 packages/global/core/workflow/node/io/utils.ts rename packages/global/core/workflow/template/system/{tools.ts => agent.ts} (87%) delete mode 100644 packages/global/core/workflow/template/utils.ts delete mode 100644 packages/global/core/workflow/type/fe.d.ts delete mode 100644 packages/plugins/README.md delete mode 100644 packages/plugins/package.json delete mode 100644 packages/plugins/register.ts delete mode 100644 packages/plugins/runtime/worker.ts delete mode 100644 packages/plugins/src/DingTalkWebhook/template.json delete mode 100644 packages/plugins/src/Doc2X/PDF2text/index.ts delete mode 100644 packages/plugins/src/Doc2X/PDF2text/template.json delete mode 100644 packages/plugins/src/Doc2X/template.json delete mode 100644 packages/plugins/src/WeWorkWebhook/template.json delete mode 100644 packages/plugins/src/bing/template.json delete mode 100644 packages/plugins/src/bocha/template.json delete mode 100644 packages/plugins/src/databaseConnection/index.ts delete mode 100644 packages/plugins/src/databaseConnection/template.json delete mode 100644 packages/plugins/src/delay/index.ts delete mode 100644 packages/plugins/src/delay/template.json delete mode 100644 packages/plugins/src/drawing/baseChart/index.ts delete mode 100644 packages/plugins/src/drawing/baseChart/template.json delete mode 100644 packages/plugins/src/drawing/template.json delete mode 100644 packages/plugins/src/duckduckgo/search/index.ts delete mode 100644 packages/plugins/src/duckduckgo/search/template.json delete mode 100644 packages/plugins/src/duckduckgo/searchImg/index.ts delete mode 100644 packages/plugins/src/duckduckgo/searchImg/template.json delete mode 100644 packages/plugins/src/duckduckgo/searchNews/index.ts delete mode 100644 packages/plugins/src/duckduckgo/searchNews/template.json delete mode 100644 packages/plugins/src/duckduckgo/searchVideo/index.ts delete mode 100644 packages/plugins/src/duckduckgo/searchVideo/template.json delete mode 100644 packages/plugins/src/duckduckgo/template.json delete mode 100644 packages/plugins/src/feishu/template.json delete mode 100644 packages/plugins/src/fetchUrl/index.ts delete mode 100644 packages/plugins/src/fetchUrl/template.json delete mode 100644 packages/plugins/src/getTime/index.ts delete mode 100644 packages/plugins/src/getTime/template.json delete mode 100644 packages/plugins/src/google/template.json delete mode 100644 packages/plugins/src/mathExprVal/index.ts delete mode 100644 packages/plugins/src/mathExprVal/template.json delete mode 100644 packages/plugins/src/searchXNG/index.ts delete mode 100644 packages/plugins/src/searchXNG/template.json delete mode 100644 packages/plugins/src/smtpEmail/index.ts delete mode 100644 packages/plugins/src/smtpEmail/template.json delete mode 100644 packages/plugins/src/template/index.ts delete mode 100644 packages/plugins/src/template/template.json delete mode 100644 packages/plugins/src/wiki/index.ts delete mode 100644 packages/plugins/src/wiki/template.json delete mode 100644 packages/plugins/tsconfig.json delete mode 100644 packages/plugins/type.d.ts create mode 100644 packages/service/common/middle/i18n.ts create mode 100644 packages/service/core/app/tool/api.ts delete mode 100644 packages/service/core/plugin/schema.ts delete mode 100644 packages/service/core/plugin/type.d.ts rename packages/service/core/workflow/dispatch/{agent/runTool => ai/agent}/constants.ts (100%) rename packages/service/core/workflow/dispatch/{agent/runTool => ai/agent}/functionCall.ts (99%) rename packages/service/core/workflow/dispatch/{agent/runTool => ai/agent}/index.ts (99%) rename packages/service/core/workflow/dispatch/{agent/runTool => ai/agent}/promptCall.ts (99%) rename packages/service/core/workflow/dispatch/{agent/runTool => ai/agent}/stopTool.ts (100%) rename packages/service/core/workflow/dispatch/{agent/runTool => ai/agent}/toolChoice.ts (99%) rename packages/service/core/workflow/dispatch/{agent/runTool => ai/agent}/toolParams.ts (100%) rename packages/service/core/workflow/dispatch/{agent/runTool => ai/agent}/type.d.ts (97%) rename packages/service/core/workflow/dispatch/{agent/runTool => ai/agent}/utils.ts (100%) rename packages/service/core/workflow/dispatch/{chat/oneapi.ts => ai/chat.ts} (100%) rename packages/service/core/workflow/dispatch/{agent => ai}/classifyQuestion.ts (100%) rename packages/service/core/workflow/dispatch/{agent => ai}/extract.ts (100%) create mode 100644 projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/ToolParamConfig.tsx create mode 100644 projects/app/src/pageComponents/app/plugin/SecretInputModal.tsx delete mode 100644 projects/app/src/pages/api/admin/initv47.ts delete mode 100644 projects/app/src/pages/api/admin/initv485.ts delete mode 100644 projects/app/src/pages/api/plugins/TFSwitch/index.ts delete mode 100644 projects/app/src/pages/api/plugins/customFeedback/index.ts delete mode 100644 projects/app/src/pages/api/plugins/customFeedback/v2/index.ts delete mode 100644 projects/app/src/pages/api/plugins/textEditor/index.ts delete mode 100644 projects/app/src/pages/api/plugins/textEditor/v2/index.ts create mode 100644 projects/app/src/pages/api/system/pluginImgs/[...path].ts delete mode 100644 projects/app/src/service/core/app/plugin.ts create mode 100644 projects/app/src/web/core/workflow/type.d.ts diff --git a/.eslintignore b/.eslintignore index 8c323cd20..18a697aa7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,6 +3,7 @@ dist/ build/ .next/ out/ +local/ # 依赖目录 node_modules/ diff --git a/.github/workflows/docs-preview.yml b/.github/workflows/docs-preview.yml index a77a92e65..fc60a4593 100644 --- a/.github/workflows/docs-preview.yml +++ b/.github/workflows/docs-preview.yml @@ -71,25 +71,16 @@ jobs: command: pages deploy ./docSite/public --project-name=fastgpt-doc packageManager: npm - - name: Create deployment status comment - if: always() - env: - JOB_STATUS: ${{ job.status }} - PREVIEW_URL: ${{ steps.deploy.outputs.deployment-url }} - uses: actions/github-script@v6 + - name: '@finleyge/github-tools' + uses: FinleyGe/github-tools@0.0.1 + id: print-image-label + if: success() with: token: ${{ secrets.GITHUB_TOKEN }} - script: | - const success = process.env.JOB_STATUS === 'success'; - const deploymentUrl = `${process.env.PREVIEW_URL}`; - const status = success ? '✅ Success' : '❌ Failed'; - console.log(process.env.JOB_STATUS); - - const commentBody = `**Deployment Status: ${status}** - ${success ? `🔗 Preview URL: ${deploymentUrl}` : ''}`; - - await github.rest.issues.createComment({ - ...context.repo, - issue_number: context.payload.pull_request.number, - body: commentBody - }); + tool: issue-comment + title: 'Docs Preview:' + body: | + Deployment Status: ${status} + ``` + ${success ? `🔗 Preview URL: ${deploymentUrl}` : ''} + ``` diff --git a/.github/workflows/fastgpt-preview-image.yml b/.github/workflows/fastgpt-preview-image.yml index 661881d14..a2dcd490f 100644 --- a/.github/workflows/fastgpt-preview-image.yml +++ b/.github/workflows/fastgpt-preview-image.yml @@ -77,13 +77,15 @@ jobs: -t ${{ steps.config.outputs.DOCKER_REPO_TAGGED }} \ . - - uses: actions/github-script@v7 + - name: '@finleyge/github-tools' + uses: FinleyGe/github-tools@0.0.1 + id: print-image-label + if: success() with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: 'Preview ${{ matrix.image }} Image: `${{ steps.config.outputs.DOCKER_REPO_TAGGED }}`' - }) + token: ${{ secrets.GITHUB_TOKEN }} + tool: issue-comment + title: 'Preview ${{ matrix.image }} Image:' + body: | + ``` + ${{ steps.config.outputs.DOCKER_REPO_TAGGED }}` + ``` diff --git a/README.md b/README.md index 7f5d78438..956cb2efa 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b ## 💪 相关项目 +- [FastGPT-plugin](https://github.com/labring/fastgpt-plugin) - [Laf:3 分钟快速接入三方应用](https://github.com/labring/laf) - [Sealos:快速部署集群应用](https://github.com/labring/sealos) - [One API:多模型管理,支持 Azure、文心一言等](https://github.com/songquanpeng/one-api) diff --git a/docSite/assets/imgs/plugin-openapi.png b/docSite/assets/imgs/plugin-openapi.png new file mode 100644 index 0000000000000000000000000000000000000000..84706e738b09dd17548bf916c982b5ad9f9e45f1 GIT binary patch literal 77477 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 T2#x&){?v|Xsb(HA`TKtWXNKtx literal 0 HcmV?d00001 diff --git a/docSite/assets/imgs/plugin-openapi2.png b/docSite/assets/imgs/plugin-openapi2.png new file mode 100644 index 0000000000000000000000000000000000000000..8048b75d7a1e4527d25e186292b10dceccc9ee9b GIT binary patch literal 230965 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ⅆ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

?Ck884zhZJKI8hY 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

@N=?np2yj0yb2%)&GvJz8 z52ReGBs5wSiw$3R_+cvnaF+JvSKfSz4Ry{_193Av@KF4*kj~9StvVj{6Rz;C^)ZpD z{hGyMpU9-}nohpoCNi>ND5Kf&@rCE05T~h98XtCo9NpTYEz1jxsjs*ES#U1afShMo zuw5*{`qQw=q0{VJR~%44DfW-9RIK#Cu)qnFa{mpBJ<%~{nUK^yA4P0Qg16Qn>wf-= z{Q}*YPmG71)v9~+Qn{LsI(N<6S!e8+Q#C-^Bs9uM<&hhCcmyt0V`-ab@TN$RtbP={S^FeWju8;bG

M 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 -lN?tvr_`%IY9mG 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%0A>D;ZZ8y9a}v~LDJ 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 B*5m*H literal 0 HcmV?d00001 diff --git a/docSite/content/zh-cn/docs/development/docker.md b/docSite/content/zh-cn/docs/development/docker.md index b84451f1a..0ec679d2a 100644 --- a/docSite/content/zh-cn/docs/development/docker.md +++ b/docSite/content/zh-cn/docs/development/docker.md @@ -21,8 +21,9 @@ weight: 707 {{% alert icon="🤖" context="success" %}} - MongoDB:用于存储除了向量外的各类数据 -- PostgreSQL/Milvus:存储向量数据 -- OneAPI: 聚合各类 AI API,支持多模型调用 (任何模型问题,先自行通过 OneAPI 测试校验) +- MinIO: 用于存储插件的文件数据 +- PostgreSQL/Milvus/Oceanbase:存储向量数据 +- AIProxy: 聚合各类 AI API,支持多模型调用 {{% /alert %}} @@ -66,7 +67,14 @@ Zilliz Cloud 由 Milvus 原厂打造,是全托管的 SaaS 向量数据库服 如果使用`OpenAI`等国外模型接口,请确保可以正常访问,否则会报错:`Connection error` 等。 方案可以参考:[代理方案](/docs/development/proxy/) -### 2. 准备 Docker 环境 +### 2. 开放防火墙端口 + +1. 3000: fastgpt 主服务端口 +2. 3005: mcp server 端口 +3. 9000: minio 端口 +4. 9001: minio web控制台端口 + +### 3. 准备 Docker 环境 {{< tabs tabTotal="3" >}} {{< tab tabName="Linux" >}} @@ -148,29 +156,26 @@ curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/mai 找到 yml 文件中,fastgpt 容器的环境变量进行下面操作: -{{< tabs tabTotal="3" >}} -{{< tab tabName="PgVector版本" >}} +{{< tabs tabTotal="2" >}} +{{< tab tabName="所有版本通用操作" >}} {{< markdownify >}} -无需操作 +修改环境变量: + +``` +# fastgpt 容器 +FE_DOMAIN=前端外部可访问的地址。用于自动补全文件资源路径。例如 https:fastgpt.cn,不能填 localhost。 +DEFAULT_ROOT_PSW=root 用户密码,每次重启root 都会修改成这个密码 +AES256_SECRET_KEY=密钥加密 key,尽量取复杂密钥,一旦使用后,不能随便修改,否则会导致系统加密的数据无法正常解密 + +# fastgpt-plugin容器 +MINIO_HOST=minio 公网地址,用于给系统工具提供文件存储。例如 http://ip:9000 +``` {{< /markdownify >}} {{< /tab >}} -{{< tab tabName="Oceanbase版本" >}} -{{< markdownify >}} -无需操作 - -{{< /markdownify >}} -{{< /tab >}} -{{< tab tabName="Milvus版本" >}} -{{< markdownify >}} - -无需操作 - -{{< /markdownify >}} -{{< /tab >}} -{{< tab tabName="Zilliz版本" >}} +{{< tab tabName="Zilliz版本特有" >}} {{< markdownify >}} 打开 [Zilliz Cloud](https://zilliz.com.cn/), 创建实例并获取相关秘钥。 @@ -189,7 +194,7 @@ curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/mai ### 3. 修改 config.json 配置文件 -修改`config.json`文件中的`mcpServerProxyEndpoint`值,设置成`mcp server`的公网可访问地址,yml 文件中默认给出了映射到 3005 端口,如通过 IP 访问,则可能是:`120.172.2.10:3005`。 +修改`config.json`文件中的`mcpServerProxyEndpoint`值,设置成`mcp server`的公网可访问地址,yml 文件中默认给出了映射到 3005 端口,如通过 IP 访问,则可能是:`ip:3005`。 ### 4. 启动容器 diff --git a/docSite/content/zh-cn/docs/development/upgrading/4100.md b/docSite/content/zh-cn/docs/development/upgrading/4100.md new file mode 100644 index 000000000..4d29f4b5a --- /dev/null +++ b/docSite/content/zh-cn/docs/development/upgrading/4100.md @@ -0,0 +1,64 @@ +--- +title: 'V4.10.0' +description: 'FastGPT V4.10.0 更新说明' +icon: 'upgrade' +draft: false +toc: true +weight: 785 +--- + +## 更新指南 + +### Docker 版本 + +- 参考最新的[docker-compose.yml](https://github.com/labring/FastGPT/blob/main/deploy/docker/docker-compose-pgvector.yml)文件,加入`fastgpt-plugin`和`minio`服务。 +- 修改`fastgpt-plugin`环境变量`AUTH_TOKEN`为较复杂的值。 +- 修改`fastgpt-plugin`环境变量`MINIO_HOST`为`ip:9000` 或相关域名,要求公网可访问。 +- 更新`fastgpt`和`fastgpt-pro`(商业版)容器的环境变量: + +``` +PLUGIN_BASE_URL=http://fastgpt-plugin:3000 +PLUGIN_TOKEN=刚修改的 AUTH_TOKEN 值 +``` +- 更新`fastgpt`和`fastgpt-pro`镜像 tag: v4.10.0。 +- `docker-compose up -d`启动/更新所有服务。 + +### Sealos 版本 + +- 在 Sealos 桌面的`对象存储`中,新建一个存储桶,设置`publicRead`权限。并获取相关密钥: + +![](/imgs/sealos-s3.png) + +- 部署`fastgpt-plugin`服务,镜像`registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-plugin:v0.1`,无需公网访问,设置环境变量: + +``` +AUTH_TOKEN=鉴权 token + +# 日志等级: debug,info,warn,error +LOG_LEVEL=info + +# S3 配置 +MINIO_HOST=External +MINIO_PORT=443 +MINIO_USE_SSL=true +MINIO_ACCESS_KEY=Access Key +MINIO_SECRET_KEY=Secret Key +MINIO_BUCKET=存储桶名 +``` + +- 更新`fastgpt`和`fastgpt-pro`(商业版)容器的环境变量以及镜像 tag: v4.10.0。 + +``` +PLUGIN_BASE_URL=fastgpt-plugin 服务的内网地址 +PLUGIN_TOKEN=刚修改的 AUTH_TOKEN 值 +``` + +## 🚀 新增内容 + +1. 独立系统工具服务,支持系统工具独立开发和调试。 +2. 更新系统工具开发指南[系统工具开发指南](/docs/guide/plugins/dev_system_tool/)。 +3. 更新系统工具设计 +## ⚙️ 优化 + + +## 🐛 修复 diff --git a/docSite/content/zh-cn/docs/development/upgrading/4914.md b/docSite/content/zh-cn/docs/development/upgrading/4914.md index 165111ef8..64d894567 100644 --- a/docSite/content/zh-cn/docs/development/upgrading/4914.md +++ b/docSite/content/zh-cn/docs/development/upgrading/4914.md @@ -33,6 +33,7 @@ weight: 786 7. 过滤 CSV 导出时可能存在的危险字符串。 8. 添加安全请求头。 9. 修改密码,强制其他登录端失效。 +10. Cite 引用展示优化,识别前置的 url 并自动加空格。 ## 🐛 修复 diff --git a/docSite/content/zh-cn/docs/guide/plugins/design_plugin.md b/docSite/content/zh-cn/docs/guide/plugins/design_plugin.md new file mode 100644 index 000000000..0b9945aa5 --- /dev/null +++ b/docSite/content/zh-cn/docs/guide/plugins/design_plugin.md @@ -0,0 +1,23 @@ +--- +title: "系统插件设计" +description: "FastGPT 系统插件设计方案" +icon: "extension" +draft: false +toc: true +weight: 301 +--- + +## 背景 + +原先 FastGPT 的各项功能均采用单体应用,子 packages 的方式进行构建。随着用户范围增多,个性化需求丰富,以及多次交付时遇到的系统工具定制困难问题,导致我们对 +我们决定设计一种更为灵活的扩展 + +主要有如下的目的: +1. 解耦合,模块化。 +2. FastGPT-plugin 可以快速迭代,版本不依赖于 FastGPT +3. 降低开发复杂度(不需要运行 FastGPT 环境) +4. 插件市场 + +更远期的设想: +1. 以纯代码的形式构建应用 +2. 加入其他可以自定义的模块 diff --git a/docSite/content/zh-cn/docs/guide/plugins/dev_system_tool.md b/docSite/content/zh-cn/docs/guide/plugins/dev_system_tool.md new file mode 100644 index 000000000..c7b3d340c --- /dev/null +++ b/docSite/content/zh-cn/docs/guide/plugins/dev_system_tool.md @@ -0,0 +1,200 @@ +--- +title: "如何开发系统工具" +description: "FastGPT 系统工具开发指南" +icon: "home_repair_service" +draft: false +toc: true +weight: 302 +--- + +## 介绍 + +FastGPT 系统工具项目从 4.10.0 版本后移动到独立的`fastgpt-plugin`项目中,采用纯代码的模式进行工具编写。你可以在`fastgpt-plugin`项目中进行独立开发和调试好插件后,直接向 FastGPT 官方提交 PR 即可,无需运行 FastGPT 主服务。 + +## 概念 + +- 工具(Tool):最小的运行单元,每个工具都有唯一 ID 和特定的输入和输出。 +- 工具集(Toolset):工具的集合,可以包含多个工具。 + +在`fastgpt-plugin`中,你可以每次创建一个工具/工具集,每次提交时,仅接收一个工具/工具集。如需开发多个,可以创建多个 PR 进行提交。 + +## 1. 准备工作 + +- Fork[fastgpt-plugin 项目](https://github.com/labring/fastgpt-plugin) +- 安装[Bun](https://bun.sh/) +- 本地拉取项目进行 Dev 开发。 + - bun install + - bun run dev + +## 2. 初始化一个新的工具/攻击 + +### 2.1 执行创建命令 + +```bash +bun run new:tool +``` + +依据提示分别选择创建工具/工具集,以及目录名(小驼峰命名)。 + +执行完后,系统会在 `packages/tool/packages/[your-tool-name]`下生成一个工具/工具集的目录。 + +系统工具 (Tool) 文件结构如下: + +```plaintext +src // 源代码,处理逻辑 +└── index.ts +test // 测试样例 +└── index.test.ts +config.ts // 配置,配置工具的名称、描述、类型、图标等 +index.ts // 入口,不要改这个文件 +logo.svg // Logo,替换成你的工具的 Logo +package.json // npm 包 +``` + +工具集(toolset) 的文件结构如下: + +```plaintext +children +└── tool // 这个里面的结构就和上面的 tool 基本一致 +config.ts +index.ts +logo.svg +package.json +``` + +### 2.2 修改 config.ts + +- **name** 和 **description** 字段为中文和英文两种语言 +- **courseUrl** 密钥获取链接,或官网链接。 +- **author** 开发者名 +- **type** 为枚举类型,目前有: + - tools: 工具 + - search: 搜索 + - multimodal: 多模态 + - communication: 通讯 + - other: 其他 +- **versionList** (工具中配置)用于版本管理,是一个列表,其中的元素格式: + - value:版本号,建议使用 semver + - description: 描述 + - inputs 入参 + - outputs 返回值 +- **children**:(工具集 toolset 配置),需要将 tool import 后手动写入。 + +对于 ToolSet 下的 tool 来说,无需填写 `type`、`courseUrl`、`author`,这几个字段会继承 ToolSet 的配置。 + +#### inputs 参数格式 + +一般格式: + +```ts +{ + key: '本工具内唯一的 key,和 src/index.ts 中的 InputType 定义相同', + label: '前端显示的 label', + renderTypeList: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference], // 前端输入框的类型 + valueType: WorkflowIOValueTypeEnum.string, // 数据类型 + toolDescription: '工具调用时用到的描述' // 如果需要设置成工具调用参数,需要设置这个字段 +} +``` + +有一个特殊的 key `'system_input_config'`,其用于配置工具的`激活信息`,通常包含`密钥`、`Endpoint`、`Port`等。 + +配置中`inputType=secret`的数据,将会通过对称加密的方式保存,以保证安全性。 + +**参考 dalle3**: + +``` +"inputs": [ + { + key: 'system_input_config', // 必须为这个值 + label: '', // 为空即可 + inputList: [ + { + key: 'url', + label: 'Dalle3 接口基础地址', + description: '例如:https://api.openai.com', + required: true, + inputType: 'input' + }, + { + key: 'authorization', + label: '接口凭证(不需要 Bearer)', + description: 'sk-xxxx', + required: true, + inputType: 'secret' + } + ], + renderTypeList: [FlowNodeInputTypeEnum.hidden], // 必须为这个值 + valueType: WorkflowIOValueTypeEnum.object // 必须为这个值 + }, +.... +] +``` + +#### outputs 参数格式 +``` +{ + key: 'link', // 唯一键值对 + valueType: WorkflowIOValueTypeEnum.string, // 具体可以看这个 Enum 的类型定义 + label: '图片访问链接', // 名字 + description: '图片访问链接' // 描述,可选 +} +``` + +## 2. 编写处理逻辑 + +在 `[your-tool-name]/src/index.ts` 为入口编写处理逻辑,需要注意: + +1. 使用 zod 进行类型定义,导出为 InputType 和 OutputType 两个 Schema。 +2. 入口函数为 `tool`,可以定义其他的函数。 + +```ts +import { format } from 'date-fns'; +import { z } from 'zod'; + +export const InputType = z.object({ + formatStr: z.string().optional() +}); + +export const OutputType = z.object({ + time: z.string() +}); + +export async function tool(props: z.infer): Promise> { + const formatStr = props.formatStr || 'yyyy-MM-dd HH:mm:ss'; + + return { + time: format(new Date(), formatStr) + }; +} +``` + +上述例子给出了一个传入 formatStr (格式化字符串)并且返回当前时间的简单样例,如需安装包,可以在`/packages/tools/packages/[your-tool-name]`路径下,使用`bun install PACKAGE` 进行安装。 + +## 3. 调试 + +### 单测 + +在 `test/index.test.ts` 中编写测试样例,使用 `bun run test index.test.ts完整路径` 即可运行测试。 + +### 从 OpenAPI 文件进行测试 + +浏览器打开`localhost:3000/openapi`可进入`fastgpt-plugin`的 OpenAPI 页面,进行 API 调试。 + +![](/imgs/plugin-openapi.png) + +可以先通过`/tool/list`接口,获取工具列表,找到需要调试的工具的`toolId`。紧接着,通过`/tool/run`来运行工具获取实际结果。 + +![](/imgs/plugin-openapi2.png) + +### 从 FastGPT 主服务进行测试 + +如果本地运行有`FastGPT`主服务,则可以直接添加对应的工具进行测试。 + +### 可视化调试(TODO) + +## 4. 提交工具至官方目录 + +完毕上述所有内容后,向官方仓库 `https://github.com/labring/fastgpt-plugin` 提交 PR。官方人员审核通过后即可收录为 FastGPT 的官方插件。 + +如无需官方收录,可自行对该项目进行 Docker 打包,并替换官方镜像即可。 + diff --git a/docSite/content/zh-cn/docs/guide/plugins/how_to_submit_system_plugin.md b/docSite/content/zh-cn/docs/guide/plugins/how_to_submit_system_plugin.md deleted file mode 100644 index e8168bdee..000000000 --- a/docSite/content/zh-cn/docs/guide/plugins/how_to_submit_system_plugin.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: "如何提交系统插件" -description: "FastGPT 系统插件提交指南" -icon: "plugin_submission" -draft: false -toc: true -weight: 302 ---- - -> 如何向 FastGPT 社区提交系统插件 - -## 系统插件原则 - -- 尽可能的轻量简洁,以解决实际问题的工具为主 -- 不允许有密集 cpu 计算,不会占用大量内存占用或网络消耗 -- 不允许操作数据库 -- 不允许往固定的私人地址发送请求(不包含请求某些在线服务,例如 gapier, firecrawl等) -- 不允许使用私人包,可使用主流的开源包 - -## 什么插件可以合并 - -由于目前未采用按需安装的模式,合并进仓库的插件会全部展示给用户使用。 - -为了控制插件的质量以及避免数量过多带来的繁琐,并不是所有的插件都会被合并到开源仓库中,你可以提前 PR 与我们沟通插件的内容。 - -后续实现插件按需安装后,我们会允许更多的社区插件合入。 - -## 如何写一个系统插件 - 初步 - -FastGPT 系统插件和用户工作台的插件效果是一致的,所以你需要提前了解“插件”的定义和功能。 - -在 FastGPT 中,插件是一种特殊的工作流,它允许你将一个工作流封装起来,并自定义入口参数和出口参数,类似于代码里的 “子函数”。 - -1. ### 跑通 FastGPT dev 环境 - -需要在 dev 环境下执行下面的操作。 - -1. ### 在 FastGPT 工作台中,创建一个插件 - -选择基础模板即可。 - -![](/imgs/plugin_submission1.png) - -1. ### 创建系统插件配置 - -系统插件配置以及自定义代码,都会在 **packages/plugins** 目录下。 - -1. 在 **packages/plugins/src** 下,复制一份 **template** 目录,并修改名字。 -2. 打开目录里面的 template.json 文件,配置如下: -3. 目录还有一个 index.ts 文件,下文再提。 - -```TypeScript -{ - "author": "填写你的名字", - "version": "当前系统版本号", - "name": "插件名", - "avatar": "插件头像,需要配成 icon 格式。直接把 logo 图在 pr 评论区提交即可,我们会帮你加入。", - "intro": " 插件的描述,这个描述会影响工具调用", - "showStatus": false, // 是否在对话过程展示状态 - "weight": 10, // 排序权重,均默认 10 - - "isTool": true, // 是否作为工具调用节点 - "templateType": "tools", // 都填写 tools 即可,由官方来分类 - - "workflow": { // 这个对象先不管,待会直接粘贴导出的工作流即可 - "nodes": [], - "edges": [] - } -} -``` - -1. 打开 **packages/plugins/register** 文件,注册你的插件。在 list 数组中,加入一个你插件目录的名字,如下图的例子。如需构建插件组(带目录),可参考 DuckDuckGo 插件。 - -无需额外写代码的插件,直接放在 staticPluginList 内,需要在项目内额外写代码的,写在 packagePluginList 中。 - -![](/imgs/plugin_submission2.png) - -1. ### 完成工作流编排并测试 - -完成工作流编排后,可以点击右上角的发布,并在其他工作流中引入进行测试(此时属于团队插件)。 - -1. ### 复制配置到 template.json - -鼠标放置在左上角插件的头像和名称上,会出现对于下拉框操作,可以导出工作流配置。 - -导出的配置,会自动到剪切板,可以直接到 template.json 文件中粘贴使用,替换步骤 2 中,**workflow** 的值。 - -![](/imgs/plugin_submission3.png) - -1. ### 验证插件是否加载成功 - -刷新页面,打开系统插件,看其是否成功加载,并将其添加到工作流中使用。 - -![](/imgs/plugin_submission4.png) - -1. ### 提交 PR - -如果你觉得你的插件需要提交到开源仓库,可以通过 PR 形式向我们提交。 - -- 写清楚插件的介绍和功能 -- 配上插件运行的效果图 -- 插件参数填写说明,需要在 PR 中写清楚。例如,有些插件需要去某个提供商申请 key,需要附上对应的地址和教材,后续我们会加入到文档中。 - -## 写一个复杂的系统插件 - 进阶 - -这一章会介绍如何增加一些无法单纯通过编排实现的插件。因为可能需要用到网络请求或第三方包。 - -上一章提到,在插件的 **template** 目录下,还有一个 **index.ts** 文件,这个文件就是用来执行一些插件的代码的。你可以通过在 HTTP 节点中的 URL,填写插件的名字,即可触发该方法,下面以 **duckduckgo/search** 这个插件为例: - -![](/imgs/plugin_submission5.png) - -![](/imgs/plugin_submission6.png) - -![](/imgs/plugin_submission7.png) - -参考上面 3 张图片,当 HTTP 节点的 URL 为系统插件注册的名字时,该请求不会以 HTTP 形式发送,而是会请求到 index.ts 文件中的 main 方法。出入参则对应了 body 和自定义输出的字段名。 - -由于目前插件会默认插件输出均作为“工具调用”的结果,无法单独指定某些字段作为工具输出,所以,请避免插件的自定义输出携带大量说明字段。 \ No newline at end of file diff --git a/package.json b/package.json index df23feec4..e46810023 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ "previewIcon": "node ./scripts/icon/index.js", "api:gen": "tsc ./scripts/openapi/index.ts && node ./scripts/openapi/index.js && npx @redocly/cli build-docs ./scripts/openapi/openapi.json -o ./projects/app/public/openapi/index.html", "create:i18n": "node ./scripts/i18n/index.js", - "lint": "eslint \"**/*.{ts,tsx}\" --ignore-path .eslintignore", - "lint:fix": "eslint \"**/*.{ts,tsx}\" --fix --ignore-path .eslintignore", + "lint": "eslint \"**/*.{ts,tsx}\" --fix --ignore-path .eslintignore", "test": "vitest run", "test:workflow": "vitest run workflow" }, @@ -41,7 +40,7 @@ "pnpm format-code" ], "./**/**/*.{ts,tsx}": [ - "pnpm lint:fix" + "pnpm lint" ], "./docSite/**/**/*.md": "pnpm format-doc && pnpm gen:llms" }, diff --git a/packages/global/common/error/utils.ts b/packages/global/common/error/utils.ts index 69cf364a6..63c8c9654 100644 --- a/packages/global/common/error/utils.ts +++ b/packages/global/common/error/utils.ts @@ -10,6 +10,7 @@ export const getErrText = (err: any, def = ''): any => { err?.response?.data?.msg || err?.response?.msg || err?.msg || + err?.error || def; // msg && console.log('error =>', msg); return replaceSensitiveText(msg); diff --git a/projects/app/src/web/common/utils/i18n.ts b/packages/global/common/i18n/type.ts similarity index 66% rename from projects/app/src/web/common/utils/i18n.ts rename to packages/global/common/i18n/type.ts index bcb1c3c21..002099bbe 100644 --- a/projects/app/src/web/common/utils/i18n.ts +++ b/packages/global/common/i18n/type.ts @@ -1,11 +1,18 @@ -import { type I18nNsType } from '@fastgpt/web/types/i18next'; -import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; +export type I18nStringType = { + 'zh-CN'?: string; + 'zh-Hant'?: string; + en: string; +}; export enum LangEnum { 'zh_CN' = 'zh-CN', 'zh_Hant' = 'zh-Hant', 'en' = 'en' } + +export type localeType = `${LangEnum}`; +export const LocaleList = ['en', 'zh-CN', 'zh-Hant'] as const; + export const langMap = { [LangEnum.en]: { label: 'English(US)', diff --git a/packages/global/common/i18n/utils.ts b/packages/global/common/i18n/utils.ts new file mode 100644 index 000000000..8e3f5082b --- /dev/null +++ b/packages/global/common/i18n/utils.ts @@ -0,0 +1,6 @@ +import type { I18nStringType, localeType } from './type'; + +export const parseI18nString = (str: I18nStringType | string = '', lang: localeType = 'en') => { + if (!str || typeof str === 'string') return str; + return str[lang] ?? str['en']; +}; diff --git a/packages/global/core/app/httpPlugin/utils.ts b/packages/global/core/app/httpPlugin/utils.ts index 740e86fe5..d69967ed3 100644 --- a/packages/global/core/app/httpPlugin/utils.ts +++ b/packages/global/core/app/httpPlugin/utils.ts @@ -8,7 +8,7 @@ import { WorkflowIOValueTypeEnum } from '../../workflow/constants'; import { PluginInputModule } from '../../workflow/template/system/pluginInput'; import { PluginOutputModule } from '../../workflow/template/system/pluginOutput'; import { HttpNode468 } from '../../workflow/template/system/http468'; -import { type HttpParamAndHeaderItemType } from '../../workflow/api'; +import { type HttpParamAndHeaderItemType } from '../../workflow/type/io'; import { type StoreNodeItemType } from '../../workflow/type/node'; import { HttpImgUrl } from '../../../common/file/image/constants'; import SwaggerParser from '@apidevtools/swagger-parser'; diff --git a/packages/global/core/app/mcpTools/utils.ts b/packages/global/core/app/mcpTools/utils.ts index af1ffa3ae..b7d2d0d91 100644 --- a/packages/global/core/app/mcpTools/utils.ts +++ b/packages/global/core/app/mcpTools/utils.ts @@ -3,13 +3,13 @@ import { NodeOutputKeyEnum, WorkflowIOValueTypeEnum } from '../../workflow/constants'; +import { i18nT } from '../../../../web/i18n/utils'; import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from '../../workflow/node/constant'; import { type McpToolConfigType } from '../type'; -import { i18nT } from '../../../../web/i18n/utils'; import { type RuntimeNodeItemType } from '../../workflow/runtime/type'; import { type StoreSecretValueType } from '../../../common/secret/type'; import { jsonSchema2NodeInput } from '../jsonschema'; diff --git a/packages/global/core/app/plugin/constants.ts b/packages/global/core/app/plugin/constants.ts new file mode 100644 index 000000000..60b0df4af --- /dev/null +++ b/packages/global/core/app/plugin/constants.ts @@ -0,0 +1,7 @@ +export enum PluginSourceEnum { + personal = 'personal', // this is a app. + systemTool = 'systemTool', // FastGPT-plugin tools, pure code. + commercial = 'commercial', // configured in Pro, with associatedPluginId. Specially, commercial-dalle3 is a systemTool + // @deprecated + community = 'community' // this is deprecated, will be replaced by systemTool +} diff --git a/packages/global/core/app/plugin/type.d.ts b/packages/global/core/app/plugin/type.d.ts new file mode 100644 index 000000000..1377074cd --- /dev/null +++ b/packages/global/core/app/plugin/type.d.ts @@ -0,0 +1,63 @@ +import type { StoreEdgeItemType } from 'core/workflow/type/edge'; +import { ModuleTemplateTypeEnum } from '../../workflow/constants'; +import type { StoreNodeItemType } from '../../workflow/type/node'; +import { MethodType } from './controller'; +import type { FlowNodeTemplateType } from '../../workflow/type/node'; +import type { WorkflowTemplateType } from '../../workflow/type'; +import type { FlowNodeInputItemType, FlowNodeOutputItemType } from '../../workflow/type/io'; +import type { ParentIdType } from 'common/parentFolder/type'; + +export type PluginRuntimeType = { + id: string; + teamId?: string; + tmbId?: string; + + name: string; + avatar: string; + showStatus?: boolean; + isTool?: boolean; + nodes: StoreNodeItemType[]; + edges: StoreEdgeItemType[]; + currentCost?: number; + hasTokenFee?: boolean; +}; + +// system plugin +export type SystemPluginTemplateItemType = WorkflowTemplateType & { + parentId?: ParentIdType; + isFolder?: boolean; + templateType: string; + + // FastGPT-plugin tool + inputs?: FlowNodeInputItemType[]; + outputs?: FlowNodeOutputItemType[]; + versionList?: { + value: string; + description?: string; + }[]; + + // Admin workflow tool + associatedPluginId?: string; + userGuide?: string; + + // commercial plugin config + originCost?: number; // n points/one time + currentCost?: number; + hasTokenFee?: boolean; + pluginOrder?: number; + + isActive?: boolean; + isOfficial?: boolean; + + // Admin config + inputList?: FlowNodeInputItemType['inputList']; + hasSystemSecret?: boolean; +}; + +export type SystemPluginTemplateListItemType = Omit< + SystemPluginTemplateItemType, + 'name' | 'intro' +> & { + name: string; + intro: string; +}; diff --git a/packages/global/core/app/systemTool/constants.ts b/packages/global/core/app/systemTool/constants.ts new file mode 100644 index 000000000..8b13b4610 --- /dev/null +++ b/packages/global/core/app/systemTool/constants.ts @@ -0,0 +1,18 @@ +import { i18nT } from '../../../../web/i18n/utils'; + +export enum SystemToolInputTypeEnum { + system = 'system', + team = 'team', + manual = 'manual' +} +export const SystemToolInputTypeMap = { + [SystemToolInputTypeEnum.system]: { + text: i18nT('common:System') + }, + [SystemToolInputTypeEnum.team]: { + text: i18nT('common:Team') + }, + [SystemToolInputTypeEnum.manual]: { + text: i18nT('common:Manual') + } +}; diff --git a/packages/global/core/app/type.d.ts b/packages/global/core/app/type.d.ts index ed5145418..3d83a9f44 100644 --- a/packages/global/core/app/type.d.ts +++ b/packages/global/core/app/type.d.ts @@ -6,7 +6,7 @@ import type { VariableInputEnum, WorkflowIOValueTypeEnum } from '../workflow/constants'; -import type { SelectedDatasetType } from '../workflow/api'; +import type { SelectedDatasetType } from '../workflow/type/io'; import type { DatasetSearchModeEnum } from '../dataset/constants'; import { TeamTagSchema as TeamTagsSchemaType } from '@fastgpt/global/support/user/team/type.d'; import type { StoreEdgeItemType } from '../workflow/type/edge'; diff --git a/packages/global/core/app/utils.ts b/packages/global/core/app/utils.ts index adda6f73a..87d88837e 100644 --- a/packages/global/core/app/utils.ts +++ b/packages/global/core/app/utils.ts @@ -53,7 +53,7 @@ export const appWorkflow2Form = ({ nodes.forEach((node) => { if ( node.flowNodeType === FlowNodeTypeEnum.chatNode || - node.flowNodeType === FlowNodeTypeEnum.tools + node.flowNodeType === FlowNodeTypeEnum.agent ) { defaultAppForm.aiSettings.model = findInputValueByKey(node.inputs, NodeInputKeyEnum.aiModel); defaultAppForm.aiSettings.systemPrompt = findInputValueByKey( diff --git a/packages/global/core/chat/utils.ts b/packages/global/core/chat/utils.ts index d40d1c356..1e92b13f5 100644 --- a/packages/global/core/chat/utils.ts +++ b/packages/global/core/chat/utils.ts @@ -94,7 +94,7 @@ export const filterPublicNodeResponseData = ({ const publicNodeMap: Record = { [FlowNodeTypeEnum.pluginModule]: true, [FlowNodeTypeEnum.datasetSearchNode]: true, - [FlowNodeTypeEnum.tools]: true, + [FlowNodeTypeEnum.agent]: true, [FlowNodeTypeEnum.pluginOutput]: true }; diff --git a/packages/global/core/plugin/constants.ts b/packages/global/core/plugin/constants.ts deleted file mode 100644 index 6778f04d6..000000000 --- a/packages/global/core/plugin/constants.ts +++ /dev/null @@ -1,25 +0,0 @@ -export enum PluginTypeEnum { - folder = 'folder', - custom = 'custom', - http = 'http' -} -export const pluginTypeMap = { - [PluginTypeEnum.folder]: { - label: '文件夹', - icon: 'file/fill/folder' - }, - [PluginTypeEnum.custom]: { - label: '自定义', - icon: 'common/custom' - }, - [PluginTypeEnum.http]: { - label: 'HTTP', - icon: 'common/http' - } -}; - -export enum PluginSourceEnum { - personal = 'personal', - community = 'community', - commercial = 'commercial' -} diff --git a/packages/global/core/plugin/controller.d.ts b/packages/global/core/plugin/controller.d.ts deleted file mode 100644 index aa8052da6..000000000 --- a/packages/global/core/plugin/controller.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { StoreEdgeItemType } from 'core/workflow/type/edge'; -import type { StoreNodeItemType } from '../workflow/type/node'; -import type { PluginTypeEnum } from './constants'; -import { HttpAuthMethodType } from '../app/httpPlugin/type'; - -export type CreateOnePluginParams = { - name: string; - avatar: string; - intro: string; - modules: StoreNodeItemType[]; - parentId: string | null; - type: `${PluginTypeEnum}`; - metadata?: { - apiSchemaStr?: string; - customHeaders?: string; - }; -}; -export type UpdatePluginParams = { - id: string; - parentId?: string | null; - name?: string; - avatar?: string; - intro?: string; - modules?: StoreNodeItemType[]; - edges?: StoreEdgeItemType[]; - metadata?: { - apiSchemaStr?: string; - customHeaders?: string; - }; -}; -export type PluginListItemType = { - _id: string; - parentId: string; - type: `${PluginTypeEnum}`; - name: string; - avatar: string; - intro: string; - metadata?: { - apiSchemaStr?: string; - customHeaders?: string; - }; -}; diff --git a/packages/global/core/plugin/type.d.ts b/packages/global/core/plugin/type.d.ts deleted file mode 100644 index 08ad06dd2..000000000 --- a/packages/global/core/plugin/type.d.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { StoreEdgeItemType } from 'core/workflow/type/edge'; -import { ModuleTemplateTypeEnum } from '../workflow/constants'; -import type { StoreNodeItemType } from '../workflow/type/node'; -import type { PluginSourceEnum, PluginTypeEnum } from './constants'; -import { MethodType } from './controller'; -import type { FlowNodeTemplateType } from '../workflow/type/node'; - -export type PluginItemSchema = { - _id: string; - userId: string; - teamId: string; - tmbId: string; - name: string; - avatar: string; - intro: string; - updateTime: Date; - modules: StoreNodeItemType[]; - edges: StoreEdgeItemType[]; - parentId: string; - type: `${PluginTypeEnum}`; - metadata?: { - pluginUid?: string; - apiSchemaStr?: string; - customHeaders?: string; - }; - version?: 'v1' | 'v2'; - nodeVersion?: string; - inited?: boolean; -}; - -/* plugin template */ -export type PluginTemplateType = PluginRuntimeType & { - author?: string; - id: string; - source: PluginSourceEnum; - templateType: FlowNodeTemplateType['templateType']; - intro: string; - version: string; -}; - -export type PluginRuntimeType = { - id: string; - teamId?: string; - tmbId?: string; - - name: string; - avatar: string; - showStatus?: boolean; - isTool?: boolean; - nodes: StoreNodeItemType[]; - edges: StoreEdgeItemType[]; - currentCost?: number; - hasTokenFee?: boolean; -}; diff --git a/packages/global/core/workflow/api.d.ts b/packages/global/core/workflow/api.d.ts deleted file mode 100644 index 24934d2db..000000000 --- a/packages/global/core/workflow/api.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { EmbeddingModelItemType } from '../ai/model.d'; -import { NodeInputKeyEnum } from './constants'; - -export type SelectedDatasetType = { - datasetId: string; - avatar: string; - name: string; - vectorModel: EmbeddingModelItemType; -}[]; - -export type HttpBodyType> = { - // [NodeInputKeyEnum.addInputParam]: Record; -} & T; -export type HttpQueryType = { - appId: string; - chatId?: string; - responseChatItemId?: string; - variables: Record; - [key: string]: any; -}; - -/* http node */ -export type HttpParamAndHeaderItemType = { - key: string; - type: string; - value: string; -}; diff --git a/packages/global/core/workflow/constants.ts b/packages/global/core/workflow/constants.ts index 2cc68823a..7498d30f4 100644 --- a/packages/global/core/workflow/constants.ts +++ b/packages/global/core/workflow/constants.ts @@ -5,14 +5,23 @@ export enum FlowNodeTemplateTypeEnum { systemInput = 'systemInput', ai = 'ai', function = 'function', - tools = 'tools', interactive = 'interactive', + // System tool type + tools = 'tools', search = 'search', multimodal = 'multimodal', communication = 'communication', - + finance = 'finance', + design = 'design', + productivity = 'productivity', + news = 'news', + entertainment = 'entertainment', + social = 'social', + scientific = 'scientific', other = 'other', + + // Team app type teamApp = 'teamApp' } @@ -143,6 +152,7 @@ export enum NodeInputKeyEnum { addInputParam = 'system_addInputParam', forbidStream = 'system_forbid_stream', headerSecret = 'system_header_secret', + systemInputConfig = 'system_input_config', // history historyMaxAmount = 'maxContext', @@ -263,6 +273,7 @@ export enum NodeOutputKeyEnum { text = 'system_text', addOutputParam = 'system_addOutputParam', rawResponse = 'system_rawResponse', + systemError = 'system_error', // start userFiles = 'userFiles', diff --git a/packages/global/core/workflow/node/constant.ts b/packages/global/core/workflow/node/constant.ts index 086459d2b..2b86b2f7c 100644 --- a/packages/global/core/workflow/node/constant.ts +++ b/packages/global/core/workflow/node/constant.ts @@ -1,5 +1,5 @@ -import { WorkflowIOValueTypeEnum } from '../constants'; import { i18nT } from '../../../../web/i18n/utils'; +import { WorkflowIOValueTypeEnum } from '../constants'; export enum FlowNodeInputTypeEnum { // render ui reference = 'reference', // reference to other node output input = 'input', // one line input @@ -125,7 +125,7 @@ export enum FlowNodeTypeEnum { pluginInput = 'pluginInput', pluginOutput = 'pluginOutput', queryExtension = 'cfr', - tools = 'tools', + agent = 'tools', stopTool = 'stopTool', toolParams = 'toolParams', lafModule = 'lafModule', diff --git a/packages/global/core/workflow/node/io/utils.ts b/packages/global/core/workflow/node/io/utils.ts deleted file mode 100644 index 8ec53e568..000000000 --- a/packages/global/core/workflow/node/io/utils.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { type FlowNodeInputItemType } from '../../type/io'; - -export const getInputComponentProps = (input: FlowNodeInputItemType) => { - return { - referencePlaceholder: input.referencePlaceholder, - placeholder: input.placeholder, - maxLength: input.maxLength, - list: input.list, - markList: input.markList, - step: input.step, - max: input.max, - min: input.min, - defaultValue: input.defaultValue, - llmModelType: input.llmModelType, - customInputConfig: input.customInputConfig - }; -}; diff --git a/packages/global/core/workflow/runtime/type.d.ts b/packages/global/core/workflow/runtime/type.d.ts index 55690a30d..8b69cb11a 100644 --- a/packages/global/core/workflow/runtime/type.d.ts +++ b/packages/global/core/workflow/runtime/type.d.ts @@ -1,7 +1,6 @@ import type { ChatNodeUsageType } from '../../../support/wallet/bill/type'; import type { ChatItemType, - UserChatItemValueItemType, ToolRunResponseItemType, AIChatItemValueItemType } from '../../chat/type'; @@ -96,15 +95,15 @@ export type RuntimeNodeItemType = { flowNodeType: StoreNodeItemType['flowNodeType']; showStatus?: StoreNodeItemType['showStatus']; isEntry?: boolean; + version?: string; inputs: FlowNodeInputItemType[]; outputs: FlowNodeOutputItemType[]; pluginId?: string; // workflow id / plugin id - version?: string; - // tool - toolConfig?: NodeToolConfigType; + // Tool + toolConfig?: StoreNodeItemType['toolConfig']; }; export type RuntimeEdgeItemType = StoreEdgeItemType & { diff --git a/packages/global/core/workflow/runtime/utils.ts b/packages/global/core/workflow/runtime/utils.ts index 9518e3f59..1a1675cc7 100644 --- a/packages/global/core/workflow/runtime/utils.ts +++ b/packages/global/core/workflow/runtime/utils.ts @@ -1,20 +1,24 @@ -import { ChatCompletionRequestMessageRoleEnum } from '../../ai/constants'; -import { NodeInputKeyEnum, NodeOutputKeyEnum, WorkflowIOValueTypeEnum } from '../constants'; -import { FlowNodeTypeEnum } from '../node/constant'; -import { type StoreNodeItemType } from '../type/node'; -import { type StoreEdgeItemType } from '../type/edge'; -import { type RuntimeEdgeItemType, type RuntimeNodeItemType } from './type'; -import { VARIABLE_NODE_ID } from '../constants'; -import { isValidReferenceValueFormat } from '../utils'; -import { type FlowNodeOutputItemType, type ReferenceValueType } from '../type/io'; -import { type ChatItemType, type NodeOutputItemType } from '../../../core/chat/type'; -import { ChatItemValueTypeEnum, ChatRoleEnum } from '../../../core/chat/constants'; -import { replaceVariable, valToStr } from '../../../common/string/tools'; import json5 from 'json5'; +import { replaceVariable, valToStr } from '../../../common/string/tools'; +import { ChatItemValueTypeEnum, ChatRoleEnum } from '../../../core/chat/constants'; +import type { ChatItemType, NodeOutputItemType } from '../../../core/chat/type'; +import { ChatCompletionRequestMessageRoleEnum } from '../../ai/constants'; +import { + NodeInputKeyEnum, + NodeOutputKeyEnum, + VARIABLE_NODE_ID, + WorkflowIOValueTypeEnum +} from '../constants'; +import { FlowNodeTypeEnum } from '../node/constant'; import { type InteractiveNodeResponseType, type WorkflowInteractiveResponseType } from '../template/system/interactive/type'; +import type { StoreEdgeItemType } from '../type/edge'; +import type { FlowNodeOutputItemType, ReferenceValueType } from '../type/io'; +import type { StoreNodeItemType } from '../type/node'; +import { isValidReferenceValueFormat } from '../utils'; +import type { RuntimeEdgeItemType, RuntimeNodeItemType } from './type'; export const extractDeepestInteractive = ( interactive: WorkflowInteractiveResponseType @@ -151,7 +155,7 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => { return value; }; -/* +/* Get interaction information (if any) from the last AI message. What can be done: 1. Get the interactive data @@ -254,7 +258,8 @@ export const storeNodes2RuntimeNodes = ( inputs: node.inputs, outputs: node.outputs, pluginId: node.pluginId, - version: node.version + version: node.version, + toolConfig: node.toolConfig }; }) || [] ); @@ -268,7 +273,7 @@ export const filterWorkflowEdges = (edges: RuntimeEdgeItemType[]) => { ); }; -/* +/* 1. 输入线分类:普通线和递归线(可以追溯到自身) 2. 起始线全部非 waiting 执行,或递归线全部非 waiting 执行 */ @@ -279,7 +284,7 @@ export const checkNodeRunStatus = ({ node: RuntimeNodeItemType; runtimeEdges: RuntimeEdgeItemType[]; }) => { - /* + /* 区分普通连线和递归连线 递归连线:可以通过往上查询 nodes,最终追溯到自身 */ @@ -363,7 +368,7 @@ export const checkNodeRunStatus = ({ return 'wait'; }; -/* +/* Get the value of the reference variable/node output 1. [string,string] 2. [string,string][] diff --git a/packages/global/core/workflow/template/constants.ts b/packages/global/core/workflow/template/constants.ts index c84783025..6a5e7e813 100644 --- a/packages/global/core/workflow/template/constants.ts +++ b/packages/global/core/workflow/template/constants.ts @@ -1,41 +1,41 @@ -import { SystemConfigNode } from './system/systemConfig'; -import { PluginConfigNode } from './system/pluginConfig'; -import { EmptyNode } from './system/emptyNode'; -import { WorkflowStart } from './system/workflowStart'; import { AiChatModule } from './system/aiChat'; -import { DatasetSearchModule } from './system/datasetSearch'; -import { DatasetConcatModule } from './system/datasetConcat'; import { AssignedAnswerModule } from './system/assignedAnswer'; import { ClassifyQuestionModule } from './system/classifyQuestion/index'; import { ContextExtractModule } from './system/contextExtract/index'; +import { DatasetConcatModule } from './system/datasetConcat'; +import { DatasetSearchModule } from './system/datasetSearch'; +import { EmptyNode } from './system/emptyNode'; import { HttpNode468 } from './system/http468'; +import { PluginConfigNode } from './system/pluginConfig'; +import { SystemConfigNode } from './system/systemConfig'; +import { WorkflowStart } from './system/workflowStart'; -import { ToolModule } from './system/tools'; import { StopToolNode } from './system/stopTool'; +import { AgentNode } from './system/agent'; import { RunAppModule } from './system/abandoned/runApp/index'; import { PluginInputModule } from './system/pluginInput'; import { PluginOutputModule } from './system/pluginOutput'; -import { RunPluginModule } from './system/runPlugin'; -import { RunAppNode } from './system/runApp'; import { AiQueryExtension } from './system/queryExtension'; +import { RunAppNode } from './system/runApp'; +import { RunPluginModule } from './system/runPlugin'; import type { FlowNodeTemplateType } from '../type/node'; -import { LafModule } from './system/laf'; -import { IfElseNode } from './system/ifElse/index'; -import { VariableUpdateNode } from './system/variableUpdate'; -import { CodeNode } from './system/sandbox'; -import { TextEditorNode } from './system/textEditor'; import { CustomFeedbackNode } from './system/customFeedback'; -import { ReadFilesNode } from './system/readFiles'; -import { UserSelectNode } from './system/interactive/userSelect'; -import { LoopNode } from './system/loop/loop'; -import { LoopStartNode } from './system/loop/loopStart'; -import { LoopEndNode } from './system/loop/loopEnd'; +import { IfElseNode } from './system/ifElse/index'; import { FormInputNode } from './system/interactive/formInput'; -import { ToolParamsNode } from './system/toolParams'; +import { UserSelectNode } from './system/interactive/userSelect'; +import { LafModule } from './system/laf'; +import { LoopNode } from './system/loop/loop'; +import { LoopEndNode } from './system/loop/loopEnd'; +import { LoopStartNode } from './system/loop/loopStart'; +import { ReadFilesNode } from './system/readFiles'; import { RunToolNode } from './system/runTool'; import { RunToolSetNode } from './system/runToolSet'; +import { CodeNode } from './system/sandbox'; +import { TextEditorNode } from './system/textEditor'; +import { ToolParamsNode } from './system/toolParams'; +import { VariableUpdateNode } from './system/variableUpdate'; const systemNodes: FlowNodeTemplateType[] = [ AiChatModule, @@ -45,7 +45,7 @@ const systemNodes: FlowNodeTemplateType[] = [ ClassifyQuestionModule, ContextExtractModule, DatasetConcatModule, - ToolModule, + AgentNode, ToolParamsNode, StopToolNode, ReadFilesNode, diff --git a/packages/global/core/workflow/template/system/abandoned/runApp/index.ts b/packages/global/core/workflow/template/system/abandoned/runApp/index.ts index 6c8a78712..d075afa87 100644 --- a/packages/global/core/workflow/template/system/abandoned/runApp/index.ts +++ b/packages/global/core/workflow/template/system/abandoned/runApp/index.ts @@ -12,15 +12,14 @@ import { FlowNodeTemplateTypeEnum } from '../../../../constants'; import { Input_Template_History, Input_Template_UserChatInput } from '../../../input'; -import { getHandleConfig } from '../../../utils'; import { i18nT } from '../../../../../../../web/i18n/utils'; export const RunAppModule: FlowNodeTemplateType = { id: FlowNodeTypeEnum.runApp, templateType: FlowNodeTemplateTypeEnum.tools, flowNodeType: FlowNodeTypeEnum.runApp, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/runApp', name: i18nT('workflow:application_call'), intro: i18nT('workflow:select_another_application_to_call'), diff --git a/packages/global/core/workflow/template/system/tools.ts b/packages/global/core/workflow/template/system/agent.ts similarity index 87% rename from packages/global/core/workflow/template/system/tools.ts rename to packages/global/core/workflow/template/system/agent.ts index b6ce2d1c3..3fe9baccd 100644 --- a/packages/global/core/workflow/template/system/tools.ts +++ b/packages/global/core/workflow/template/system/agent.ts @@ -3,7 +3,7 @@ import { FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from '../../node/constant'; -import { type FlowNodeTemplateType } from '../../type/node.d'; +import { type FlowNodeTemplateType } from '../../type/node'; import { WorkflowIOValueTypeEnum, NodeOutputKeyEnum, @@ -18,19 +18,18 @@ import { } from '../input'; import { chatNodeSystemPromptTip, systemPromptTip } from '../tip'; import { LLMModelTypeEnum } from '../../../ai/constants'; -import { getHandleConfig } from '../utils'; import { i18nT } from '../../../../../web/i18n/utils'; import { Input_Template_File_Link } from '../input'; -export const ToolModule: FlowNodeTemplateType = { - id: FlowNodeTypeEnum.tools, - flowNodeType: FlowNodeTypeEnum.tools, +export const AgentNode: FlowNodeTemplateType = { + id: FlowNodeTypeEnum.agent, + flowNodeType: FlowNodeTypeEnum.agent, templateType: FlowNodeTemplateTypeEnum.ai, - sourceHandle: getHandleConfig(true, true, false, true), - targetHandle: getHandleConfig(true, true, false, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/toolCall', - name: i18nT('workflow:template.tool_call'), - intro: i18nT('workflow:template.tool_call_intro'), + name: i18nT('workflow:template.agent'), + intro: i18nT('workflow:template.agent_intro'), showStatus: true, courseUrl: '/docs/guide/dashboard/workflow/tool/', version: '4.9.2', diff --git a/packages/global/core/workflow/template/system/aiChat/index.ts b/packages/global/core/workflow/template/system/aiChat/index.ts index 1fbc53c58..0881b0b85 100644 --- a/packages/global/core/workflow/template/system/aiChat/index.ts +++ b/packages/global/core/workflow/template/system/aiChat/index.ts @@ -19,7 +19,6 @@ import { Input_Template_UserChatInput, Input_Template_File_Link } from '../../input'; -import { getHandleConfig } from '../../utils'; import { i18nT } from '../../../../../../web/i18n/utils'; export const AiChatQuoteRole = { @@ -46,8 +45,8 @@ export const AiChatModule: FlowNodeTemplateType = { id: FlowNodeTypeEnum.chatNode, templateType: FlowNodeTemplateTypeEnum.ai, flowNodeType: FlowNodeTypeEnum.chatNode, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/aiChat', name: i18nT('workflow:template.ai_chat'), intro: i18nT('workflow:template.ai_chat_intro'), diff --git a/packages/global/core/workflow/template/system/assignedAnswer.ts b/packages/global/core/workflow/template/system/assignedAnswer.ts index b62009164..c46b7a3c3 100644 --- a/packages/global/core/workflow/template/system/assignedAnswer.ts +++ b/packages/global/core/workflow/template/system/assignedAnswer.ts @@ -5,15 +5,14 @@ import { NodeInputKeyEnum, FlowNodeTemplateTypeEnum } from '../../constants'; -import { getHandleConfig } from '../utils'; import { i18nT } from '../../../../../web/i18n/utils'; export const AssignedAnswerModule: FlowNodeTemplateType = { id: FlowNodeTypeEnum.answerNode, templateType: FlowNodeTemplateTypeEnum.tools, flowNodeType: FlowNodeTypeEnum.answerNode, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/reply', name: i18nT('workflow:assigned_reply'), intro: i18nT('workflow:intro_assigned_reply'), diff --git a/packages/global/core/workflow/template/system/classifyQuestion/index.ts b/packages/global/core/workflow/template/system/classifyQuestion/index.ts index 454b7e2e3..87411b0a9 100644 --- a/packages/global/core/workflow/template/system/classifyQuestion/index.ts +++ b/packages/global/core/workflow/template/system/classifyQuestion/index.ts @@ -17,15 +17,14 @@ import { } from '../../input'; import { Input_Template_System_Prompt } from '../../input'; import { LLMModelTypeEnum } from '../../../../ai/constants'; -import { getHandleConfig } from '../../utils'; import { i18nT } from '../../../../../../web/i18n/utils'; export const ClassifyQuestionModule: FlowNodeTemplateType = { id: FlowNodeTypeEnum.classifyQuestion, templateType: FlowNodeTemplateTypeEnum.ai, flowNodeType: FlowNodeTypeEnum.classifyQuestion, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(true, false, true, true), + showSourceHandle: false, + showTargetHandle: true, avatar: 'core/workflow/template/questionClassify', name: i18nT('workflow:question_classification'), intro: i18nT('workflow:intro_question_classification'), diff --git a/packages/global/core/workflow/template/system/comment.ts b/packages/global/core/workflow/template/system/comment.ts index aa7145be1..d3e1a191c 100644 --- a/packages/global/core/workflow/template/system/comment.ts +++ b/packages/global/core/workflow/template/system/comment.ts @@ -5,14 +5,13 @@ import { NodeInputKeyEnum, WorkflowIOValueTypeEnum } from '../../constants'; -import { getHandleConfig } from '../utils'; export const CommentNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.comment, templateType: FlowNodeTemplateTypeEnum.systemInput, flowNodeType: FlowNodeTypeEnum.comment, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(false, false, false, false), + showSourceHandle: false, + showTargetHandle: false, avatar: '', name: '', intro: '', diff --git a/packages/global/core/workflow/template/system/contextExtract/index.ts b/packages/global/core/workflow/template/system/contextExtract/index.ts index 2dd55187c..04cab9130 100644 --- a/packages/global/core/workflow/template/system/contextExtract/index.ts +++ b/packages/global/core/workflow/template/system/contextExtract/index.ts @@ -12,15 +12,14 @@ import { } from '../../../constants'; import { Input_Template_SelectAIModel, Input_Template_History } from '../../input'; import { LLMModelTypeEnum } from '../../../../ai/constants'; -import { getHandleConfig } from '../../utils'; import { i18nT } from '../../../../../../web/i18n/utils'; export const ContextExtractModule: FlowNodeTemplateType = { id: FlowNodeTypeEnum.contentExtract, templateType: FlowNodeTemplateTypeEnum.ai, flowNodeType: FlowNodeTypeEnum.contentExtract, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/extractJson', name: i18nT('workflow:text_content_extraction'), intro: i18nT('workflow:intro_text_content_extraction'), diff --git a/packages/global/core/workflow/template/system/customFeedback.ts b/packages/global/core/workflow/template/system/customFeedback.ts index f5f3be338..c445c9bdb 100644 --- a/packages/global/core/workflow/template/system/customFeedback.ts +++ b/packages/global/core/workflow/template/system/customFeedback.ts @@ -5,15 +5,14 @@ import { FlowNodeTemplateTypeEnum, NodeInputKeyEnum } from '../../constants'; -import { getHandleConfig } from '../utils'; import { i18nT } from '../../../../../web/i18n/utils'; export const CustomFeedbackNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.customFeedback, templateType: FlowNodeTemplateTypeEnum.other, flowNodeType: FlowNodeTypeEnum.customFeedback, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/customFeedback', name: i18nT('workflow:custom_feedback'), intro: i18nT('workflow:intro_custom_feedback'), diff --git a/packages/global/core/workflow/template/system/datasetConcat.ts b/packages/global/core/workflow/template/system/datasetConcat.ts index 5f171f57a..6b13d77ed 100644 --- a/packages/global/core/workflow/template/system/datasetConcat.ts +++ b/packages/global/core/workflow/template/system/datasetConcat.ts @@ -12,7 +12,6 @@ import { FlowNodeTemplateTypeEnum } from '../../constants'; import { getNanoid } from '../../../../common/string/tools'; -import { getHandleConfig } from '../utils'; import { type FlowNodeInputItemType } from '../../type/io.d'; import { i18nT } from '../../../../../web/i18n/utils'; @@ -35,8 +34,8 @@ export const DatasetConcatModule: FlowNodeTemplateType = { id: FlowNodeTypeEnum.datasetConcatNode, flowNodeType: FlowNodeTypeEnum.datasetConcatNode, templateType: FlowNodeTemplateTypeEnum.other, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/datasetConcat', name: i18nT('workflow:knowledge_base_search_merge'), intro: i18nT('workflow:intro_knowledge_base_search_merge'), diff --git a/packages/global/core/workflow/template/system/datasetSearch.ts b/packages/global/core/workflow/template/system/datasetSearch.ts index 4965c37cd..5a9b9b993 100644 --- a/packages/global/core/workflow/template/system/datasetSearch.ts +++ b/packages/global/core/workflow/template/system/datasetSearch.ts @@ -14,7 +14,6 @@ import { } from '../../constants'; import { Input_Template_UserChatInput } from '../input'; import { DatasetSearchModeEnum } from '../../../dataset/constants'; -import { getHandleConfig } from '../utils'; import { i18nT } from '../../../../../web/i18n/utils'; export const Dataset_SEARCH_DESC = i18nT('workflow:template.dataset_search_intro'); @@ -23,8 +22,8 @@ export const DatasetSearchModule: FlowNodeTemplateType = { id: FlowNodeTypeEnum.datasetSearchNode, templateType: FlowNodeTemplateTypeEnum.ai, flowNodeType: FlowNodeTypeEnum.datasetSearchNode, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/datasetSearch', name: i18nT('workflow:template.dataset_search'), intro: Dataset_SEARCH_DESC, diff --git a/packages/global/core/workflow/template/system/emptyNode.ts b/packages/global/core/workflow/template/system/emptyNode.ts index c88171b6e..d9a20ffd1 100644 --- a/packages/global/core/workflow/template/system/emptyNode.ts +++ b/packages/global/core/workflow/template/system/emptyNode.ts @@ -1,14 +1,13 @@ import { FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node'; import { FlowNodeTemplateTypeEnum } from '../../constants'; -import { getHandleConfig } from '../utils'; export const EmptyNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.emptyNode, templateType: FlowNodeTemplateTypeEnum.systemInput, flowNodeType: FlowNodeTypeEnum.emptyNode, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(false, false, false, false), + showSourceHandle: false, + showTargetHandle: false, avatar: '', name: '', intro: '', diff --git a/packages/global/core/workflow/template/system/http468.ts b/packages/global/core/workflow/template/system/http468.ts index 5ce5635e1..ea0328043 100644 --- a/packages/global/core/workflow/template/system/http468.ts +++ b/packages/global/core/workflow/template/system/http468.ts @@ -13,15 +13,14 @@ import { } from '../../constants'; import { Input_Template_DynamicInput } from '../input'; import { Output_Template_AddOutput } from '../output'; -import { getHandleConfig } from '../utils'; import { i18nT } from '../../../../../web/i18n/utils'; export const HttpNode468: FlowNodeTemplateType = { id: FlowNodeTypeEnum.httpRequest468, templateType: FlowNodeTemplateTypeEnum.tools, flowNodeType: FlowNodeTypeEnum.httpRequest468, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/httpRequest', name: i18nT('workflow:http_request'), intro: i18nT('workflow:intro_http_request'), diff --git a/packages/global/core/workflow/template/system/ifElse/index.ts b/packages/global/core/workflow/template/system/ifElse/index.ts index ffbe49536..f422ef3ee 100644 --- a/packages/global/core/workflow/template/system/ifElse/index.ts +++ b/packages/global/core/workflow/template/system/ifElse/index.ts @@ -11,14 +11,13 @@ import { FlowNodeTypeEnum } from '../../../node/constant'; import { type FlowNodeTemplateType } from '../../../type/node'; -import { getHandleConfig } from '../../utils'; export const IfElseNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.ifElseNode, templateType: FlowNodeTemplateTypeEnum.tools, flowNodeType: FlowNodeTypeEnum.ifElseNode, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(true, false, true, true), + showSourceHandle: false, + showTargetHandle: true, avatar: 'core/workflow/template/ifelse', name: i18nT('workflow:condition_checker'), intro: i18nT('workflow:execute_different_branches_based_on_conditions'), diff --git a/packages/global/core/workflow/template/system/interactive/formInput.ts b/packages/global/core/workflow/template/system/interactive/formInput.ts index 5487f6f16..a7b74a5cc 100644 --- a/packages/global/core/workflow/template/system/interactive/formInput.ts +++ b/packages/global/core/workflow/template/system/interactive/formInput.ts @@ -11,14 +11,13 @@ import { FlowNodeTypeEnum } from '../../../node/constant'; import { type FlowNodeTemplateType } from '../../../type/node'; -import { getHandleConfig } from '../../utils'; export const FormInputNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.formInput, templateType: FlowNodeTemplateTypeEnum.interactive, flowNodeType: FlowNodeTypeEnum.formInput, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/formInput', name: i18nT('app:workflow.form_input'), intro: i18nT(`app:workflow.form_input_tip`), diff --git a/packages/global/core/workflow/template/system/interactive/userSelect.ts b/packages/global/core/workflow/template/system/interactive/userSelect.ts index 723cffa33..6854506b2 100644 --- a/packages/global/core/workflow/template/system/interactive/userSelect.ts +++ b/packages/global/core/workflow/template/system/interactive/userSelect.ts @@ -11,14 +11,13 @@ import { FlowNodeTypeEnum } from '../../../node/constant'; import { type FlowNodeTemplateType } from '../../../type/node.d'; -import { getHandleConfig } from '../../utils'; export const UserSelectNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.userSelect, templateType: FlowNodeTemplateTypeEnum.interactive, flowNodeType: FlowNodeTypeEnum.userSelect, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(true, false, true, true), + showSourceHandle: false, + showTargetHandle: true, avatar: 'core/workflow/template/userSelect', diagram: '/imgs/app/userSelect.svg', name: i18nT('app:workflow.user_select'), diff --git a/packages/global/core/workflow/template/system/laf.ts b/packages/global/core/workflow/template/system/laf.ts index c9d886eb7..4a4dfc912 100644 --- a/packages/global/core/workflow/template/system/laf.ts +++ b/packages/global/core/workflow/template/system/laf.ts @@ -12,7 +12,6 @@ import { } from '../../constants'; import { Input_Template_DynamicInput } from '../input'; import { Output_Template_AddOutput } from '../output'; -import { getHandleConfig } from '../utils'; import { i18nT } from '../../../../../web/i18n/utils'; export const nodeLafCustomInputConfig = { @@ -25,8 +24,8 @@ export const LafModule: FlowNodeTemplateType = { id: FlowNodeTypeEnum.lafModule, templateType: FlowNodeTemplateTypeEnum.other, flowNodeType: FlowNodeTypeEnum.lafModule, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/lafDispatch', name: i18nT('workflow:laf_function_call_test'), intro: i18nT('workflow:intro_laf_function_call'), diff --git a/packages/global/core/workflow/template/system/loop/loop.ts b/packages/global/core/workflow/template/system/loop/loop.ts index 16a5c75e1..2a2b28945 100644 --- a/packages/global/core/workflow/template/system/loop/loop.ts +++ b/packages/global/core/workflow/template/system/loop/loop.ts @@ -10,7 +10,6 @@ import { NodeOutputKeyEnum, WorkflowIOValueTypeEnum } from '../../../constants'; -import { getHandleConfig } from '../../utils'; import { i18nT } from '../../../../../../web/i18n/utils'; import { Input_Template_Children_Node_List, @@ -23,8 +22,8 @@ export const LoopNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.loop, templateType: FlowNodeTemplateTypeEnum.tools, flowNodeType: FlowNodeTypeEnum.loop, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/loop', name: i18nT('workflow:loop'), intro: i18nT('workflow:intro_loop'), diff --git a/packages/global/core/workflow/template/system/loop/loopEnd.ts b/packages/global/core/workflow/template/system/loop/loopEnd.ts index 9712ac8b5..adfce6a84 100644 --- a/packages/global/core/workflow/template/system/loop/loopEnd.ts +++ b/packages/global/core/workflow/template/system/loop/loopEnd.ts @@ -6,14 +6,13 @@ import { } from '../../../constants'; import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../../node/constant'; import { type FlowNodeTemplateType } from '../../../type/node'; -import { getHandleConfig } from '../../utils'; export const LoopEndNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.loopEnd, templateType: FlowNodeTemplateTypeEnum.systemInput, flowNodeType: FlowNodeTypeEnum.loopEnd, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(false, false, false, true), + showSourceHandle: false, + showTargetHandle: true, unique: true, forbidDelete: true, avatar: 'core/workflow/template/loopEnd', diff --git a/packages/global/core/workflow/template/system/loop/loopStart.ts b/packages/global/core/workflow/template/system/loop/loopStart.ts index c355b8af9..59a4cc0ec 100644 --- a/packages/global/core/workflow/template/system/loop/loopStart.ts +++ b/packages/global/core/workflow/template/system/loop/loopStart.ts @@ -10,15 +10,14 @@ import { NodeOutputKeyEnum, WorkflowIOValueTypeEnum } from '../../../constants'; -import { getHandleConfig } from '../../utils'; import { i18nT } from '../../../../../../web/i18n/utils'; export const LoopStartNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.loopStart, templateType: FlowNodeTemplateTypeEnum.systemInput, flowNodeType: FlowNodeTypeEnum.loopStart, - sourceHandle: getHandleConfig(false, true, false, false), - targetHandle: getHandleConfig(false, false, false, false), + showSourceHandle: true, + showTargetHandle: false, avatar: 'core/workflow/template/loopStart', name: i18nT('workflow:loop_start'), unique: true, diff --git a/packages/global/core/workflow/template/system/pluginConfig.ts b/packages/global/core/workflow/template/system/pluginConfig.ts index 5b5960c67..dceec8926 100644 --- a/packages/global/core/workflow/template/system/pluginConfig.ts +++ b/packages/global/core/workflow/template/system/pluginConfig.ts @@ -1,15 +1,14 @@ import { FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node.d'; import { FlowNodeTemplateTypeEnum } from '../../constants'; -import { getHandleConfig } from '../utils'; import { i18nT } from '../../../../../web/i18n/utils'; export const PluginConfigNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.pluginConfig, templateType: FlowNodeTemplateTypeEnum.systemInput, flowNodeType: FlowNodeTypeEnum.pluginConfig, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(false, false, false, false), + showSourceHandle: false, + showTargetHandle: false, avatar: 'core/workflow/template/systemConfig', name: i18nT('workflow:template.system_config'), intro: '', diff --git a/packages/global/core/workflow/template/system/pluginInput.ts b/packages/global/core/workflow/template/system/pluginInput.ts index 262c810a0..d8847c852 100644 --- a/packages/global/core/workflow/template/system/pluginInput.ts +++ b/packages/global/core/workflow/template/system/pluginInput.ts @@ -2,14 +2,13 @@ import { i18nT } from '../../../../../web/i18n/utils'; import { FlowNodeTemplateTypeEnum } from '../../constants'; import { FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node'; -import { getHandleConfig } from '../utils'; export const PluginInputModule: FlowNodeTemplateType = { id: FlowNodeTypeEnum.pluginInput, templateType: FlowNodeTemplateTypeEnum.systemInput, flowNodeType: FlowNodeTypeEnum.pluginInput, - sourceHandle: getHandleConfig(false, true, false, false), - targetHandle: getHandleConfig(false, false, false, false), + showSourceHandle: true, + showTargetHandle: false, unique: true, forbidDelete: true, avatar: 'core/workflow/template/workflowStart', diff --git a/packages/global/core/workflow/template/system/pluginOutput.ts b/packages/global/core/workflow/template/system/pluginOutput.ts index b5cb49eb3..960e6dd88 100644 --- a/packages/global/core/workflow/template/system/pluginOutput.ts +++ b/packages/global/core/workflow/template/system/pluginOutput.ts @@ -2,14 +2,13 @@ import { i18nT } from '../../../../../web/i18n/utils'; import { FlowNodeTemplateTypeEnum } from '../../constants'; import { FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node'; -import { getHandleConfig } from '../utils'; export const PluginOutputModule: FlowNodeTemplateType = { id: FlowNodeTypeEnum.pluginOutput, templateType: FlowNodeTemplateTypeEnum.systemInput, flowNodeType: FlowNodeTypeEnum.pluginOutput, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(false, false, false, true), + showSourceHandle: false, + showTargetHandle: true, unique: true, forbidDelete: true, avatar: 'core/workflow/template/pluginOutput', diff --git a/packages/global/core/workflow/template/system/queryExtension.ts b/packages/global/core/workflow/template/system/queryExtension.ts index acadecb01..01ee258b1 100644 --- a/packages/global/core/workflow/template/system/queryExtension.ts +++ b/packages/global/core/workflow/template/system/queryExtension.ts @@ -15,16 +15,14 @@ import { Input_Template_UserChatInput, Input_Template_SelectAIModel } from '../input'; -import { LLMModelTypeEnum } from '../../../ai/constants'; -import { getHandleConfig } from '../utils'; import { i18nT } from '../../../../../web/i18n/utils'; export const AiQueryExtension: FlowNodeTemplateType = { id: FlowNodeTypeEnum.queryExtension, templateType: FlowNodeTemplateTypeEnum.other, flowNodeType: FlowNodeTypeEnum.queryExtension, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/queryExtension', name: i18nT('workflow:question_optimization'), intro: i18nT('workflow:intro_question_optimization'), diff --git a/packages/global/core/workflow/template/system/readFiles/index.tsx b/packages/global/core/workflow/template/system/readFiles/index.tsx index beaa38559..1e6711bcf 100644 --- a/packages/global/core/workflow/template/system/readFiles/index.tsx +++ b/packages/global/core/workflow/template/system/readFiles/index.tsx @@ -11,14 +11,13 @@ import { FlowNodeTypeEnum } from '../../../node/constant'; import { type FlowNodeTemplateType } from '../../../type/node'; -import { getHandleConfig } from '../../utils'; export const ReadFilesNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.readFiles, templateType: FlowNodeTemplateTypeEnum.tools, flowNodeType: FlowNodeTypeEnum.readFiles, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/readFiles', name: i18nT('app:workflow.read_files'), intro: i18nT('app:workflow.read_files_tip'), diff --git a/packages/global/core/workflow/template/system/runApp.ts b/packages/global/core/workflow/template/system/runApp.ts index cf8a8534c..dc3221766 100644 --- a/packages/global/core/workflow/template/system/runApp.ts +++ b/packages/global/core/workflow/template/system/runApp.ts @@ -1,14 +1,13 @@ import { FlowNodeTemplateTypeEnum } from '../../constants'; import { FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node'; -import { getHandleConfig } from '../utils'; export const RunAppNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.appModule, templateType: FlowNodeTemplateTypeEnum.other, flowNodeType: FlowNodeTypeEnum.appModule, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, intro: '', name: '', showStatus: false, diff --git a/packages/global/core/workflow/template/system/runPlugin.ts b/packages/global/core/workflow/template/system/runPlugin.ts index 1ee726d09..7c0c1c8c1 100644 --- a/packages/global/core/workflow/template/system/runPlugin.ts +++ b/packages/global/core/workflow/template/system/runPlugin.ts @@ -1,14 +1,13 @@ import { FlowNodeTemplateTypeEnum } from '../../constants'; import { FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node'; -import { getHandleConfig } from '../utils'; export const RunPluginModule: FlowNodeTemplateType = { id: FlowNodeTypeEnum.pluginModule, templateType: FlowNodeTemplateTypeEnum.other, flowNodeType: FlowNodeTypeEnum.pluginModule, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, intro: '', name: '', showStatus: false, diff --git a/packages/global/core/workflow/template/system/runTool.ts b/packages/global/core/workflow/template/system/runTool.ts index 60df16363..e7a91ac7e 100644 --- a/packages/global/core/workflow/template/system/runTool.ts +++ b/packages/global/core/workflow/template/system/runTool.ts @@ -1,14 +1,13 @@ import { FlowNodeTemplateTypeEnum } from '../../constants'; import { FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node'; -import { getHandleConfig } from '../utils'; export const RunToolNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.tool, templateType: FlowNodeTemplateTypeEnum.other, flowNodeType: FlowNodeTypeEnum.tool, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, intro: '', name: '', showStatus: false, diff --git a/packages/global/core/workflow/template/system/runToolSet.ts b/packages/global/core/workflow/template/system/runToolSet.ts index 71aefac76..8cb05095d 100644 --- a/packages/global/core/workflow/template/system/runToolSet.ts +++ b/packages/global/core/workflow/template/system/runToolSet.ts @@ -1,18 +1,17 @@ import { FlowNodeTemplateTypeEnum } from '../../constants'; import { FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node'; -import { getHandleConfig } from '../utils'; export const RunToolSetNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.toolSet, templateType: FlowNodeTemplateTypeEnum.other, flowNodeType: FlowNodeTypeEnum.toolSet, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(false, false, false, false), + showSourceHandle: false, + showTargetHandle: false, + isTool: true, intro: '', name: '', showStatus: false, - isTool: true, inputs: [], outputs: [] }; diff --git a/packages/global/core/workflow/template/system/sandbox/index.ts b/packages/global/core/workflow/template/system/sandbox/index.ts index cc7203fc2..53422c950 100644 --- a/packages/global/core/workflow/template/system/sandbox/index.ts +++ b/packages/global/core/workflow/template/system/sandbox/index.ts @@ -10,7 +10,6 @@ import { FlowNodeTypeEnum } from '../../../node/constant'; import { type FlowNodeTemplateType } from '../../../type/node'; -import { getHandleConfig } from '../../utils'; import { Input_Template_DynamicInput } from '../../input'; import { Output_Template_AddOutput } from '../../output'; import { JS_TEMPLATE } from './constants'; @@ -20,8 +19,8 @@ export const CodeNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.code, templateType: FlowNodeTemplateTypeEnum.tools, flowNodeType: FlowNodeTypeEnum.code, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/codeRun', name: i18nT('workflow:code_execution'), intro: i18nT('workflow:execute_a_simple_script_code_usually_for_complex_data_processing'), diff --git a/packages/global/core/workflow/template/system/stopTool.ts b/packages/global/core/workflow/template/system/stopTool.ts index e2e7cb36b..0f0a434ac 100644 --- a/packages/global/core/workflow/template/system/stopTool.ts +++ b/packages/global/core/workflow/template/system/stopTool.ts @@ -1,15 +1,14 @@ import { FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node'; import { FlowNodeTemplateTypeEnum } from '../../constants'; -import { getHandleConfig } from '../utils'; import { i18nT } from '../../../../../web/i18n/utils'; export const StopToolNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.stopTool, templateType: FlowNodeTemplateTypeEnum.ai, flowNodeType: FlowNodeTypeEnum.stopTool, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: false, + showTargetHandle: true, avatar: 'core/workflow/template/stopTool', name: i18nT('workflow:tool_call_termination'), intro: i18nT('workflow:intro_tool_call_termination'), diff --git a/packages/global/core/workflow/template/system/systemConfig.ts b/packages/global/core/workflow/template/system/systemConfig.ts index e9c3efcd0..c44a2a130 100644 --- a/packages/global/core/workflow/template/system/systemConfig.ts +++ b/packages/global/core/workflow/template/system/systemConfig.ts @@ -1,15 +1,14 @@ import { FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node.d'; import { FlowNodeTemplateTypeEnum } from '../../constants'; -import { getHandleConfig } from '../utils'; import { i18nT } from '../../../../../web/i18n/utils'; export const SystemConfigNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.systemConfig, templateType: FlowNodeTemplateTypeEnum.systemInput, flowNodeType: FlowNodeTypeEnum.systemConfig, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(false, false, false, false), + showSourceHandle: false, + showTargetHandle: false, avatar: 'core/workflow/template/systemConfig', name: i18nT('workflow:template.system_config'), intro: '', diff --git a/packages/global/core/workflow/template/system/textEditor.ts b/packages/global/core/workflow/template/system/textEditor.ts index 7faf6e5fe..38f24b2fd 100644 --- a/packages/global/core/workflow/template/system/textEditor.ts +++ b/packages/global/core/workflow/template/system/textEditor.ts @@ -10,16 +10,14 @@ import { FlowNodeTemplateTypeEnum, NodeInputKeyEnum } from '../../constants'; -import { getHandleConfig } from '../utils'; -import { Input_Template_DynamicInput } from '../input'; import { i18nT } from '../../../../../web/i18n/utils'; export const TextEditorNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.textEditor, templateType: FlowNodeTemplateTypeEnum.tools, flowNodeType: FlowNodeTypeEnum.textEditor, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/textConcat', name: i18nT('workflow:text_concatenation'), intro: i18nT('workflow:intro_text_concatenation'), diff --git a/packages/global/core/workflow/template/system/toolParams.ts b/packages/global/core/workflow/template/system/toolParams.ts index 22267a59c..86bff22d8 100644 --- a/packages/global/core/workflow/template/system/toolParams.ts +++ b/packages/global/core/workflow/template/system/toolParams.ts @@ -1,15 +1,14 @@ import { FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node'; import { FlowNodeTemplateTypeEnum } from '../../constants'; -import { getHandleConfig } from '../utils'; import { i18nT } from '../../../../../web/i18n/utils'; export const ToolParamsNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.toolParams, templateType: FlowNodeTemplateTypeEnum.ai, flowNodeType: FlowNodeTypeEnum.toolParams, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/toolParams', name: i18nT('workflow:tool_custom_field'), intro: i18nT('workflow:intro_tool_params_config'), diff --git a/packages/global/core/workflow/template/system/variableUpdate/index.tsx b/packages/global/core/workflow/template/system/variableUpdate/index.tsx index 50206246f..1294e3aef 100644 --- a/packages/global/core/workflow/template/system/variableUpdate/index.tsx +++ b/packages/global/core/workflow/template/system/variableUpdate/index.tsx @@ -5,15 +5,14 @@ import { NodeInputKeyEnum, WorkflowIOValueTypeEnum } from '../../../constants'; -import { getHandleConfig } from '../../utils'; import { i18nT } from '../../../../../../web/i18n/utils'; export const VariableUpdateNode: FlowNodeTemplateType = { id: FlowNodeTypeEnum.variableUpdate, templateType: FlowNodeTemplateTypeEnum.tools, flowNodeType: FlowNodeTypeEnum.variableUpdate, - sourceHandle: getHandleConfig(true, true, true, true), - targetHandle: getHandleConfig(true, true, true, true), + showSourceHandle: true, + showTargetHandle: true, avatar: 'core/workflow/template/variableUpdate', name: i18nT('workflow:variable_update'), intro: i18nT('workflow:update_specified_node_output_or_global_variable'), diff --git a/packages/global/core/workflow/template/system/workflowStart.ts b/packages/global/core/workflow/template/system/workflowStart.ts index 54b1dbb63..4a2c9bc7d 100644 --- a/packages/global/core/workflow/template/system/workflowStart.ts +++ b/packages/global/core/workflow/template/system/workflowStart.ts @@ -5,7 +5,6 @@ import { NodeOutputKeyEnum, FlowNodeTemplateTypeEnum } from '../../constants'; -import { getHandleConfig } from '../utils'; import { Input_Template_UserChatInput } from '../input'; import { i18nT } from '../../../../../web/i18n/utils'; import { type FlowNodeOutputItemType } from '../../type/io'; @@ -23,8 +22,8 @@ export const WorkflowStart: FlowNodeTemplateType = { id: FlowNodeTypeEnum.workflowStart, templateType: FlowNodeTemplateTypeEnum.systemInput, flowNodeType: FlowNodeTypeEnum.workflowStart, - sourceHandle: getHandleConfig(false, true, false, false), - targetHandle: getHandleConfig(false, false, false, false), + showSourceHandle: true, + showTargetHandle: false, avatar: 'core/workflow/template/workflowStart', name: i18nT('workflow:template.workflow_start'), intro: '', diff --git a/packages/global/core/workflow/template/tip.ts b/packages/global/core/workflow/template/tip.ts index d02c64af6..b4b88041a 100644 --- a/packages/global/core/workflow/template/tip.ts +++ b/packages/global/core/workflow/template/tip.ts @@ -1,2 +1,4 @@ -export const chatNodeSystemPromptTip = 'core.app.tip.chatNodeSystemPromptTip'; -export const systemPromptTip = 'core.app.tip.systemPromptTip'; +import { i18nT } from '../../../../web/i18n/utils'; + +export const chatNodeSystemPromptTip = i18nT('common:core.app.tip.chatNodeSystemPromptTip'); +export const systemPromptTip = i18nT('common:core.app.tip.systemPromptTip'); diff --git a/packages/global/core/workflow/template/utils.ts b/packages/global/core/workflow/template/utils.ts deleted file mode 100644 index f66b9d436..000000000 --- a/packages/global/core/workflow/template/utils.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const getHandleConfig = (top: boolean, right: boolean, bottom: boolean, left: boolean) => ({ - top, - right, - bottom, - left -}); diff --git a/packages/global/core/workflow/type/fe.d.ts b/packages/global/core/workflow/type/fe.d.ts deleted file mode 100644 index 7e25db1b3..000000000 --- a/packages/global/core/workflow/type/fe.d.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { FlowNodeInputItemType, FlowNodeOutputItemType } from './io'; - -export type FlowNodeChangeProps = { nodeId: string } & ( - | { - type: 'attr'; // key: attr, value: new value - key: string; - value: any; - } - | { - type: 'updateInput'; // key: update input key, value: new input value - key: string; - value: FlowNodeInputItemType; - } - | { - type: 'replaceInput'; // key: old input key, value: new input value - key: string; - value: FlowNodeInputItemType; - } - | { - type: 'addInput'; // key: null, value: new input value - value: FlowNodeInputItemType; - index?: number; - } - | { - type: 'delInput'; // key: delete input key, value: null - key: string; - } - | { - type: 'updateOutput'; // key: update output key, value: new output value - key: string; - value: FlowNodeOutputItemType; - } - | { - type: 'replaceOutput'; // key: old output key, value: new output value - key: string; - value: FlowNodeOutputItemType; - } - | { - type: 'addOutput'; // key: null, value: new output value - value: FlowNodeOutputItemType; - index?: number; - } - | { - type: 'delOutput'; // key: delete output key, value: null - key: string; - } -); diff --git a/packages/global/core/workflow/type/index.d.ts b/packages/global/core/workflow/type/index.d.ts index 2bfa1787b..de20f9aee 100644 --- a/packages/global/core/workflow/type/index.d.ts +++ b/packages/global/core/workflow/type/index.d.ts @@ -6,7 +6,8 @@ import { VariableInputEnum } from '../constants'; import { DispatchNodeResponseKeyEnum } from '../runtime/constants'; -import { CustomInputItemType, FlowNodeInputItemType, FlowNodeOutputItemType } from './io.d'; +import type { FlowNodeInputItemType, FlowNodeOutputItemType } from './io.d'; +import { CustomInputItemType } from './io.d'; import { ChatHistoryItemResType, ChatItemType, @@ -14,13 +15,14 @@ import { ToolRunResponseItemType } from '../../chat/type'; import { ChatNodeUsageType } from '../../../support/wallet/bill/type'; -import { PluginTypeEnum } from '../../plugin/constants'; import type { StoreEdgeItemType } from './edge'; import type { AppChatConfigType } from '../../app/type'; import type { ParentIdType } from 'common/parentFolder/type'; import type { AppTypeEnum } from 'core/app/constants'; import type { StoreNodeItemType } from './node'; import { FlowNodeTemplateType } from './node'; +import type { SecretValueType } from './../../../common/secret/type'; +import type { I18nStringType } from '../../../common/i18n/type'; export type WorkflowTemplateBasicType = { nodes: StoreNodeItemType[]; @@ -32,19 +34,15 @@ export type WorkflowTemplateType = { parentId?: ParentIdType; isFolder?: boolean; - name: string; avatar: string; - intro?: string; + name: I18nStringType | string; + intro?: I18nStringType | string; + author?: string; courseUrl?: string; - - version?: string; - versionLabel?: string; - isLatestVersion?: boolean; - - showStatus?: boolean; weight?: number; + version?: string; workflow: WorkflowTemplateBasicType; }; @@ -63,43 +61,3 @@ export type TemplateMarketListItemType = { type: AppTypeEnum.simple | AppTypeEnum.workflow | AppTypeEnum.plugin; avatar: string; }; - -// system plugin -export type SystemPluginTemplateItemType = WorkflowTemplateType & { - customWorkflow?: string; - associatedPluginId?: string; - userGuide?: string; - - templateType: string; - isTool?: boolean; - - // commercial plugin config - originCost: number; // n points/one time - currentCost: number; - hasTokenFee: boolean; - pluginOrder: number; - - isActive?: boolean; - isOfficial?: boolean; - inputConfig?: { - // Render config input form. Find the corresponding node and replace the variable directly - key: string; - label: string; - description: string; - value?: any; - }[]; -}; - -export type THelperLine = { - position: number; - nodes: { - left: number; - right: number; - top: number; - bottom: number; - width: number; - height: number; - centerX: number; - centerY: number; - }[]; -}; diff --git a/packages/global/core/workflow/type/io.d.ts b/packages/global/core/workflow/type/io.d.ts index 90bbf4a9d..382b212da 100644 --- a/packages/global/core/workflow/type/io.d.ts +++ b/packages/global/core/workflow/type/io.d.ts @@ -1,7 +1,8 @@ -import type { LLMModelItemType } from '../../ai/model.d'; +import type { EmbeddingModelItemType, LLMModelItemType } from '../../ai/model.d'; import type { LLMModelTypeEnum } from '../../ai/constants'; import type { WorkflowIOValueTypeEnum, NodeInputKeyEnum, NodeOutputKeyEnum } from '../constants'; import type { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum } from '../node/constant'; +import type { SecretValueType } from '../../../common/secret/type'; // Dynamic input field configuration export type CustomFieldConfigType = { @@ -10,11 +11,6 @@ export type CustomFieldConfigType = { // reference selectValueTypeList?: WorkflowIOValueTypeEnum[]; // 可以选哪个数据类型, 只有1个的话,则默认选择 - // showIsToolParam?: boolean; // 是否作为工具参数 - - // showRequired?: boolean; - // defaultRequired?: boolean; - showDefaultValue?: boolean; showDescription?: boolean; }; @@ -29,6 +25,7 @@ export type InputComponentPropsType = { step?: number; // slider max?: number; // slider, number input min?: number; // slider, number input + precision?: number; // number input defaultValue?: string; @@ -37,6 +34,17 @@ export type InputComponentPropsType = { // dynamic input customInputConfig?: CustomFieldConfigType; }; +export type InputConfigType = { + key: string; + label: string; + description?: string; + required?: boolean; + inputType: 'input' | 'numberInput' | 'secret' | 'switch' | 'select'; + value?: SecretValueType; + + // Selector + list?: { label: string; value: string }[]; +}; export type FlowNodeInputItemType = InputComponentPropsType & { selectedTypeIndex?: number; @@ -52,6 +60,8 @@ export type FlowNodeInputItemType = InputComponentPropsType & { required?: boolean; enum?: string; + inputList?: InputConfigType[]; // when key === 'system_input_config', this field is used + toolDescription?: string; // If this field is not empty, it is entered as a tool // render components params @@ -92,6 +102,21 @@ export type FlowNodeOutputItemType = { deprecated?: boolean; }; +// Field value type export type ReferenceItemValueType = [string, string | undefined]; export type ReferenceArrayValueType = ReferenceItemValueType[]; export type ReferenceValueType = ReferenceItemValueType | ReferenceArrayValueType; + +export type SelectedDatasetType = { + datasetId: string; + avatar: string; + name: string; + vectorModel: EmbeddingModelItemType; +}[]; + +/* http node */ +export type HttpParamAndHeaderItemType = { + key: string; + type: string; + value: string; +}; diff --git a/packages/global/core/workflow/type/node.d.ts b/packages/global/core/workflow/type/node.d.ts index 8a7d27923..ba45fd1d3 100644 --- a/packages/global/core/workflow/type/node.d.ts +++ b/packages/global/core/workflow/type/node.d.ts @@ -17,7 +17,6 @@ import { } from '../../chat/type'; import { ChatNodeUsageType } from '../../../support/wallet/bill/type'; import { RuntimeNodeItemType } from '../runtime/type'; -import { PluginTypeEnum } from '../../plugin/constants'; import { RuntimeEdgeItemType, StoreEdgeItemType } from './edge'; import { NextApiResponse } from 'next'; import type { AppDetailType, AppSchema, McpToolConfigType } from '../../app/type'; @@ -29,6 +28,9 @@ export type NodeToolConfigType = { mcpTool?: McpToolConfigType & { url: string; }; + systemTool?: { + toolId: string; + }; }; export type FlowNodeCommonType = { @@ -55,7 +57,12 @@ export type FlowNodeCommonType = { pluginData?: PluginDataType; // tool data - toolData?: NodeToolConfigType; + toolConfig?: NodeToolConfigType; + + // Not store, just computed + currentCost?: number; + hasTokenFee?: boolean; + hasSystemSecret?: boolean; }; export type PluginDataType = { @@ -78,9 +85,8 @@ export type FlowNodeTemplateType = FlowNodeCommonType & { id: string; // node id, unique templateType: string; - // show handle - sourceHandle?: HandleType; - targetHandle?: HandleType; + showSourceHandle?: boolean; + showTargetHandle?: boolean; // info isTool?: boolean; // can be connected by tool @@ -92,6 +98,11 @@ export type FlowNodeTemplateType = FlowNodeCommonType & { diagram?: string; // diagram url courseUrl?: string; // course url userGuide?: string; // user guide + + // @deprecated + // show handle + sourceHandle?: HandleType; + targetHandle?: HandleType; }; export type NodeTemplateListItemType = { diff --git a/packages/global/core/workflow/utils.ts b/packages/global/core/workflow/utils.ts index fc05fe934..2756f4537 100644 --- a/packages/global/core/workflow/utils.ts +++ b/packages/global/core/workflow/utils.ts @@ -274,9 +274,6 @@ export const appData2FlowNodeIO = ({ }; }); - // const showFileLink = - // chatConfig?.fileSelectConfig?.canSelectFile || chatConfig?.fileSelectConfig?.canSelectImg; - return { inputs: [ Input_Template_Stream_MODE, @@ -356,7 +353,7 @@ export const formatEditorVariablePickerIcon = ( export const isValidReferenceValueFormat = (value: any): value is ReferenceItemValueType => { return Array.isArray(value) && value.length === 2 && typeof value[0] === 'string'; }; -/* +/* Check whether the value([variableId, outputId]) value is a valid reference value: 1. The value must be an array of length 2 2. The first item of the array must be one of VARIABLE_NODE_ID or nodeIds @@ -370,7 +367,7 @@ export const isValidReferenceValue = ( const validIdSet = new Set([VARIABLE_NODE_ID, ...nodeIds]); return validIdSet.has(value[0]); }; -/* +/* Check whether the value([variableId, outputId][]) value is a valid reference value array: 1. The value must be an array 2. The array must contain at least one element diff --git a/packages/plugins/README.md b/packages/plugins/README.md deleted file mode 100644 index 19ab10f20..000000000 --- a/packages/plugins/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Package 说明 - -该 package 存放工作流系统插件。 \ No newline at end of file diff --git a/packages/plugins/package.json b/packages/plugins/package.json deleted file mode 100644 index 5f0d39e16..000000000 --- a/packages/plugins/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "@fastgpt/plugins", - "version": "1.0.0", - "type": "module", - "dependencies": { - "cheerio": "1.0.0-rc.12", - "@types/pg": "^8.6.6", - "@types/nodemailer": "^6.4.17", - "axios": "^1.8.2", - "duck-duck-scrape": "^2.2.5", - "echarts": "5.4.1", - "expr-eval": "^2.0.2", - "lodash": "^4.17.21", - "mssql": "^11.0.1", - "mysql2": "^3.11.3", - "json5": "^2.2.3", - "nodemailer": "^6.10.0", - "pg": "^8.10.0", - "wikijs": "^6.4.1" - }, - "devDependencies": { - "@fastgpt/global": "workspace:*", - "@fastgpt/service": "workspace:*", - "@types/lodash": "^4.14.191", - "@types/node": "20.14.0" - } -} diff --git a/packages/plugins/register.ts b/packages/plugins/register.ts deleted file mode 100644 index 41c17355c..000000000 --- a/packages/plugins/register.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; -import { type SystemPluginResponseType } from './type'; -import { type SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type'; -import { cloneDeep } from 'lodash'; -import { WorkerNameEnum, runWorker } from '@fastgpt/service/worker/utils'; - -// Run in main thread -const staticPluginList = [ - 'getTime', - 'fetchUrl', - 'feishu', - 'DingTalkWebhook', - 'WeWorkWebhook', - 'google', - 'bing', - 'bocha', - 'delay' -]; -// Run in worker thread (Have npm packages) -const packagePluginList = [ - 'mathExprVal', - 'duckduckgo', - 'duckduckgo/search', - 'duckduckgo/searchImg', - 'duckduckgo/searchNews', - 'duckduckgo/searchVideo', - 'drawing', - 'drawing/baseChart', - 'wiki', - 'databaseConnection', - 'Doc2X', - 'Doc2X/PDF2text', - 'searchXNG', - 'smtpEmail' -]; - -export const list = [...staticPluginList, ...packagePluginList]; - -/* Get plugins */ -export const getCommunityPlugins = () => { - return Promise.all( - list.map>(async (name) => { - const config = (await import(`./src/${name}/template.json`))?.default; - - const isFolder = list.find((item) => item.startsWith(`${name}/`)); - - const parentIdList = name.split('/').slice(0, -1); - const parentId = - parentIdList.length > 0 ? `${PluginSourceEnum.community}-${parentIdList.join('/')}` : null; - - return { - ...config, - id: `${PluginSourceEnum.community}-${name}`, - isFolder, - parentId, - isActive: true, - isOfficial: true - }; - }) - ); -}; - -export const getSystemPluginTemplates = () => { - if (!global.systemPlugins) return []; - - const oldPlugins = global.communityPlugins ?? []; - return [...oldPlugins, ...cloneDeep(global.systemPlugins)]; -}; - -export const getCommunityCb = async () => { - const loadCommunityModule = async (name: string) => { - const pluginModule = await import(`./src/${name}/index`); - return pluginModule.default; - }; - - const result = ( - await Promise.all( - list.map(async (name) => { - try { - return { - name, - cb: staticPluginList.includes(name) - ? await loadCommunityModule(name) - : (e: any) => { - return runWorker(WorkerNameEnum.systemPluginRun, { - pluginName: name, - data: e - }); - } - }; - } catch (error) {} - }) - ) - ).filter(Boolean) as { - name: string; - cb: any; - }[]; - - return result.reduce SystemPluginResponseType>>( - (acc, { name, cb }) => { - acc[name] = cb; - return acc; - }, - {} - ); -}; diff --git a/packages/plugins/runtime/worker.ts b/packages/plugins/runtime/worker.ts deleted file mode 100644 index 979c8e580..000000000 --- a/packages/plugins/runtime/worker.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { type SystemPluginResponseType } from '../type'; -import { parentPort } from 'worker_threads'; - -const loadModule = async (name: string): Promise<(e: any) => SystemPluginResponseType> => { - const pluginModule = await import(`../src/${name}/index`); - return pluginModule.default; -}; - -parentPort?.on('message', async ({ pluginName, data }: { pluginName: string; data: any }) => { - try { - const cb = await loadModule(pluginName); - parentPort?.postMessage({ - type: 'success', - data: await cb(data) - }); - } catch (error) { - parentPort?.postMessage({ - type: 'error', - data: error - }); - } - - process.exit(); -}); diff --git a/packages/plugins/src/DingTalkWebhook/template.json b/packages/plugins/src/DingTalkWebhook/template.json deleted file mode 100644 index 056e13d5c..000000000 --- a/packages/plugins/src/DingTalkWebhook/template.json +++ /dev/null @@ -1,535 +0,0 @@ -{ - "author": "", - "name": "钉钉 webhook", - "avatar": "plugins/dingding", - "intro": "向钉钉机器人发起 webhook 请求。", - "courseUrl": "https://open.dingtalk.com/document/robots/custom-robot-access", - "showStatus": false, - "weight": 10, - "isTool": true, - "templateType": "communication", - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "自定义配置外部输入,使用插件时,仅暴露自定义配置的输入", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 557.4542421888484, - "y": -131.2827008898969 - }, - "version": "481", - "inputs": [ - { - "inputType": "input", - "valueType": "string", - "key": "钉钉机器人地址", - "label": "钉钉机器人地址", - "description": "", - "isToolInput": false, - "defaultValue": "", - "editField": { - "key": true - }, - "dynamicParamDefaultValue": { - "inputType": "reference", - "valueType": "string", - "required": true - }, - "renderTypeList": ["input"], - "required": true, - "canEdit": true, - "value": "", - "list": [] - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "加签值", - "label": "加签值", - "description": "钉钉机器人加签值", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "发送的消息", - "label": "发送的消息", - "description": "发送的消息", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true, - "toolDescription": "发送的消息" - } - ], - "outputs": [ - { - "id": "mv52BrPVE6bm", - "key": "钉钉机器人地址", - "valueType": "string", - "label": "钉钉机器人地址", - "type": "static" - }, - { - "id": "srcret", - "valueType": "string", - "key": "加签值", - "label": "加签值", - "type": "hidden" - }, - { - "id": "发送的消息", - "valueType": "string", - "key": "发送的消息", - "label": "发送的消息", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 2420.0305926489386, - "y": -106.28270088989689 - }, - "version": "481", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "rKBYGQuYefae", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1645.779103978597, - "y": -431.7827008898969 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "{{$a5qdMS7ECNYE.qLUQfhG0ILRX$}}", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\r\n \"msgtype\": \"text\",\r\n \"text\": {\r\n \"content\": \"{{$pluginInput.发送的消息$}}\"\r\n }\r\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "editField": { - "key": true, - "valueType": true - } - } - ] - }, - { - "nodeId": "q3ccNXiZIHoS", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": 99.73879703925843, - "y": -201.26482361861054 - }, - "version": "4811", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "a5qdMS7ECNYE", - "name": "代码运行", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 1106.1011901190363, - "y": -407.7827008898969 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({url, secret}){\n const {sign,timestamp} = createHmac('sha256',secret)\n\n return {\n result: `${url}×tamp=${timestamp}&sign=${sign}`\n }\n}", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "url", - "label": "url", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "mv52BrPVE6bm"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "secret", - "label": "secret", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "srcret"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key", - "valueDesc": "" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "result", - "valueType": "string", - "label": "result", - "valueDesc": "", - "description": "" - } - ] - } - ], - "edges": [ - { - "source": "rKBYGQuYefae", - "target": "pluginOutput", - "sourceHandle": "rKBYGQuYefae-source-right", - "targetHandle": "pluginOutput-target-left" - }, - { - "source": "pluginInput", - "target": "a5qdMS7ECNYE", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "a5qdMS7ECNYE-target-left" - }, - { - "source": "a5qdMS7ECNYE", - "target": "rKBYGQuYefae", - "sourceHandle": "a5qdMS7ECNYE-source-right", - "targetHandle": "rKBYGQuYefae-target-left" - } - ], - "chatConfig": { - "welcomeText": "", - "variables": [], - "questionGuide": false, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "", - "autoExecute": { - "open": false, - "defaultPrompt": "" - }, - "_id": "6710a5619c45325525326719" - } - } -} diff --git a/packages/plugins/src/Doc2X/PDF2text/index.ts b/packages/plugins/src/Doc2X/PDF2text/index.ts deleted file mode 100644 index 9e875da74..000000000 --- a/packages/plugins/src/Doc2X/PDF2text/index.ts +++ /dev/null @@ -1,256 +0,0 @@ -import { delay } from '@fastgpt/global/common/system/utils'; -import axios from 'axios'; -import { getErrText } from '@fastgpt/global/common/error/utils'; - -type Props = { - apikey: string; - HTMLtable: boolean; - files: string[]; -}; - -// Response type same as HTTP outputs -type Response = Promise<{ - result: string; - success: boolean; - error?: Record; -}>; - -function processContent(content: string, HTMLtable: boolean): string { - if (HTMLtable) { - return content; - } - return content.replace(/[\s\S]*?<\/table>/g, (htmlTable) => { - try { - // Clean up whitespace and newlines - const cleanHtml = htmlTable.replace(/\n\s*/g, ''); - const rows = cleanHtml.match(/(.*?)<\/tr>/g); - if (!rows) return htmlTable; - - // Parse table data - let tableData: string[][] = []; - let maxColumns = 0; - - // Try to convert to markdown table - try { - rows.forEach((row, rowIndex) => { - if (!tableData[rowIndex]) { - tableData[rowIndex] = []; - } - let colIndex = 0; - const cells = row.match(/(.*?)<\/td>/g) || []; - - cells.forEach((cell) => { - while (tableData[rowIndex][colIndex]) { - colIndex++; - } - const colspan = parseInt(cell.match(/colspan="(\d+)"/)?.[1] || '1'); - const rowspan = parseInt(cell.match(/rowspan="(\d+)"/)?.[1] || '1'); - const content = cell.replace(/|<\/td>/g, '').trim(); - - for (let i = 0; i < rowspan; i++) { - for (let j = 0; j < colspan; j++) { - if (!tableData[rowIndex + i]) { - tableData[rowIndex + i] = []; - } - tableData[rowIndex + i][colIndex + j] = i === 0 && j === 0 ? content : '^^'; - } - } - colIndex += colspan; - maxColumns = Math.max(maxColumns, colIndex); - }); - - for (let i = 0; i < maxColumns; i++) { - if (!tableData[rowIndex][i]) { - tableData[rowIndex][i] = ' '; - } - } - }); - const chunks: string[] = []; - - const headerCells = tableData[0] - .slice(0, maxColumns) - .map((cell) => (cell === '^^' ? ' ' : cell || ' ')); - const headerRow = '| ' + headerCells.join(' | ') + ' |'; - chunks.push(headerRow); - - const separator = '| ' + Array(headerCells.length).fill('---').join(' | ') + ' |'; - chunks.push(separator); - - tableData.slice(1).forEach((row) => { - const paddedRow = row - .slice(0, maxColumns) - .map((cell) => (cell === '^^' ? ' ' : cell || ' ')); - while (paddedRow.length < maxColumns) { - paddedRow.push(' '); - } - chunks.push('| ' + paddedRow.join(' | ') + ' |'); - }); - - return chunks.join('\n'); - } catch (error) { - return htmlTable; - } - } catch (error) { - return htmlTable; - } - }); -} - -const main = async ({ apikey, files, HTMLtable }: Props): Response => { - // Check the apikey - if (!apikey) { - return Promise.reject(`API key is required`); - } - const successResult = []; - const failedResult = []; - - const axiosInstance = axios.create({ - timeout: 30000 // 30 seconds timeout - }); - - //Process each file one by one - for await (const url of files) { - try { - //Fetch the pdf and check its content type - const PDFResponse = await axios - .get(url, { - responseType: 'arraybuffer', - proxy: false, - timeout: 20000 - }) - .catch((error) => { - throw new Error(`[Fetch PDF Error] Failed to fetch PDF: ${getErrText(error)}`); - }); - - if (PDFResponse.status !== 200) { - throw new Error( - `[Fetch PDF Error] Failed with status ${PDFResponse.status}: ${PDFResponse.data}` - ); - } - - const contentType = PDFResponse.headers['content-type']; - const file_name = url.match(/read\/([^?]+)/)?.[1] || 'unknown.pdf'; - if (!contentType || !contentType.startsWith('application/pdf')) { - throw new Error(`The provided file does not point to a PDF: ${contentType}`); - } - - const blob = new Blob([PDFResponse.data], { type: 'application/pdf' }); - // Get pre-upload URL first - const preupload_response = await axiosInstance - .post('https://v2.doc2x.noedgeai.com/api/v2/parse/preupload', null, { - headers: { - Authorization: `Bearer ${apikey}` - } - }) - .catch((error) => { - throw new Error(`[Pre-upload Error] Failed to get pre-upload URL: ${getErrText(error)}`); - }); - - if (preupload_response.status !== 200) { - throw new Error(`Failed to get pre-upload URL: ${preupload_response.data}`); - } - - const preupload_data = preupload_response.data; - if (preupload_data.code !== 'success') { - throw new Error(`Failed to get pre-upload URL: ${JSON.stringify(preupload_data)}`); - } - - const upload_url = preupload_data.data.url; - const uid = preupload_data.data.uid; - // Upload file to pre-signed URL with binary stream - - const response = await axiosInstance - .put(upload_url, blob, { - headers: { - 'Content-Type': 'application/pdf' - } - }) - .catch((error) => { - throw new Error(`[Upload Error] Failed to upload file: ${getErrText(error)}`); - }); - - if (response.status !== 200) { - throw new Error(`Upload failed with status ${response.status}: ${response.statusText}`); - } - - // Get the result by uid - - // Wait for the result - const checkResult = async (retry = 20) => { - if (retry <= 0) - return Promise.reject( - `File:${file_name}\n\n[Parse Timeout Error] Failed to get result (uid: ${uid}): Process timeout\n` - ); - - try { - const result_response = await axiosInstance - .get(`https://v2.doc2x.noedgeai.com/api/v2/parse/status?uid=${uid}`, { - headers: { - Authorization: `Bearer ${apikey}` - } - }) - .catch((error) => { - throw new Error( - `[Parse Status Error] Failed to get parse status: ${getErrText(error)}` - ); - }); - - const result_data = result_response.data; - if (!['ok', 'success'].includes(result_data.code)) { - return Promise.reject( - `File:${file_name}\n\nFailed to get result (uid: ${uid}): ${JSON.stringify(result_data)}\n` - ); - } - - if (['ready', 'processing'].includes(result_data.data.status)) { - await delay(4000); - return checkResult(retry - 1); - } - - if (result_data.data.status === 'success') { - const result = processContent( - await Promise.all( - result_data.data.result.pages.map((page: { md: any }) => page.md) - ).then((pages) => pages.join('\n')), - HTMLtable - ) - // Do some post-processing - .replace(/\\[\(\)]/g, '$') - .replace(/\\[\[\]]/g, '$$') - .replace(/]*)?(?:\s*\/>|>)/g, '![img]($1)') - .replace(//g, '') - .replace(//g, '') - .replace(/\$(.+?)\s+\\tag\{(.+?)\}\$/g, '$$$1 \\qquad \\qquad ($2)$$') - .replace(/\\text\{([^}]*?)(\b\w+)_(\w+\b)([^}]*?)\}/g, '\\text{$1$2\\_$3$4}'); - - return `File:${file_name}\n\n${result}\n`; - } - return checkResult(retry - 1); - } catch (error) { - if (retry > 1) { - await delay(100); - return checkResult(retry - 1); - } - throw error; - } - }; - - const result = await checkResult(); - successResult.push(result); - } catch (error) { - failedResult.push( - `File:${url} \n\nFailed to fetch file from URL: ${getErrText(error)}\n` - ); - } - } - - return { - result: successResult.join('\n******\n'), - error: { - message: failedResult.join('\n******\n') - }, - success: failedResult.length === 0 - }; -}; - -export default main; diff --git a/packages/plugins/src/Doc2X/PDF2text/template.json b/packages/plugins/src/Doc2X/PDF2text/template.json deleted file mode 100644 index fd7eee77a..000000000 --- a/packages/plugins/src/Doc2X/PDF2text/template.json +++ /dev/null @@ -1,462 +0,0 @@ -{ - "author": "Menghuan1918", - "name": "PDF识别", - "avatar": "plugins/doc2x", - "intro": "将PDF文件发送至Doc2X进行解析,返回结构化的LaTeX公式的文本(markdown),支持传入String类型的URL或者流程输出中的文件链接变量", - "courseUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview", - "showStatus": true, - "weight": 10, - "isTool": true, - "templateType": "tools", - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "自定义插件输入", - "intro": "可以配置插件需要哪些输入,利用这些输入来运行插件", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": -137.96875104510553, - "y": -90.9968973555371 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "apikey", - "label": "apikey", - "description": "Doc2X的API密匙,可以从Doc2X开放平台获得", - "required": true, - "defaultValue": "", - "list": [] - }, - { - "renderTypeList": ["fileSelect"], - "selectedTypeIndex": 0, - "valueType": "arrayString", - "canEdit": true, - "key": "files", - "label": "files", - "description": "需要处理的PDF地址", - "required": true, - "list": [], - "canSelectFile": true, - "canSelectImg": false, - "maxFiles": 14, - "defaultValue": "" - }, - { - "renderTypeList": ["switch", "reference"], - "selectedTypeIndex": 0, - "valueType": "boolean", - "canEdit": true, - "key": "HTMLtable", - "label": "HTMLtable", - "description": "是否以HTML格式输出表格。如果需要精确地输出表格,请打开此开关以使用HTML格式。关闭后,表格将转换为Markdown形式输出,但这可能会损失一些表格特性,如合并单元格。", - "defaultValue": false, - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true - } - ], - "outputs": [ - { - "id": "apikey", - "valueType": "string", - "key": "apikey", - "label": "apikey", - "type": "hidden" - }, - { - "id": "url", - "valueType": "arrayString", - "key": "files", - "label": "files", - "type": "hidden" - }, - { - "id": "htmltable", - "valueType": "boolean", - "key": "HTMLtable", - "label": "HTMLtable", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "自定义插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1505.494975310334, - "y": -4.14668564643415 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "result", - "label": "result", - "description": "处理结果,由文件名以及文档内容组成,多个文件之间由横线分隔开", - "value": ["zHG5jJBkXmjB", "xWQuEf50F3mr"] - }, - { - "renderTypeList": ["reference"], - "valueType": "object", - "canEdit": true, - "key": "error", - "label": "error", - "description": "", - "value": ["zHG5jJBkXmjB", "httpRawResponse"], - "isToolOutput": true - }, - { - "renderTypeList": ["reference"], - "valueType": "boolean", - "canEdit": true, - "key": "success", - "label": "success", - "description": "是否全部文件都处理成功,如有没有处理成功的文件,失败原因将会输出在failreason中", - "value": ["zHG5jJBkXmjB", "m6CJJj7GFud5"], - "isToolOutput": false - } - ], - "outputs": [] - }, - { - "nodeId": "zHG5jJBkXmjB", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 619.0661933308237, - "y": -472.91377894611503 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 300, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "Doc2X/PDF2text", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"apikey\": \"{{apikey}}\",\n \"HTMLtable\": {{HTMLtable}},\n \"files\": {{files}}\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "apikey", - "label": "apikey", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "apikey"] - }, - { - "renderTypeList": ["reference"], - "valueType": "arrayString", - "canEdit": true, - "key": "files", - "label": "files", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": [["pluginInput", "url"]] - }, - { - "renderTypeList": ["reference"], - "valueType": "boolean", - "canEdit": true, - "key": "HTMLtable", - "label": "HTMLtable", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "htmltable"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "id": "xWQuEf50F3mr", - "valueType": "string", - "type": "dynamic", - "key": "result", - "label": "result" - }, - { - "id": "m6CJJj7GFud5", - "valueType": "boolean", - "type": "dynamic", - "key": "success", - "label": "success" - } - ] - } - ], - "edges": [ - { - "source": "zHG5jJBkXmjB", - "target": "pluginOutput", - "sourceHandle": "zHG5jJBkXmjB-source-right", - "targetHandle": "pluginOutput-target-left" - }, - { - "source": "pluginInput", - "target": "zHG5jJBkXmjB", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "zHG5jJBkXmjB-target-left" - } - ], - "chatConfig": { - "questionGuide": { - "open": false - }, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "", - "variables": [], - "welcomeText": "" - } - } -} diff --git a/packages/plugins/src/Doc2X/template.json b/packages/plugins/src/Doc2X/template.json deleted file mode 100644 index 598cc0f6b..000000000 --- a/packages/plugins/src/Doc2X/template.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "author": "Menghuan1918", - "name": "Doc2X服务", - "avatar": "plugins/doc2x", - "intro": "将传入的图片或PDF文件发送至Doc2X进行解析,返回带LaTeX公式的markdown格式的文本。", - "showStatus": true, - "weight": 10, - - "isTool": true, - "templateType": "tools", - - "workflow": { - "nodes": [], - "edges": [] - } -} diff --git a/packages/plugins/src/WeWorkWebhook/template.json b/packages/plugins/src/WeWorkWebhook/template.json deleted file mode 100644 index 516052203..000000000 --- a/packages/plugins/src/WeWorkWebhook/template.json +++ /dev/null @@ -1,385 +0,0 @@ -{ - "author": "", - "name": "企业微信 webhook", - "avatar": "plugins/qiwei", - "intro": "向企业微信机器人发起 webhook 请求。只能内部群使用。", - "courseUrl": "https://developer.work.weixin.qq.com/document/path/91770", - "showStatus": false, - "weight": 10, - "isTool": true, - "templateType": "communication", - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "自定义配置外部输入,使用插件时,仅暴露自定义配置的输入", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 537.6357458754286, - "y": -201.26482361861054 - }, - "version": "481", - "inputs": [ - { - "inputType": "input", - "valueType": "string", - "key": "企微机器人地址", - "label": "企微机器人地址", - "description": "", - "isToolInput": false, - "defaultValue": "", - "editField": { - "key": true - }, - "dynamicParamDefaultValue": { - "inputType": "reference", - "valueType": "string", - "required": true - }, - "renderTypeList": ["input"], - "required": true, - "canEdit": true, - "value": "" - }, - { - "key": "发送的消息", - "valueType": "string", - "label": "发送的消息", - "renderTypeList": ["input", "reference"], - "required": true, - "description": "发送的消息", - "canEdit": true, - "value": "", - "editField": { - "key": true - }, - "dynamicParamDefaultValue": { - "inputType": "reference", - "valueType": "string", - "required": true - }, - "list": [], - "defaultValue": "", - "toolDescription": "发送的消息" - } - ], - "outputs": [ - { - "id": "mv52BrPVE6bm", - "key": "企微机器人地址", - "valueType": "string", - "label": "企微机器人地址", - "type": "static" - }, - { - "id": "p0m68Dv5KaIp", - "key": "发送的消息", - "valueType": "string", - "label": "发送的消息", - "type": "static" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1776.027569211593, - "y": -58.264823618610535 - }, - "version": "481", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "rKBYGQuYefae", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1069.7228495148624, - "y": -392.26482361861054 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "{{url}}", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\r\n \"msgtype\": \"text\",\r\n \"text\": {\r\n \"content\": \"{{text}}\"\r\n }\r\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "text", - "valueType": "string", - "label": "text", - "renderTypeList": ["reference"], - "description": "", - "canEdit": true, - "editField": { - "key": true, - "valueType": true - }, - "value": ["pluginInput", "p0m68Dv5KaIp"], - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "url", - "valueType": "string", - "label": "url", - "renderTypeList": ["reference"], - "description": "", - "canEdit": true, - "editField": { - "key": true, - "valueType": true - }, - "value": ["pluginInput", "mv52BrPVE6bm"], - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "editField": { - "key": true, - "valueType": true - } - } - ] - }, - { - "nodeId": "q3ccNXiZIHoS", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": 99.73879703925843, - "y": -201.26482361861054 - }, - "version": "4811", - "inputs": [], - "outputs": [] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "rKBYGQuYefae", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "rKBYGQuYefae-target-left" - }, - { - "source": "rKBYGQuYefae", - "target": "pluginOutput", - "sourceHandle": "rKBYGQuYefae-source-right", - "targetHandle": "pluginOutput-target-left" - } - ], - "chatConfig": { - "welcomeText": "", - "variables": [], - "questionGuide": false, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "", - "autoExecute": { - "open": false, - "defaultPrompt": "" - }, - "_id": "6710a5619c45325525326719" - } - } -} diff --git a/packages/plugins/src/bing/template.json b/packages/plugins/src/bing/template.json deleted file mode 100644 index 12f51f9b1..000000000 --- a/packages/plugins/src/bing/template.json +++ /dev/null @@ -1,511 +0,0 @@ -{ - "author": "", - "name": "Bing搜索", - "avatar": "core/workflow/template/bing", - "intro": "在Bing中搜索。", - "showStatus": true, - "weight": 10, - "courseUrl": "https://fael3z0zfze.feishu.cn/wiki/LsKAwOmtniA4vkkC259cmfxXnAc?fromScene=spaceOverview", - "isTool": true, - "templateType": "search", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "workflow:template.plugin_start", - "intro": "workflow:intro_plugin_input", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 636.3048409085379, - "y": -238.61714728578016 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "key", - "label": "key", - "description": "bing搜索key", - "defaultValue": "", - "required": true - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "description": "查询字段值", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "required": true, - "toolDescription": "查询字段值" - } - ], - "outputs": [ - { - "id": "key", - "valueType": "string", - "key": "key", - "label": "key", - "type": "hidden" - }, - { - "id": "query", - "valueType": "string", - "key": "query", - "label": "query", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "common:core.module.template.self_output", - "intro": "workflow:intro_custom_plugin_output", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 2764.1105686698083, - "y": -30.617147285780163 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "object", - "canEdit": true, - "key": "result", - "label": "result", - "isToolOutput": true, - "description": "", - "value": ["pZTkvleFSZXo", "system_rawResponse"] - } - ], - "outputs": [] - }, - { - "nodeId": "pluginConfig", - "name": "common:core.module.template.system_config", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": 184.66337662472682, - "y": -216.05298493910115 - }, - "version": "4811", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "nyA6oA8mF1iW", - "name": "HTTP 请求", - "intro": "调用谷歌搜索,查询相关内容", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1335.0647252518884, - "y": -455.9043948565971 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "GET", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "https://api.bing.microsoft.com/v7.0/search", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [ - { - "key": "Ocp-Apim-Subscription-Key", - "type": "string", - "value": "{{$pluginInput.key$}}" - } - ], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [ - { - "key": "q", - "type": "string", - "value": "{{query}}" - } - ], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "valueType": "string", - "renderTypeList": ["reference"], - "key": "query", - "label": "query", - "toolDescription": "谷歌搜索检索词", - "required": true, - "canEdit": true, - "editField": { - "key": true, - "description": true - }, - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "value": ["pluginInput", "query"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "editField": { - "key": true, - "valueType": true - } - }, - { - "id": "M5YmxaYe8em1", - "type": "dynamic", - "key": "prompt", - "valueType": "string", - "label": "prompt" - } - ] - }, - { - "nodeId": "pZTkvleFSZXo", - "name": "代码运行", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 2153.5325687235554, - "y": -188.04429852303304 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "editField": { - "key": true, - "valueType": true - }, - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({data}){\n const result = data.webPages.value.map((item) => ({\n title: item.name,\n link: item.url,\n snippet: item.snippet\n }))\n return JSON.stringify(result) \n}", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "data", - "valueType": "object", - "label": "data", - "renderTypeList": ["reference"], - "description": "", - "canEdit": true, - "editField": { - "key": true, - "valueType": true - }, - "value": ["nyA6oA8mF1iW", "httpRawResponse"], - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "editField": { - "key": true, - "valueType": true - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "prompt", - "valueType": "string", - "label": "prompt" - } - ] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "nyA6oA8mF1iW", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "nyA6oA8mF1iW-target-left" - }, - { - "source": "nyA6oA8mF1iW", - "target": "pZTkvleFSZXo", - "sourceHandle": "nyA6oA8mF1iW-source-right", - "targetHandle": "pZTkvleFSZXo-target-left" - }, - { - "source": "pZTkvleFSZXo", - "target": "pluginOutput", - "sourceHandle": "pZTkvleFSZXo-source-right", - "targetHandle": "pluginOutput-target-left" - } - ], - "chatConfig": { - "welcomeText": "", - "variables": [], - "questionGuide": { - "open": false - }, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "", - "_id": "6709e90cd9873479ee78fe71" - } - } -} diff --git a/packages/plugins/src/bocha/template.json b/packages/plugins/src/bocha/template.json deleted file mode 100644 index 614bec8bc..000000000 --- a/packages/plugins/src/bocha/template.json +++ /dev/null @@ -1,489 +0,0 @@ -{ - "author": "", - "name": "博查搜索", - "avatar": "core/workflow/template/bocha", - "intro": "使用博查AI搜索引擎进行网络搜索。", - "showStatus": true, - "weight": 10, - "courseUrl": "", - "isTool": true, - "templateType": "search", - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "workflow:template.plugin_start", - "intro": "workflow:intro_plugin_input", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 636.3048409085379, - "y": -238.61714728578016 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "apiKey", - "label": "apiKey", - "description": "博查API密钥", - "defaultValue": "", - "required": true - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "description": "搜索查询词", - "defaultValue": "", - "required": true, - "toolDescription": "搜索查询词" - }, - { - "renderTypeList": ["select", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "freshness", - "label": "freshness", - "description": "搜索指定时间范围内的网页。", - "defaultValue": "noLimit", - "required": false, - "toolDescription": "搜索指定时间范围内的网页。", - "list": [ - { - "label": "noLimit", - "value": "noLimit" - }, - { - "label": "oneDay", - "value": "oneDay" - }, - { - "label": "oneWeek", - "value": "oneWeek" - }, - { - "label": "oneMonth", - "value": "oneMonth" - }, - { - "label": "oneYear", - "value": "oneYear" - } - ] - }, - { - "renderTypeList": ["switch", "reference"], - "selectedTypeIndex": 0, - "valueType": "boolean", - "canEdit": true, - "key": "summary", - "label": "summary", - "description": "是否显示文本摘要。", - "defaultValue": true, - "required": false, - "list": [] - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "include", - "label": "include", - "description": "指定搜索的site范围。多个域名使用|或,分隔,最多20个。例如:qq.com|m.163.com", - "defaultValue": "", - "required": false, - "list": [] - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "exclude", - "label": "exclude", - "description": "排除搜索的网站范围。多个域名使用|或,分隔,最多20个。例如:qq.com|m.163.com", - "defaultValue": "", - "required": false, - "list": [] - }, - { - "renderTypeList": ["numberInput", "reference"], - "selectedTypeIndex": 0, - "valueType": "number", - "canEdit": true, - "key": "count", - "label": "count", - "description": "返回结果的条数。可填范围:1-50,默认为10", - "defaultValue": 10, - "required": false, - "min": 1, - "max": 50, - "list": [] - } - ], - "outputs": [ - { - "id": "apiKey", - "valueType": "string", - "key": "apiKey", - "label": "apiKey", - "type": "hidden" - }, - { - "id": "query", - "valueType": "string", - "key": "query", - "label": "query", - "type": "hidden" - }, - { - "id": "freshness", - "valueType": "string", - "key": "freshness", - "label": "freshness", - "type": "hidden" - }, - { - "id": "summary", - "valueType": "boolean", - "key": "summary", - "label": "summary", - "type": "hidden" - }, - { - "id": "include", - "valueType": "string", - "key": "include", - "label": "include", - "type": "hidden" - }, - { - "id": "exclude", - "valueType": "string", - "key": "exclude", - "label": "exclude", - "type": "hidden" - }, - { - "id": "count", - "valueType": "number", - "key": "count", - "label": "count", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "common:core.module.template.self_output", - "intro": "workflow:intro_custom_plugin_output", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 2289.548741109713, - "y": -113.61714728578016 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "arrayObject", - "canEdit": true, - "key": "result", - "label": "result", - "isToolOutput": true, - "description": "", - "value": [["cixTtgyy4gK43lPD", "hb4MQP8oGxPx1f9G"]], - "required": true - }, - { - "renderTypeList": ["reference"], - "valueType": "object", - "canEdit": true, - "key": "error", - "label": "error", - "isToolOutput": true, - "description": "", - "required": true, - "value": ["cixTtgyy4gK43lPD", "error"] - } - ], - "outputs": [] - }, - { - "nodeId": "pluginConfig", - "name": "common:core.module.template.system_config", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": 184.66337662472682, - "y": -216.05298493910115 - }, - "version": "4811", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "cixTtgyy4gK43lPD", - "name": "HTTP 请求#2", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1336.2141952438083, - "y": -513.6171472857802 - }, - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "接收前方节点的输出值作为变量,这些变量可以被 HTTP 请求参数使用。", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectDataset", - "selectApp" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "新的 HTTP 请求地址。如果出现两个“请求地址”,可以删除该模块重新加入,会拉取最新的模块配置。", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "https://api.bochaai.com/v1/web-search", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [ - { - "key": "Authorization", - "type": "string", - "value": "Bearer {{$pluginInput.apiKey$}}" - } - ], - "label": "", - "description": "自定义请求头,请严格填入 JSON 字符串。\n1. 确保最后一个属性没有逗号\n2. 确保 key 包含双引号\n例如:{\"Authorization\":\"Bearer xxx\"}", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"query\": \"{{$pluginInput.query$}}\",\n \"freshness\": \"{{$pluginInput.freshness$}}\",\n \"summary\": {{$pluginInput.summary$}},\n \"include\": \"{{$pluginInput.include$}}\",\n \"exclude\": \"{{$pluginInput.exclude$}}\",\n \"count\": {{$pluginInput.count$}}\n}", - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false - } - ], - "outputs": [ - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "输出字段提取", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectDataset", - "selectApp" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "可以通过 JSONPath 语法来提取响应值中的指定字段", - "valueDesc": "" - }, - { - "id": "error", - "key": "error", - "label": "请求错误", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static", - "valueDesc": "" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "原始响应", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static", - "valueDesc": "" - }, - { - "id": "hb4MQP8oGxPx1f9G", - "valueType": "arrayObject", - "type": "dynamic", - "key": "$.data.webPages.value", - "label": "$.data.webPages.value" - } - ] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "cixTtgyy4gK43lPD", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "cixTtgyy4gK43lPD-target-left" - }, - { - "source": "cixTtgyy4gK43lPD", - "target": "pluginOutput", - "sourceHandle": "cixTtgyy4gK43lPD-source-right", - "targetHandle": "pluginOutput-target-left" - } - ], - "chatConfig": { - "variables": [], - "_id": "67bd78aeebcd3c6700e82e5e", - "questionGuide": { - "open": false, - "model": "gpt-4o-mini", - "customPrompt": "" - }, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "", - "autoExecute": { - "open": false, - "defaultPrompt": "" - }, - "welcomeText": "" - } - }, - "chatConfig": {} -} diff --git a/packages/plugins/src/databaseConnection/index.ts b/packages/plugins/src/databaseConnection/index.ts deleted file mode 100644 index 055a2f2de..000000000 --- a/packages/plugins/src/databaseConnection/index.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Client as PgClient } from 'pg'; // PostgreSQL 客户端 -import mysql from 'mysql2/promise'; // MySQL 客户端 -import mssql from 'mssql'; // SQL Server 客户端 - -type Props = { - databaseType: string; - host: string; - port: string; - databaseName: string; - user: string; - password: string; - sql: string; -}; - -type Response = Promise<{ - result: any; // 根据你的 SQL 查询结果类型调整 -}>; - -const main = async ({ - databaseType, - host, - port, - databaseName, - user, - password, - sql -}: Props): Response => { - let result; - - try { - if (databaseType === 'PostgreSQL') { - const client = new PgClient({ - host, - port: parseInt(port, 10), - database: databaseName, - user, - password, - connectionTimeoutMillis: 30000 - }); - - await client.connect(); - const res = await client.query(sql); - result = res.rows; - await client.end(); - } else if (databaseType === 'MySQL') { - const connection = await mysql.createConnection({ - host, - port: parseInt(port, 10), - database: databaseName, - user, - password, - connectTimeout: 30000 - }); - - const [rows] = await connection.execute(sql); - result = rows; - await connection.end(); - } else if (databaseType === 'Microsoft SQL Server') { - const pool = await mssql.connect({ - server: host, - port: parseInt(port, 10), - database: databaseName, - user, - password, - options: { - trustServerCertificate: true - } - }); - - result = await pool.query(sql); - await pool.close(); - } - return { - result - }; - } catch (error: unknown) { - // 使用类型断言来处理错误 - if (error instanceof Error) { - console.error('Database query error:', error.message); - return Promise.reject(error.message); - } - console.error('Database query error:', error); - return Promise.reject('An unknown error occurred'); - } -}; - -export default main; diff --git a/packages/plugins/src/databaseConnection/template.json b/packages/plugins/src/databaseConnection/template.json deleted file mode 100644 index 39691d7f8..000000000 --- a/packages/plugins/src/databaseConnection/template.json +++ /dev/null @@ -1,692 +0,0 @@ -{ - "author": "silencezhang", - "name": "数据库连接", - "avatar": "core/workflow/template/datasource", - "intro": "可连接常用数据库,并执行sql", - "showStatus": true, - "weight": 10, - - "isTool": true, - "templateType": "tools", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "workflow:template.plugin_start", - "intro": "workflow:intro_plugin_input", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 334.24111198705634, - "y": -260.8285440670886 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["select", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "databaseType", - "label": "databaseType", - "description": "数据库的类型", - "defaultValue": "", - "list": [ - { - "label": "MySQL", - "value": "MySQL" - }, - { - "label": "PostgreSQL", - "value": "PostgreSQL" - }, - { - "label": "Microsoft SQL Server", - "value": "Microsoft SQL Server" - } - ], - "required": true - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "host", - "label": "host", - "description": "数据库连接host", - "defaultValue": "", - "required": true, - "list": [ - { - "label": "", - "value": "" - } - ] - }, - { - "renderTypeList": ["numberInput", "reference"], - "selectedTypeIndex": 0, - "valueType": "number", - "canEdit": true, - "key": "port", - "label": "port", - "description": "数据库连接端口号", - "defaultValue": "", - "required": true, - "list": [ - { - "label": "", - "value": "" - } - ] - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "databaseName", - "label": "databaseName", - "description": "数据库名称", - "defaultValue": "", - "required": true, - "list": [ - { - "label": "", - "value": "" - } - ] - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "password", - "label": "password", - "description": "数据库密码", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "required": true - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "user", - "label": "user", - "description": "数据库账号", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "required": true - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "sql", - "label": "sql", - "description": "sql语句,可以传入sql语句直接执行", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "required": true, - "toolDescription": "sql语句,可以传入sql语句直接执行" - } - ], - "outputs": [ - { - "id": "databaseType", - "valueType": "string", - "key": "databaseType", - "label": "databaseType", - "type": "hidden" - }, - { - "id": "host", - "valueType": "string", - "key": "host", - "label": "host", - "type": "hidden" - }, - { - "id": "port", - "valueType": "number", - "key": "port", - "label": "port", - "type": "hidden" - }, - { - "id": "dataBaseName", - "valueType": "string", - "key": "databaseName", - "label": "databaseName", - "type": "hidden" - }, - { - "id": "dataBasePwd", - "valueType": "string", - "key": "password", - "label": "password", - "type": "hidden" - }, - { - "id": "user", - "valueType": "string", - "key": "user", - "label": "user", - "type": "hidden" - }, - { - "id": "sql", - "valueType": "string", - "key": "sql", - "label": "sql", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "common:core.module.template.self_output", - "intro": "workflow:intro_custom_plugin_output", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1788.4723692358186, - "y": -153.2313912808486 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "result", - "label": "result", - "isToolOutput": true, - "description": "数据库连接结果", - "value": ["zBeXy7YZEiXe", "httpRawResponse"] - } - ], - "outputs": [] - }, - { - "nodeId": "pluginConfig", - "name": "common:core.module.template.system_config", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": -133.25818142678844, - "y": -200.98784849888733 - }, - "version": "4811", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "zBeXy7YZEiXe", - "name": "数据库连接", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1035.92763304296, - "y": -498.57137296107504 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "databaseConnection", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\r\n \"databaseType\":\"{{databaseType-H}}\",\r\n \"host\":\"{{host-H}}\",\r\n \"port\":\"{{port-H}}\",\r\n \"databaseName\":\"{{databaseName-H}}\",\r\n \"user\":\"{{databaseUser-H}}\",\r\n \"password\":\"{{databasePwd-H}}\",\r\n \"sql\":\"{{sql-H}}\"\r\n}", - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "databaseType-H", - "label": "databaseType-H", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "databaseType"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "host-H", - "label": "host-H", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "host"] - }, - { - "renderTypeList": ["reference"], - "valueType": "number", - "canEdit": true, - "key": "port-H", - "label": "port-H", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "port"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "databaseName-H", - "label": "databaseName-H", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "dataBaseName"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "databasePwd-H", - "label": "databasePwd-H", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "dataBasePwd"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "databaseUser-H", - "label": "databaseUser-H", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "user"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "sql-H", - "label": "sql-H", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "sql"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "valueDesc": "", - "description": "" - } - ] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "zBeXy7YZEiXe", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "zBeXy7YZEiXe-target-left" - }, - { - "source": "zBeXy7YZEiXe", - "target": "pluginOutput", - "sourceHandle": "zBeXy7YZEiXe-source-right", - "targetHandle": "pluginOutput-target-left" - } - ], - "chatConfig": { - "welcomeText": "", - "variables": [], - "questionGuide": { - "open": false - }, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "数据源配置,支持主流数据库配置", - "_id": "670a23b31957c5b9899b4a4d" - } - } -} diff --git a/packages/plugins/src/delay/index.ts b/packages/plugins/src/delay/index.ts deleted file mode 100644 index 2e89a837d..000000000 --- a/packages/plugins/src/delay/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { delay } from '@fastgpt/global/common/system/utils'; - -type Props = { - ms: number; -}; -type Response = Promise; - -const main = async ({ ms }: Props): Response => { - if (typeof ms !== 'number' || ms <= 0 || ms > 300000) { - return ms; - } - - await delay(ms); - - return ms; -}; - -export default main; diff --git a/packages/plugins/src/delay/template.json b/packages/plugins/src/delay/template.json deleted file mode 100644 index f3f5e385f..000000000 --- a/packages/plugins/src/delay/template.json +++ /dev/null @@ -1,317 +0,0 @@ -{ - "author": "collin", - "name": "流程等待", - "avatar": "core/workflow/template/sleep", - "intro": "让工作流等待指定时间后运行", - "showStatus": true, - "weight": 1, - - "isTool": true, - "templateType": "tools", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "workflow:template.plugin_start", - "intro": "workflow:intro_plugin_input", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 627.6352390819724, - "y": -165.05298493910118 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["numberInput", "reference"], - "selectedTypeIndex": 0, - "valueType": "number", - "canEdit": true, - "key": "延迟时长", - "label": "延迟时长", - "description": "需要暂停的时间,单位毫秒", - "defaultValue": 1000, - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true, - "toolDescription": "需要暂停的时间,单位毫秒", - "max": 300000, - "min": 1 - } - ], - "outputs": [ - { - "id": "ms", - "valueType": "number", - "key": "延迟时长", - "label": "延迟时长", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "common:core.module.template.self_output", - "intro": "workflow:intro_custom_plugin_output", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1921.839722563351, - "y": -160.05298493910115 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "any", - "canEdit": true, - "key": "result", - "label": "result", - "isToolOutput": true, - "description": "", - "required": true, - "value": ["zCJC6zw7c14i", "httpRawResponse"] - } - ], - "outputs": [] - }, - { - "nodeId": "pluginConfig", - "name": "common:core.module.template.system_config", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": 184.66337662472682, - "y": -216.05298493910115 - }, - "version": "4811", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "zCJC6zw7c14i", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1154.4041630064592, - "y": -455.0529849391012 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "delay", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n\"ms\": {{$pluginInput.ms$}}\n}", - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "输出字段提取", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "可以通过 JSONPath 语法来提取响应值中的指定字段", - "valueDesc": "" - } - ] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "zCJC6zw7c14i", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "zCJC6zw7c14i-target-left" - }, - { - "source": "zCJC6zw7c14i", - "target": "pluginOutput", - "sourceHandle": "zCJC6zw7c14i-source-right", - "targetHandle": "pluginOutput-target-left" - } - ], - "chatConfig": { - "welcomeText": "" - } - } -} diff --git a/packages/plugins/src/drawing/baseChart/index.ts b/packages/plugins/src/drawing/baseChart/index.ts deleted file mode 100644 index 5484eea19..000000000 --- a/packages/plugins/src/drawing/baseChart/index.ts +++ /dev/null @@ -1,99 +0,0 @@ -import * as echarts from 'echarts'; -import json5 from 'json5'; -import { type SystemPluginSpecialResponse } from '../../../type.d'; - -type Props = { - title: string; - xAxis: string[]; - yAxis: string[]; - chartType: string; -}; - -type Response = Promise<{ - result: SystemPluginSpecialResponse; -}>; - -type SeriesData = { - name: string; - type: 'bar' | 'line' | 'pie'; // 只允许这三种类型 - data: number[] | { value: number; name: string }[]; // 根据图表类型的数据结构 -}; -type Option = { - backgroundColor: string; - title: { text: string }; - tooltip: {}; - xAxis: { data: string[] }; - yAxis: {}; - series: SeriesData[]; // 使用定义的类型 -}; - -const generateChart = async ( - title: string, - xAxis: string[], - yAxis: string[], - chartType: string -) => { - // @ts-ignore 无法使用dom,如使用jsdom会出现生成图片无法正常展示,有高手可以帮忙解决 - const chart = echarts.init(undefined, undefined, { - renderer: 'svg', // 必须使用 SVG 模式 - ssr: true, // 开启 SSR - width: 400, // 需要指明高和宽 - height: 300 - }); - - const option: Option = { - backgroundColor: '#f5f5f5', - title: { text: title }, - tooltip: {}, - xAxis: { data: xAxis }, - yAxis: {}, - series: [] // 初始化为空数组 - }; - - // 根据 chartType 生成不同的图表 - switch (chartType) { - case '柱状图': - option.series.push({ name: 'Sample', type: 'bar', data: yAxis.map(Number) }); - break; - case '折线图': - option.series.push({ name: 'Sample', type: 'line', data: yAxis.map(Number) }); - break; - case '饼图': - option.series.push({ - name: 'Sample', - type: 'pie', - data: yAxis.map((value, index) => ({ - value: Number(value), - name: xAxis[index] // 使用 xAxis 作为饼图的名称 - })) - }); - break; - default: - console.error('不支持的图表类型:', chartType); - return ''; - } - - chart.setOption(option); - // 生成 Base64 图像 - const base64Image = chart.getDataURL({ - type: 'png', - pixelRatio: 2 // 可以设置更高的像素比以获得更清晰的图像 - }); - const svgContent = decodeURIComponent(base64Image.split(',')[1]); - const base64 = `data:image/svg+xml;base64,${Buffer.from(svgContent).toString('base64')}`; - - return base64; -}; - -const main = async ({ title, xAxis, yAxis, chartType }: Props): Response => { - const base64 = await generateChart(title, xAxis, yAxis, chartType); - return { - result: { - type: 'SYSTEM_PLUGIN_BASE64', - value: base64, - extension: 'svg' - } - }; -}; - -export default main; diff --git a/packages/plugins/src/drawing/baseChart/template.json b/packages/plugins/src/drawing/baseChart/template.json deleted file mode 100644 index 7180c7707..000000000 --- a/packages/plugins/src/drawing/baseChart/template.json +++ /dev/null @@ -1,406 +0,0 @@ -{ - "author": "silencezhang", - "name": "基础图表", - "avatar": "core/workflow/template/baseChart", - "intro": "根据数据生成图表,可根据chartType生成柱状图,折线图,饼图", - "showStatus": true, - "weight": 10, - - "isTool": true, - "templateType": "tools", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "common:core.module.template.self_input", - "intro": "workflow:intro_plugin_input", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 613.7921798611637, - "y": -123.07734867626235 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "title", - "label": "title", - "description": "BI图表的标题", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "required": true, - "toolDescription": "BI图表的标题" - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "xAxis", - "label": "xAxis", - "description": "x轴数据,例如:[\"A\", \"B\", \"C\"]", - "defaultValue": "", - "required": true, - "toolDescription": "x轴数据,例如:[\"A\", \"B\", \"C\"]", - "list": [ - { - "label": "", - "value": "" - } - ] - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "yAxis", - "label": "yAxis", - "description": "y轴数据,例如:[1,2,3]", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "required": true, - "toolDescription": "y轴数据,例如:[1,2,3]" - }, - { - "renderTypeList": ["select", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "chartType", - "label": "chartType", - "description": "图表类型:柱状图,折线图,饼图", - "defaultValue": "", - "required": true, - "list": [ - { - "label": "柱状图", - "value": "柱状图" - }, - { - "label": "折线图", - "value": "折线图" - }, - { - "label": "饼图", - "value": "饼图" - } - ], - "toolDescription": "图表类型:柱状图,折线图,饼图" - } - ], - "outputs": [ - { - "id": "title", - "valueType": "string", - "key": "title", - "label": "title", - "type": "hidden" - }, - { - "id": "xAxis", - "valueType": "string", - "key": "xAxis", - "label": "xAxis", - "type": "hidden" - }, - { - "id": "yAxis", - "valueType": "string", - "key": "yAxis", - "label": "yAxis", - "type": "hidden" - }, - { - "id": "chartType", - "valueType": "string", - "key": "chartType", - "label": "chartType", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "common:core.module.template.self_output", - "intro": "workflow:intro_custom_plugin_output", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 2128.8138851197145, - "y": -63.52186746137181 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "图表 url", - "label": "图表 url", - "description": "可用使用markdown格式展示图片,如:![图片](url)", - "value": ["ws0DFKJnCPhk", "bzaYjKyQFOw2"], - "isToolOutput": true, - "required": true - } - ], - "outputs": [] - }, - { - "nodeId": "ws0DFKJnCPhk", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1264.2009472531117, - "y": -455.0773486762623 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "drawing/baseChart" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\r\n \"title\": \"{{$pluginInput.title$}}\",\r\n \"xAxis\": {{$pluginInput.xAxis$}},\r\n \"yAxis\": {{$pluginInput.yAxis$}},\r\n \"chartType\": \"{{$pluginInput.chartType$}}\"\r\n}", - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "valueDesc": "", - "description": "" - }, - { - "id": "bzaYjKyQFOw2", - "valueType": "string", - "type": "dynamic", - "key": "result", - "label": "result" - } - ] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "ws0DFKJnCPhk", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "ws0DFKJnCPhk-target-left" - }, - { - "source": "ws0DFKJnCPhk", - "target": "pluginOutput", - "sourceHandle": "ws0DFKJnCPhk-source-right", - "targetHandle": "pluginOutput-target-left" - } - ], - "chatConfig": { - "welcomeText": "", - "variables": [], - "questionGuide": { - "open": false - }, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "数据源配置,支持主流数据库配置", - "_id": "670a23b31957c5b9899b4a4d" - } - } -} diff --git a/packages/plugins/src/drawing/template.json b/packages/plugins/src/drawing/template.json deleted file mode 100644 index 4f9c6b432..000000000 --- a/packages/plugins/src/drawing/template.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "author": "silencezhang", - "name": "BI图表功能", - "avatar": "core/workflow/template/BI", - "intro": "BI图表功能,可以生成一些常用的图表,如饼图,柱状图,折线图等", - "showStatus": false, - "weight": 100, - - "isTool": true, - "templateType": "tools", - - "workflow": { - "nodes": [], - "edges": [] - } -} diff --git a/packages/plugins/src/duckduckgo/search/index.ts b/packages/plugins/src/duckduckgo/search/index.ts deleted file mode 100644 index 8fa0ae4d6..000000000 --- a/packages/plugins/src/duckduckgo/search/index.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { search, SafeSearchType } from 'duck-duck-scrape'; -import { delay } from '@fastgpt/global/common/system/utils'; -import { addLog } from '@fastgpt/service/common/system/log'; -import { getErrText } from '@fastgpt/global/common/error/utils'; - -type Props = { - query: string; -}; - -// Response type same as HTTP outputs -type Response = Promise<{ - result: string; -}>; - -const main = async (props: Props, retry = 3): Response => { - const { query } = props; - try { - const searchResults = await search(query, { - safeSearch: SafeSearchType.STRICT, - time: 'y' - }); - - const result = searchResults.results - .map((item) => ({ - title: item.title, - link: item.url, - snippet: item.description - })) - .slice(0, 10); - - return { - result: JSON.stringify(result) - }; - } catch (error) { - console.log(error); - if (retry <= 0) { - addLog.warn('DuckDuckGo error', { error }); - return { - result: getErrText(error, 'Failed to fetch data from DuckDuckGo') - }; - } - - await delay(Math.random() * 5000); - return main(props, retry - 1); - } -}; - -export default main; diff --git a/packages/plugins/src/duckduckgo/search/template.json b/packages/plugins/src/duckduckgo/search/template.json deleted file mode 100644 index 1aaef5bc7..000000000 --- a/packages/plugins/src/duckduckgo/search/template.json +++ /dev/null @@ -1,319 +0,0 @@ -{ - "author": "", - "name": "DuckDuckGo 网络搜索", - "avatar": "core/workflow/template/duckduckgo", - "intro": "使用 DuckDuckGo 进行网络搜索", - "showStatus": true, - "weight": 10, - - "isTool": true, - "templateType": "search", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "可以配置插件需要哪些输入,利用这些输入来运行插件", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 484.02074451450517, - "y": -79.06127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "description": "检索词", - "required": true, - "toolDescription": "检索词" - } - ], - "outputs": [ - { - "id": "query", - "valueType": "string", - "key": "query", - "label": "query", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1759.5180706702588, - "y": -60.56127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "result", - "label": "result", - "description": " 检索结果", - "value": ["hjnVuJAOwyXV", "lEyy5QqyIBrK"] - } - ], - "outputs": [] - }, - { - "nodeId": "hjnVuJAOwyXV", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1054.6774638324207, - "y": -403.06127656499825 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "duckduckgo/search", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"query\": \"{{query}}\"\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "query"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "id": "lEyy5QqyIBrK", - "valueType": "string", - "type": "dynamic", - "key": "result", - "label": "result" - } - ] - }, - { - "nodeId": "f1mRh1D85H2D", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": -28.511358745511643, - "y": -103.56127656499825 - }, - "version": "4811", - "inputs": [], - "outputs": [] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "hjnVuJAOwyXV", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "hjnVuJAOwyXV-target-left" - }, - { - "source": "hjnVuJAOwyXV", - "target": "pluginOutput", - "sourceHandle": "hjnVuJAOwyXV-source-right", - "targetHandle": "pluginOutput-target-left" - } - ] - } -} diff --git a/packages/plugins/src/duckduckgo/searchImg/index.ts b/packages/plugins/src/duckduckgo/searchImg/index.ts deleted file mode 100644 index 6f5c58679..000000000 --- a/packages/plugins/src/duckduckgo/searchImg/index.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { searchImages, SafeSearchType } from 'duck-duck-scrape'; -import { delay } from '@fastgpt/global/common/system/utils'; -import { addLog } from '@fastgpt/service/common/system/log'; -import { getErrText } from '@fastgpt/global/common/error/utils'; - -type Props = { - query: string; -}; - -// Response type same as HTTP outputs -type Response = Promise<{ - result: string; -}>; - -const main = async (props: Props, retry = 3): Response => { - const { query } = props; - - try { - const searchResults = await searchImages(query, { - safeSearch: SafeSearchType.STRICT - }); - - const result = searchResults.results - .map((item) => ({ - title: item.title, - image: item.image - })) - .slice(0, 10); - - return { - result: JSON.stringify(result) - }; - } catch (error) { - if (retry <= 0) { - addLog.warn('DuckDuckGo error', { error }); - return { - result: getErrText(error, 'Failed to fetch data from DuckDuckGo') - }; - } - - await delay(Math.random() * 5000); - return main(props, retry - 1); - } -}; - -export default main; diff --git a/packages/plugins/src/duckduckgo/searchImg/template.json b/packages/plugins/src/duckduckgo/searchImg/template.json deleted file mode 100644 index 84dad380d..000000000 --- a/packages/plugins/src/duckduckgo/searchImg/template.json +++ /dev/null @@ -1,319 +0,0 @@ -{ - "author": "", - "name": "DuckDuckGo 图片搜索", - "avatar": "core/workflow/template/duckduckgo", - "intro": "使用 DuckDuckGo 进行图片搜索", - "showStatus": true, - "weight": 10, - - "isTool": true, - "templateType": "search", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "可以配置插件需要哪些输入,利用这些输入来运行插件", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 422.59478119647315, - "y": -79.06127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "description": "检索词", - "required": true, - "toolDescription": "检索词" - } - ], - "outputs": [ - { - "id": "query", - "valueType": "string", - "key": "query", - "label": "query", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1777.58453046968, - "y": -60.56127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "result", - "label": "result", - "description": " 检索结果", - "value": ["hjnVuJAOwyXV", "lEyy5QqyIBrK"] - } - ], - "outputs": [] - }, - { - "nodeId": "hjnVuJAOwyXV", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1054.6774638324207, - "y": -403.06127656499825 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "duckduckgo/searchImg", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"query\": \"{{query}}\"\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "query"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "id": "lEyy5QqyIBrK", - "valueType": "string", - "type": "dynamic", - "key": "result", - "label": "result" - } - ] - }, - { - "nodeId": "y3A7CnUp4VOH", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": -35.73794266528006, - "y": -103.56127656499825 - }, - "version": "4811", - "inputs": [], - "outputs": [] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "hjnVuJAOwyXV", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "hjnVuJAOwyXV-target-left" - }, - { - "source": "hjnVuJAOwyXV", - "target": "pluginOutput", - "sourceHandle": "hjnVuJAOwyXV-source-right", - "targetHandle": "pluginOutput-target-left" - } - ] - } -} diff --git a/packages/plugins/src/duckduckgo/searchNews/index.ts b/packages/plugins/src/duckduckgo/searchNews/index.ts deleted file mode 100644 index ac0b84b96..000000000 --- a/packages/plugins/src/duckduckgo/searchNews/index.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { searchNews, SafeSearchType } from 'duck-duck-scrape'; -import { delay } from '@fastgpt/global/common/system/utils'; -import { addLog } from '@fastgpt/service/common/system/log'; -import { getErrText } from '@fastgpt/global/common/error/utils'; - -type Props = { - query: string; -}; - -// Response type same as HTTP outputs -type Response = Promise<{ - result: string; -}>; - -const main = async (props: Props, retry = 3): Response => { - const { query } = props; - - try { - const searchResults = await searchNews(query, { - safeSearch: SafeSearchType.STRICT - }); - - const result = searchResults.results - .map((item) => ({ - title: item.title, - excerpt: item.excerpt, - url: item.url - })) - .slice(0, 10); - - return { - result: JSON.stringify(result) - }; - } catch (error) { - if (retry <= 0) { - addLog.warn('DuckDuckGo error', { error }); - return { - result: getErrText(error, 'Failed to fetch data from DuckDuckGo') - }; - } - - await delay(Math.random() * 5000); - return main(props, retry - 1); - } -}; - -export default main; diff --git a/packages/plugins/src/duckduckgo/searchNews/template.json b/packages/plugins/src/duckduckgo/searchNews/template.json deleted file mode 100644 index 6068ccbd7..000000000 --- a/packages/plugins/src/duckduckgo/searchNews/template.json +++ /dev/null @@ -1,319 +0,0 @@ -{ - "author": "", - "name": "DuckDuckGo 新闻检索", - "avatar": "core/workflow/template/duckduckgo", - "intro": "使用 DuckDuckGo 进行新闻检索", - "showStatus": true, - "weight": 10, - - "isTool": true, - "templateType": "search", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "可以配置插件需要哪些输入,利用这些输入来运行插件", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 476.7941605947366, - "y": -79.06127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "description": "检索词", - "required": true, - "toolDescription": "检索词" - } - ], - "outputs": [ - { - "id": "query", - "valueType": "string", - "key": "query", - "label": "query", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1761.324716650201, - "y": -60.56127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "result", - "label": "result", - "description": " 检索结果", - "value": ["hjnVuJAOwyXV", "lEyy5QqyIBrK"] - } - ], - "outputs": [] - }, - { - "nodeId": "hjnVuJAOwyXV", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1054.6774638324207, - "y": -403.06127656499825 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "duckduckgo/searchNews", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"query\": \"{{query}}\"\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "query"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "id": "lEyy5QqyIBrK", - "valueType": "string", - "type": "dynamic", - "key": "result", - "label": "result" - } - ] - }, - { - "nodeId": "dG0Prv5FaR8e", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": -32.12465070539588, - "y": -103.56127656499825 - }, - "version": "4811", - "inputs": [], - "outputs": [] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "hjnVuJAOwyXV", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "hjnVuJAOwyXV-target-left" - }, - { - "source": "hjnVuJAOwyXV", - "target": "pluginOutput", - "sourceHandle": "hjnVuJAOwyXV-source-right", - "targetHandle": "pluginOutput-target-left" - } - ] - } -} diff --git a/packages/plugins/src/duckduckgo/searchVideo/index.ts b/packages/plugins/src/duckduckgo/searchVideo/index.ts deleted file mode 100644 index c1637d810..000000000 --- a/packages/plugins/src/duckduckgo/searchVideo/index.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { searchVideos, SafeSearchType } from 'duck-duck-scrape'; -import { delay } from '@fastgpt/global/common/system/utils'; -import { addLog } from '@fastgpt/service/common/system/log'; -import { getErrText } from '@fastgpt/global/common/error/utils'; - -type Props = { - query: string; -}; - -// Response type same as HTTP outputs -type Response = Promise<{ - result: string; -}>; - -const main = async (props: Props, retry = 3): Response => { - const { query } = props; - - try { - const searchResults = await searchVideos(query, { - safeSearch: SafeSearchType.STRICT - }); - - const result = searchResults.results - .map((item) => ({ - title: item.title, - description: item.description, - url: item.url - })) - .slice(0, 10); - - return { - result: JSON.stringify(result) - }; - } catch (error) { - if (retry <= 0) { - addLog.warn('DuckDuckGo error', { error }); - return { - result: getErrText(error, 'Failed to fetch data from DuckDuckGo') - }; - } - - await delay(Math.random() * 5000); - return main(props, retry - 1); - } -}; - -export default main; diff --git a/packages/plugins/src/duckduckgo/searchVideo/template.json b/packages/plugins/src/duckduckgo/searchVideo/template.json deleted file mode 100644 index bfb3efbd0..000000000 --- a/packages/plugins/src/duckduckgo/searchVideo/template.json +++ /dev/null @@ -1,319 +0,0 @@ -{ - "author": "", - "name": "DuckDuckGo 视频搜索", - "avatar": "core/workflow/template/duckduckgo", - "intro": "使用 DuckDuckGo 进行视频搜索", - "showStatus": true, - "weight": 10, - - "isTool": true, - "templateType": "search", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "可以配置插件需要哪些输入,利用这些输入来运行插件", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 429.8213651162415, - "y": -79.06127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "description": "检索词", - "required": true, - "toolDescription": "检索词" - } - ], - "outputs": [ - { - "id": "query", - "valueType": "string", - "key": "query", - "label": "query", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1781.1978224295642, - "y": -60.56127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "result", - "label": "result", - "description": " 检索结果", - "value": ["hjnVuJAOwyXV", "lEyy5QqyIBrK"] - } - ], - "outputs": [] - }, - { - "nodeId": "hjnVuJAOwyXV", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1054.6774638324207, - "y": -403.06127656499825 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "duckduckgo/searchVideo", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"query\": \"{{query}}\"\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "query"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "id": "lEyy5QqyIBrK", - "valueType": "string", - "type": "dynamic", - "key": "result", - "label": "result" - } - ] - }, - { - "nodeId": "iyF6yGGXuyWn", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": -8.638252966148258, - "y": -103.56127656499825 - }, - "version": "4811", - "inputs": [], - "outputs": [] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "hjnVuJAOwyXV", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "hjnVuJAOwyXV-target-left" - }, - { - "source": "hjnVuJAOwyXV", - "target": "pluginOutput", - "sourceHandle": "hjnVuJAOwyXV-source-right", - "targetHandle": "pluginOutput-target-left" - } - ] - } -} diff --git a/packages/plugins/src/duckduckgo/template.json b/packages/plugins/src/duckduckgo/template.json deleted file mode 100644 index 8fbd890da..000000000 --- a/packages/plugins/src/duckduckgo/template.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "author": "", - "name": "DuckDuckGo服务", - "avatar": "core/workflow/template/duckduckgo", - "intro": "DuckDuckGo 服务,包含网络搜索、图片搜索、新闻搜索等。", - "showStatus": false, - "weight": 11, - - "isTool": true, - "templateType": "search", - - "workflow": { - "nodes": [], - "edges": [] - } -} diff --git a/packages/plugins/src/feishu/template.json b/packages/plugins/src/feishu/template.json deleted file mode 100644 index ee30e9f10..000000000 --- a/packages/plugins/src/feishu/template.json +++ /dev/null @@ -1,539 +0,0 @@ -{ - "author": "", - "name": "飞书 webhook", - "avatar": "core/app/templates/plugin-feishu", - "intro": "向飞书机器人发起 webhook 请求。", - "courseUrl": "https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot#f62e72d5", - "showStatus": false, - "weight": 10, - - "isTool": true, - "templateType": "communication", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "可以配置插件需要哪些输入,利用这些输入来运行插件", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 194.3171058153904, - "y": 125.65095361549629 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "content", - "label": "content", - "description": "需要发送的消息", - "required": true, - "toolDescription": "需要发送的消息", - "list": [], - "defaultValue": "" - }, - { - "renderTypeList": ["input"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "hook_url", - "label": "hook_url", - "description": "飞书机器人地址", - "required": true, - "defaultValue": "", - "list": [] - } - ], - "outputs": [ - { - "id": "query", - "valueType": "string", - "key": "content", - "label": "content", - "type": "hidden" - }, - { - "id": "hook_url", - "valueType": "string", - "key": "hook_url", - "label": "hook_url", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 2128.4279417147436, - "y": 170.6509536154963 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "object", - "canEdit": true, - "key": "result", - "label": "result", - "description": "", - "value": ["vzreK6vHrPvZ", "httpRawResponse"] - } - ], - "outputs": [] - }, - { - "nodeId": "vzreK6vHrPvZ", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1363.4233257919495, - "y": -182.3490463845037 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "{{url}}", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{{content}}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "url", - "label": "url", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "hook_url"] - }, - { - "renderTypeList": ["reference"], - "valueType": "object", - "canEdit": true, - "key": "content", - "label": "content", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["qcJpBBVtXsGd", "system_rawResponse"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - } - ] - }, - { - "nodeId": "qcJpBBVtXsGd", - "name": "代码运行", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 833.6400043909581, - "y": -127.34904638450371 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({data1}){\n try{\n const parseData = JSON.parse(data1)\n if(typeof parseData === 'object') {\n return parseData\n }\n return {\n \"msg_type\": \"text\",\n content: {\n \"text\": data1\n }\n }\n } catch(err) {\n return {\n \"msg_type\": \"text\",\n content: {\n \"text\": data1\n }\n }\n }\n}", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "data1", - "label": "data1", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "query"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "content", - "valueType": "object", - "label": "content" - } - ] - }, - { - "nodeId": "xDvVyZbQIrPg", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": -272.2181157945658, - "y": 125.65095361549629 - }, - "version": "4811", - "inputs": [], - "outputs": [] - } - ], - "edges": [ - { - "source": "vzreK6vHrPvZ", - "target": "pluginOutput", - "sourceHandle": "vzreK6vHrPvZ-source-right", - "targetHandle": "pluginOutput-target-left" - }, - { - "source": "pluginInput", - "target": "qcJpBBVtXsGd", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "qcJpBBVtXsGd-target-left" - }, - { - "source": "qcJpBBVtXsGd", - "target": "vzreK6vHrPvZ", - "sourceHandle": "qcJpBBVtXsGd-source-right", - "targetHandle": "vzreK6vHrPvZ-target-left" - } - ], - "chatConfig": { - "welcomeText": "", - "variables": [], - "questionGuide": false, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "", - "autoExecute": { - "open": false, - "defaultPrompt": "" - }, - "_id": "6710a5619c45325525326719" - } - } -} diff --git a/packages/plugins/src/fetchUrl/index.ts b/packages/plugins/src/fetchUrl/index.ts deleted file mode 100644 index 879e80aa9..000000000 --- a/packages/plugins/src/fetchUrl/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { urlsFetch } from '@fastgpt/service/common/string/cheerio'; - -type Props = { - url: string; -}; -type Response = Promise<{ - result: any; -}>; - -const main = async ({ url }: Props): Response => { - try { - const result = await urlsFetch({ - urlList: [url], - selector: 'body' - }); - - const title = result[0]?.title; - const content = result[0]?.content; - - return { - result: `${title ? `# ${title}\n\n` : ''}${content}` - }; - } catch (error) { - return { - result: 'Fetch error' - }; - } -}; - -export default main; diff --git a/packages/plugins/src/fetchUrl/template.json b/packages/plugins/src/fetchUrl/template.json deleted file mode 100644 index 26fc48760..000000000 --- a/packages/plugins/src/fetchUrl/template.json +++ /dev/null @@ -1,340 +0,0 @@ -{ - "author": "", - "name": "网页内容抓取", - "avatar": "core/workflow/template/fetchUrl", - "intro": "可获取一个网页链接内容,并以 Markdown 格式输出,仅支持获取静态网站。", - "showStatus": true, - "weight": 10, - - "isTool": true, - "templateType": "tools", - - "workflow": { - "nodes": [ - { - "nodeId": "lmpb9v2lo2lk", - "name": "插件开始", - "intro": "自定义配置外部输入,使用插件时,仅暴露自定义配置的输入", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 487.2485939481787, - "y": -159.13661665265613 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "key": "url", - "label": "url", - "description": "需要读取的网页链接", - "required": true, - "toolDescription": "需要读取的网页链接", - "list": [], - "defaultValue": "" - } - ], - "outputs": [ - { - "id": "url", - "valueType": "string", - "key": "url", - "label": "url", - "type": "hidden" - } - ] - }, - { - "nodeId": "i7uow4wj2wdp", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1853.935047606551, - "y": -154.13661665265613 - }, - "version": "481", - "inputs": [ - { - "key": "result", - "valueType": "string", - "label": "result", - "renderTypeList": ["reference"], - "required": false, - "description": "", - "canEdit": true, - "editField": { - "key": true, - "description": true, - "valueType": true - }, - "value": ["ebLCxU43hHuZ", "rH4tMV02robs"] - } - ], - "outputs": [] - }, - { - "nodeId": "ebLCxU43hHuZ", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1054.2940501177068, - "y": -503.13661665265613 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectDataset", - "selectApp" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "fetchUrl", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"url\": \"{{url}}\"\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "url", - "label": "url", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectDataset", - "selectApp" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["lmpb9v2lo2lk", "url"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "id": "rH4tMV02robs", - "valueType": "string", - "type": "dynamic", - "key": "result", - "label": "result" - } - ] - } - ], - "edges": [ - { - "source": "lmpb9v2lo2lk", - "target": "ebLCxU43hHuZ", - "sourceHandle": "lmpb9v2lo2lk-source-right", - "targetHandle": "ebLCxU43hHuZ-target-left" - }, - { - "source": "ebLCxU43hHuZ", - "target": "i7uow4wj2wdp", - "sourceHandle": "ebLCxU43hHuZ-source-right", - "targetHandle": "i7uow4wj2wdp-target-left" - } - ], - "chatConfig": { - "welcomeText": "", - "variables": [], - "questionGuide": { - "open": false, - "model": "gpt-4o-mini", - "customPrompt": "You are an AI assistant tasked with predicting the user's next question based on the conversation history. Your goal is to generate 3 potential questions that will guide the user to continue the conversation. When generating these questions, adhere to the following rules:\n\n1. Use the same language as the user's last question in the conversation history.\n2. Keep each question under 20 characters in length.\n\nAnalyze the conversation history provided to you and use it as context to generate relevant and engaging follow-up questions. Your predictions should be logical extensions of the current topic or related areas that the user might be interested in exploring further.\n\nRemember to maintain consistency in tone and style with the existing conversation while providing diverse options for the user to choose from. Your goal is to keep the conversation flowing naturally and help the user delve deeper into the subject matter or explore related topics." - }, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "", - "autoExecute": { - "open": false, - "defaultPrompt": "" - }, - "_id": "677b59849d672185a5671b45" - } - } -} diff --git a/packages/plugins/src/getTime/index.ts b/packages/plugins/src/getTime/index.ts deleted file mode 100644 index 6c97b2761..000000000 --- a/packages/plugins/src/getTime/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -type Props = { - time: string; -}; -type Response = Promise<{ - time: string; -}>; - -const main = async ({ time }: Props): Response => { - return { - time - }; -}; - -export default main; diff --git a/packages/plugins/src/getTime/template.json b/packages/plugins/src/getTime/template.json deleted file mode 100644 index 11a2775fa..000000000 --- a/packages/plugins/src/getTime/template.json +++ /dev/null @@ -1,214 +0,0 @@ -{ - "author": "", - "templateType": "tools", - "name": "获取当前时间", - "avatar": "core/workflow/template/getTime", - "intro": "获取用户当前时区的时间。", - "showStatus": false, - "isTool": true, - "weight": 10, - "workflow": { - "nodes": [ - { - "nodeId": "lmpb9v2lo2lk", - "name": "插件开始", - "intro": "自定义配置外部输入,使用插件时,仅暴露自定义配置的输入", - "avatar": "/imgs/workflow/input.png", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 616.4226348688949, - "y": -165.05298493910115 - }, - "version": "481", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "i7uow4wj2wdp", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "/imgs/workflow/output.png", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1607.7142331269129, - "y": -150.8808596935447 - }, - "version": "481", - "inputs": [ - { - "key": "time", - "valueType": "string", - "label": "time", - "renderTypeList": ["reference"], - "required": false, - "description": "", - "canEdit": true, - "editField": { - "key": true, - "description": true, - "valueType": true - }, - "value": ["ebLCxU43hHuZ", "rH4tMV02robs"] - } - ], - "outputs": [] - }, - { - "nodeId": "ebLCxU43hHuZ", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "/imgs/workflow/http.png", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1050.9890727421412, - "y": -415.2085119990912 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "getTime" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "core.module.input.description.Http Request Header", - "placeholder": "core.module.input.description.Http Request Header", - "required": false - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"time\": \"{{cTime}}\"\n}", - "label": "", - "required": false - } - ], - "outputs": [ - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "id": "error", - "key": "error", - "label": "请求错误", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "label": "原始响应", - "required": true, - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "rH4tMV02robs", - "valueType": "string", - "type": "dynamic", - "key": "time", - "label": "time" - } - ] - } - ], - "edges": [ - { - "source": "lmpb9v2lo2lk", - "target": "ebLCxU43hHuZ", - "sourceHandle": "lmpb9v2lo2lk-source-right", - "targetHandle": "ebLCxU43hHuZ-target-left" - }, - { - "source": "ebLCxU43hHuZ", - "target": "i7uow4wj2wdp", - "sourceHandle": "ebLCxU43hHuZ-source-right", - "targetHandle": "i7uow4wj2wdp-target-left" - } - ] - } -} diff --git a/packages/plugins/src/google/template.json b/packages/plugins/src/google/template.json deleted file mode 100644 index a4167973e..000000000 --- a/packages/plugins/src/google/template.json +++ /dev/null @@ -1,560 +0,0 @@ -{ - "author": "", - "name": "Google搜索", - "avatar": "core/workflow/template/google", - "intro": "在google中搜索。", - "showStatus": true, - "weight": 10, - "courseUrl": "https://fael3z0zfze.feishu.cn/wiki/Vqk1w4ltNiuLifkHTuoc0hSrnVg?fromScene=spaceOverview", - "isTool": true, - "templateType": "search", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "workflow:template.plugin_start", - "intro": "workflow:intro_plugin_input", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 636.3048409085379, - "y": -238.61714728578016 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "cx", - "label": "cx", - "description": "Google搜索cxID", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "required": true - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "key", - "label": "key", - "description": "Google搜索key", - "defaultValue": "", - "required": true, - "list": [] - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "description": "查询字段值", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "required": true, - "toolDescription": "查询字段值" - } - ], - "outputs": [ - { - "id": "cx", - "valueType": "string", - "key": "cx", - "label": "cx", - "type": "hidden" - }, - { - "id": "key", - "valueType": "string", - "key": "key", - "label": "key", - "type": "hidden" - }, - { - "id": "query", - "valueType": "string", - "key": "query", - "label": "query", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "common:core.module.template.self_output", - "intro": "workflow:intro_custom_plugin_output", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 2764.1105686698083, - "y": -30.617147285780163 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "object", - "canEdit": true, - "key": "result", - "label": "result", - "isToolOutput": true, - "description": "", - "value": ["pZTkvleFSZXo", "system_rawResponse"] - } - ], - "outputs": [] - }, - { - "nodeId": "pluginConfig", - "name": "common:core.module.template.system_config", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": 184.66337662472682, - "y": -216.05298493910115 - }, - "version": "4811", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "nyA6oA8mF1iW", - "name": "HTTP 请求", - "intro": "调用谷歌搜索,查询相关内容", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1335.0647252518884, - "y": -455.9043948565971 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "GET", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "https://www.googleapis.com/customsearch/v1", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [ - { - "key": "q", - "type": "string", - "value": "{{query}}" - }, - { - "key": "cx", - "type": "string", - "value": "{{$pluginInput.cx$}}" - }, - { - "key": "key", - "type": "string", - "value": "{{$pluginInput.key$}}" - }, - { - "key": "c2coff", - "type": "string", - "value": "1" - }, - { - "key": "start", - "type": "string", - "value": "1" - }, - { - "key": "end", - "type": "string", - "value": "20" - }, - { - "key": "dateRestrict", - "type": "string", - "value": "m[1]" - } - ], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "valueType": "string", - "renderTypeList": ["reference"], - "key": "query", - "label": "query", - "toolDescription": "谷歌搜索检索词", - "required": true, - "canEdit": true, - "editField": { - "key": true, - "description": true - }, - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "value": ["pluginInput", "query"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "editField": { - "key": true, - "valueType": true - } - }, - { - "id": "M5YmxaYe8em1", - "type": "dynamic", - "key": "prompt", - "valueType": "string", - "label": "prompt" - } - ] - }, - { - "nodeId": "pZTkvleFSZXo", - "name": "代码运行", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 2153.5325687235554, - "y": -188.04429852303304 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "editField": { - "key": true, - "valueType": true - }, - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({data}){\n const result = data.items.map((item) => ({\n title: item.title,\n link: item.link,\n snippet: item.snippet\n }))\n return JSON.stringify(result) \n}", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "data", - "valueType": "object", - "label": "data", - "renderTypeList": ["reference"], - "description": "", - "canEdit": true, - "editField": { - "key": true, - "valueType": true - }, - "value": ["nyA6oA8mF1iW", "httpRawResponse"], - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "editField": { - "key": true, - "valueType": true - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "prompt", - "valueType": "string", - "label": "prompt" - } - ] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "nyA6oA8mF1iW", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "nyA6oA8mF1iW-target-left" - }, - { - "source": "nyA6oA8mF1iW", - "target": "pZTkvleFSZXo", - "sourceHandle": "nyA6oA8mF1iW-source-right", - "targetHandle": "pZTkvleFSZXo-target-left" - }, - { - "source": "pZTkvleFSZXo", - "target": "pluginOutput", - "sourceHandle": "pZTkvleFSZXo-source-right", - "targetHandle": "pluginOutput-target-left" - } - ], - "chatConfig": { - "welcomeText": "", - "variables": [], - "questionGuide": { - "open": false - }, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "", - "_id": "6709e90cd9873479ee78fe71" - } - } -} diff --git a/packages/plugins/src/mathExprVal/index.ts b/packages/plugins/src/mathExprVal/index.ts deleted file mode 100644 index a171b7fb9..000000000 --- a/packages/plugins/src/mathExprVal/index.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Parser } from 'expr-eval'; - -type Props = { - expr: string; -}; - -// Response type same as HTTP outputs -type Response = Promise<{ - result: string; -}>; - -const replaceSpecialChar = (expr: string) => { - // replace ** to ^ - let result = expr.replace(/\*\*/g, '^'); - return result; -}; - -const main = async ({ expr }: Props): Response => { - if (typeof expr !== 'string') { - return { - result: `${expr} is not a string` - }; - } - - try { - const parser = new Parser(); - const exprParser = parser.parse(replaceSpecialChar(expr)); - - return { - result: exprParser.evaluate() - }; - } catch (error) { - return { - result: `${expr} is not a valid math expression. Error: ${error}` - }; - } -}; - -export default main; diff --git a/packages/plugins/src/mathExprVal/template.json b/packages/plugins/src/mathExprVal/template.json deleted file mode 100644 index 2d440e59c..000000000 --- a/packages/plugins/src/mathExprVal/template.json +++ /dev/null @@ -1,252 +0,0 @@ -{ - "author": "", - "name": "数学公式执行", - "avatar": "core/workflow/template/mathCall", - "intro": "用于执行数学表达式的工具,通过 js 的 expr-eval 库运行表达式并返回结果。", - "showStatus": false, - "weight": 10, - - "isTool": true, - "templateType": "tools", - - "workflow": { - "nodes": [ - { - "nodeId": "ioNyiO62aWcG", - "name": "插件输入", - "intro": "可以配置插件需要哪些输入,利用这些输入来运行插件", - "avatar": "/imgs/workflow/input.png", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 494.7780128195933, - "y": -145.65080850146154 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "key": "数学表达式", - "label": "数学表达式", - "description": "需要执行的数学表达式", - "required": true, - "toolDescription": "需要执行的数学表达式" - } - ], - "outputs": [ - { - "id": "数学表达式", - "valueType": "string", - "key": "数学表达式", - "label": "数学表达式", - "type": "hidden" - } - ] - }, - { - "nodeId": "sowtxkCPjvb7", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "/imgs/workflow/output.png", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1850.4258139184146, - "y": -147.7125146361461 - }, - "version": "481", - "inputs": [ - { - "key": "result", - "valueType": "string", - "label": "result", - "renderTypeList": ["reference"], - "required": false, - "description": "", - "canEdit": true, - "value": ["hzO1JnuLrKpK", "vJnW9JVLOJFT"] - } - ], - "outputs": [ - { - "id": "sowtxkCPjvb7", - "key": "result", - "valueType": "string", - "label": "result", - "type": "static" - } - ] - }, - { - "nodeId": "hzO1JnuLrKpK", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "/imgs/workflow/http.png", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1188.947986995841, - "y": -473.52694296182904 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "mathExprVal" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [ - { - "key": "Authorization", - "type": "string", - "value": "Bearer fb968ed1-b1dd-4fc1-8409-c9339cbeb14f" - } - ], - "label": "", - "description": "core.module.input.description.Http Request Header", - "placeholder": "core.module.input.description.Http Request Header", - "required": false - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"expr\":\"{{expr}}\"\n}", - "label": "", - "required": false - }, - { - "key": "expr", - "valueType": "string", - "label": "expr", - "renderTypeList": ["reference"], - "canEdit": true, - "value": ["ioNyiO62aWcG", "数学表达式"] - } - ], - "outputs": [ - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "id": "error", - "key": "error", - "label": "请求错误", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "label": "原始响应", - "required": true, - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "vJnW9JVLOJFT", - "valueType": "string", - "type": "dynamic", - "key": "result", - "label": "result" - } - ] - } - ], - "edges": [ - { - "source": "ioNyiO62aWcG", - "target": "hzO1JnuLrKpK", - "sourceHandle": "ioNyiO62aWcG-source-right", - "targetHandle": "hzO1JnuLrKpK-target-left" - }, - { - "source": "hzO1JnuLrKpK", - "target": "sowtxkCPjvb7", - "sourceHandle": "hzO1JnuLrKpK-source-right", - "targetHandle": "sowtxkCPjvb7-target-left" - } - ] - } -} diff --git a/packages/plugins/src/searchXNG/index.ts b/packages/plugins/src/searchXNG/index.ts deleted file mode 100644 index eebe87adc..000000000 --- a/packages/plugins/src/searchXNG/index.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { delay } from '@fastgpt/global/common/system/utils'; -import * as cheerio from 'cheerio'; -import { i18nT } from '../../../web/i18n/utils'; - -type Props = { - query: string; - url: string; -}; - -interface SearchResult { - title: string; - link: string; - snippet: string; -} - -type Response = Promise<{ - result: string; - error?: Record; -}>; - -const main = async (props: Props, retry = 3): Response => { - const { query, url } = props; - - if (!query) { - return Promise.reject(i18nT('chat:not_query')); - } - - if (!url) { - return Promise.reject('Can not find url'); - } - - try { - const response = await fetch(`${url}?q=${encodeURIComponent(query)}&language=auto`); - const html = await response.text(); - const $ = cheerio.load(html, { - xml: false, - decodeEntities: true - }); - - const results: SearchResult[] = []; - - $('.result').each((_: number, element: cheerio.Element) => { - const $element = $(element); - results.push({ - title: $element.find('h3').text().trim(), - link: $element.find('a').first().attr('href') || '', - snippet: $element.find('.content').text().trim() - }); - }); - - if (results.length === 0) { - return { - result: JSON.stringify([]), - error: { - message: 'No search results', - code: 500 - } - }; - } - - return { - result: JSON.stringify(results.slice(0, 10)) - }; - } catch (error) { - console.log(error); - if (retry <= 0) { - console.log('Search XNG error', { error }); - return Promise.reject('Failed to fetch data from Search XNG'); - } - - await delay(Math.random() * 2000); - return main(props, retry - 1); - } -}; - -export default main; diff --git a/packages/plugins/src/searchXNG/template.json b/packages/plugins/src/searchXNG/template.json deleted file mode 100644 index 5b8f43047..000000000 --- a/packages/plugins/src/searchXNG/template.json +++ /dev/null @@ -1,412 +0,0 @@ -{ - "author": "", - "name": "Search XNG 搜索", - "avatar": "core/workflow/template/searxng", - "intro": "使用 Search XNG 服务进行搜索。", - "courseUrl": "/docs/guide/plugins/searxng_plugin_guide/", - "showStatus": true, - "weight": 10, - - "isTool": true, - "templateType": "search", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "可以配置插件需要哪些输入,利用这些输入来运行插件", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 482.8986144681427, - "y": -77.56127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "description": "检索词", - "required": true, - "toolDescription": "检索词" - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "url", - "label": "url", - "description": "部署的searXNG服务的链接", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true - } - ], - "outputs": [ - { - "id": "query", - "valueType": "string", - "key": "query", - "label": "query", - "type": "hidden" - }, - { - "id": "url", - "valueType": "string", - "key": "url", - "label": "url", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1763.7518709731714, - "y": -55.56127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "result", - "label": "result", - "description": " 检索结果", - "value": ["hjnVuJAOwyXV", "lEyy5QqyIBrK"] - }, - { - "renderTypeList": ["reference"], - "valueType": "object", - "canEdit": true, - "key": "error", - "label": "error", - "isToolOutput": true, - "description": "请求错误", - "required": true, - "value": ["hjnVuJAOwyXV", "error"] - } - ], - "outputs": [] - }, - { - "nodeId": "hjnVuJAOwyXV", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1054.6774638324207, - "y": -403.06127656499825 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "searchXNG", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"query\": \"{{query}}\",\n \"url\": \"{{url}}\"\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "query"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "url", - "label": "url", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "url"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "id": "lEyy5QqyIBrK", - "valueType": "string", - "type": "dynamic", - "key": "result", - "label": "result" - } - ] - }, - { - "nodeId": "f1mRh1D85H2D", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": -28.511358745511643, - "y": -103.56127656499825 - }, - "version": "4811", - "inputs": [], - "outputs": [] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "hjnVuJAOwyXV", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "hjnVuJAOwyXV-target-left" - }, - { - "source": "hjnVuJAOwyXV", - "target": "pluginOutput", - "sourceHandle": "hjnVuJAOwyXV-source-right", - "targetHandle": "pluginOutput-target-left" - } - ], - "chatConfig": { - "welcomeText": "", - "variables": [], - "questionGuide": false, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "", - "autoExecute": { - "open": false, - "defaultPrompt": "" - }, - "_id": "67611a5eed7efa452a6e50c5" - } - } -} diff --git a/packages/plugins/src/smtpEmail/index.ts b/packages/plugins/src/smtpEmail/index.ts deleted file mode 100644 index f08afe073..000000000 --- a/packages/plugins/src/smtpEmail/index.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { getErrText } from '@fastgpt/global/common/error/utils'; -import nodemailer from 'nodemailer'; - -interface Props { - // SMTP配置 - smtpHost: string; - smtpPort: string; - SSL: boolean; - smtpUser: string; - smtpPass: string; - fromName?: string; - // 邮件参数 - to: string; - subject: string; - content: string; - cc?: string; - bcc?: string; - attachments?: string; -} - -interface Response { - success: boolean; - messageId?: string; - error?: string; -} - -const validateEmail = (email: string) => { - const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - return regex.test(email); -}; - -const validateEmails = (emails: string) => { - return emails.split(',').every((email) => validateEmail(email.trim())); -}; - -const main = async ({ - smtpHost, - smtpPort, - SSL, - smtpUser, - smtpPass, - fromName, - to, - subject, - content, - cc, - bcc, - attachments -}: Props): Promise => { - try { - // 验证SMTP配置 - if (!smtpHost || !smtpPort || !smtpUser || !smtpPass) { - throw new Error('Incomplete SMTP configuration'); - } - - // 验证必填参数 - if (!to || !subject || !content) { - throw new Error('Recipient, subject, and content are required'); - } - - // 验证邮箱格式 - if (!validateEmails(to)) { - throw new Error('Invalid recipient email format'); - } - if (cc && !validateEmails(cc)) { - throw new Error('Invalid CC email format'); - } - if (bcc && !validateEmails(bcc)) { - throw new Error('Invalid BCC email format'); - } - - // 创建SMTP传输对象 - const transporter = nodemailer.createTransport({ - host: smtpHost, - port: Number(smtpPort), - secure: SSL === true, - auth: { - user: smtpUser, - pass: smtpPass - } - }); - - let attachmentsArray = []; - try { - attachmentsArray = JSON.parse(attachments || '[]'); - } catch (error) { - throw new Error('Attachment format parsing error, please check attachment configuration'); - } - - // 发送邮件 - const info = await transporter.sendMail({ - from: `"${fromName || 'FastGPT'}" <${smtpUser}>`, - to: to - .split(',') - .map((email) => email.trim()) - .join(','), - cc: cc - ?.split(',') - .map((email) => email.trim()) - .join(','), - bcc: bcc - ?.split(',') - .map((email) => email.trim()) - .join(','), - subject, - html: content, - attachments: attachmentsArray || [] - }); - - return { - success: true, - messageId: info.messageId - }; - } catch (error: any) { - return { - success: false, - error: getErrText(error) - }; - } -}; - -export default main; diff --git a/packages/plugins/src/smtpEmail/template.json b/packages/plugins/src/smtpEmail/template.json deleted file mode 100644 index 33cdbeae9..000000000 --- a/packages/plugins/src/smtpEmail/template.json +++ /dev/null @@ -1,650 +0,0 @@ -{ - "author": "cloudpense", - "name": "Email 邮件发送", - "avatar": "plugins/email", - "intro": "通过SMTP协议发送电子邮件(nodemailer)", - "showStatus": true, - "weight": 10, - "isTool": true, - "templateType": "tools", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "workflow:template.plugin_start", - "intro": "workflow:intro_plugin_input", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 595.3456736313964, - "y": -323.02524442647456 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "smtpHost", - "label": "smtpHost", - "description": "", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true, - "customInputConfig": { - "selectValueTypeList": ["string"] - } - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "smtpPort", - "label": "smtpPort", - "description": "SMTP端口", - "defaultValue": "465", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true - }, - { - "renderTypeList": ["select", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "SSL", - "label": "SSL", - "description": "SSL", - "defaultValue": "true", - "list": [ - { - "label": "true", - "value": "true" - }, - { - "label": "false", - "value": "false" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "smtpUser", - "label": "smtpUser", - "description": "SMTP用户名, 邮箱账号", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "smtpPass", - "label": "smtpPass", - "description": "邮箱密码或授权码", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "fromName", - "label": "fromName", - "description": "显示的发件人名称", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "to", - "label": "to", - "description": "请输入收件人邮箱,多个邮箱用逗号分隔", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true, - "toolDescription": "请输入收件人邮箱,多个邮箱用逗号分隔" - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "subject", - "label": "subject", - "description": "请输入邮件主题", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true, - "toolDescription": "请输入邮件主题" - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "content", - "label": "content", - "description": "请输入邮件内容,支持HTML格式", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": true, - "toolDescription": "请输入邮件内容,支持HTML格式" - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "cc", - "label": "cc", - "description": "请输入抄送邮箱,多个邮箱用逗号分隔", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": false, - "toolDescription": "请输入抄送邮箱,多个邮箱用逗号分隔" - }, - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "bcc", - "label": "bcc", - "description": "请输入密送邮箱,多个邮箱用逗号分隔", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": false, - "toolDescription": "请输入密送邮箱,多个邮箱用逗号分隔" - }, - { - "renderTypeList": ["JSONEditor", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "attachments", - "label": "attachments", - "description": "必须是json数组格式\n[{\"filename\":\"附件名\",\"path\":\"附件url\"}]", - "defaultValue": "", - "list": [ - { - "label": "", - "value": "" - } - ], - "maxFiles": 5, - "canSelectFile": true, - "canSelectImg": true, - "required": false, - "customInputConfig": { - "selectValueTypeList": ["arrayObject"] - }, - "toolDescription": "必须是json数组格式\n[{\"filename\":\"附件名\",\"path\":\"附件url\"}]", - "maxLength": 0 - } - ], - "outputs": [ - { - "id": "smtpHost", - "valueType": "string", - "key": "smtpHost", - "label": "smtpHost", - "type": "hidden" - }, - { - "id": "smtpPort", - "valueType": "string", - "key": "smtpPort", - "label": "smtpPort", - "type": "hidden" - }, - { - "id": "SSL", - "valueType": "string", - "key": "SSL", - "label": "SSL", - "type": "hidden" - }, - { - "id": "smtpUser", - "valueType": "string", - "key": "smtpUser", - "label": "smtpUser", - "type": "hidden" - }, - { - "id": "smtpPass", - "valueType": "string", - "key": "smtpPass", - "label": "smtpPass", - "type": "hidden" - }, - { - "id": "fromName", - "valueType": "string", - "key": "fromName", - "label": "fromName", - "type": "hidden" - }, - { - "id": "to", - "valueType": "string", - "key": "to", - "label": "to", - "type": "hidden" - }, - { - "id": "subject", - "valueType": "string", - "key": "subject", - "label": "subject", - "type": "hidden" - }, - { - "id": "content", - "valueType": "string", - "key": "content", - "label": "content", - "type": "hidden" - }, - { - "id": "cc", - "valueType": "string", - "key": "cc", - "label": "cc", - "type": "hidden" - }, - { - "id": "bcc", - "valueType": "string", - "key": "bcc", - "label": "bcc", - "type": "hidden" - }, - { - "id": "attachments", - "valueType": "string", - "key": "attachments", - "label": "attachments", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "common:core.module.template.self_output", - "intro": "workflow:intro_custom_plugin_output", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 2135.4991928806685, - "y": -98.02524442647456 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "发送结果", - "label": "发送结果", - "isToolOutput": true, - "description": "", - "required": true, - "value": ["uOX6ITvPWm9O", "httpRawResponse"] - } - ], - "outputs": [] - }, - { - "nodeId": "pluginConfig", - "name": "common:core.module.template.system_config", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": 184.66337662472682, - "y": -216.05298493910115 - }, - "version": "4811", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "uOX6ITvPWm9O", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1340.0519095857342, - "y": -393.02524442647456 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectDataset", - "selectApp" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "smtpEmail", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n\"smtpHost\": \"{{$pluginInput.smtpHost$}}\",\n\"smtpPort\": \"{{$pluginInput.smtpPort$}}\",\n\"SSL\": {{$pluginInput.SSL$}},\n\"smtpUser\": \"{{$pluginInput.smtpUser$}}\",\n\"smtpPass\": \"{{$pluginInput.smtpPass$}}\",\n\"fromName\": \"{{$pluginInput.fromName$}}\",\n\"to\": \"{{$pluginInput.to$}}\",\n\"subject\": \"{{$pluginInput.subject$}}\",\n\"content\": \"{{$pluginInput.content$}}\",\n\"cc\": \"{{$pluginInput.cc$}}\",\n\"bcc\": \"{{$pluginInput.bcc$}}\",\n\"attachments\":'{{$pluginInput.attachments$}}'\n}", - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "输出字段提取", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "可以通过 JSONPath 语法来提取响应值中的指定字段", - "valueDesc": "" - } - ] - } - ], - "edges": [ - { - "source": "uOX6ITvPWm9O", - "target": "pluginOutput", - "sourceHandle": "uOX6ITvPWm9O-source-right", - "targetHandle": "pluginOutput-target-left" - }, - { - "source": "pluginInput", - "target": "uOX6ITvPWm9O", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "uOX6ITvPWm9O-target-left" - } - ], - "chatConfig": { - "welcomeText": "", - "variables": [], - "questionGuide": { - "open": false, - "model": "gpt-4o-mini", - "customPrompt": "" - }, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "通过SMTP协议发送电子邮件", - "autoExecute": { - "open": false, - "defaultPrompt": "" - }, - "_id": "67ad649ea4b6b8eefa9d3d0d" - } - } -} diff --git a/packages/plugins/src/template/index.ts b/packages/plugins/src/template/index.ts deleted file mode 100644 index 43251bbbd..000000000 --- a/packages/plugins/src/template/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; - -type Props = { - text: string; -}; - -// Response type same as HTTP outputs -type Response = Promise<{ - [NodeInputKeyEnum.answerText]: string; - responseText: string; -}>; - -const main = async ({ text }: Props): Response => { - return { - // This output object needs to correspond to the content of the plug-in output - [NodeInputKeyEnum.answerText]: 'AnswerText', // This is a special field, and returning this field will return a message to the client - responseText: `text: ${text}` - }; -}; - -export default main; diff --git a/packages/plugins/src/template/template.json b/packages/plugins/src/template/template.json deleted file mode 100644 index 0b6c6dc04..000000000 --- a/packages/plugins/src/template/template.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "author": "", - "name": "文本加工", - "avatar": "/imgs/workflow/textEditor.svg", - "intro": "可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。", - "showStatus": false, - "weight": 10, - - "isTool": true, - "templateType": "tools", - - "workflow": { - "nodes": [], - "edges": [] - } -} diff --git a/packages/plugins/src/wiki/index.ts b/packages/plugins/src/wiki/index.ts deleted file mode 100644 index 19aaa83d8..000000000 --- a/packages/plugins/src/wiki/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { getErrText } from '@fastgpt/global/common/error/utils'; -import { addLog } from '@fastgpt/service/common/system/log'; -import { delay } from '@fastgpt/global/common/system/utils'; -import wiki from 'wikijs'; - -type Props = { - query: string; -}; - -// Response type same as HTTP outputs -type Response = Promise<{ - result: string; -}>; - -const main = async (props: Props, retry = 3): Response => { - const { query } = props; - - try { - const searchResults = await wiki({ apiUrl: 'https://zh.wikipedia.org/w/api.php' }) - .page(query) - .then((page) => { - return page.summary(); - }); - - return { - result: searchResults - }; - } catch (error) { - console.log(error); - - if (retry <= 0) { - addLog.warn('search wiki error', { error }); - return { - result: getErrText(error, 'Failed to fetch data from wiki') - }; - } - - await delay(Math.random() * 5000); - return main(props, retry - 1); - } -}; - -export default main; diff --git a/packages/plugins/src/wiki/template.json b/packages/plugins/src/wiki/template.json deleted file mode 100644 index 1be627064..000000000 --- a/packages/plugins/src/wiki/template.json +++ /dev/null @@ -1,342 +0,0 @@ -{ - "author": "", - "name": "Wiki搜索", - "avatar": "core/workflow/template/wiki", - "intro": "在Wiki中查询释义。", - "showStatus": true, - "weight": 10, - - "isTool": true, - "templateType": "search", - - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "可以配置插件需要哪些输入,利用这些输入来运行插件", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 484.02074451450517, - "y": -79.06127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["input", "reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "description": "检索词", - "required": true, - "toolDescription": "检索词", - "list": [] - } - ], - "outputs": [ - { - "id": "query", - "valueType": "string", - "key": "query", - "label": "query", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1759.5180706702588, - "y": -60.56127656499825 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "result", - "label": "result", - "description": " 检索结果", - "value": ["hjnVuJAOwyXV", "lEyy5QqyIBrK"] - } - ], - "outputs": [] - }, - { - "nodeId": "hjnVuJAOwyXV", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1054.6774638324207, - "y": -403.06127656499825 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "wiki", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"query\": \"{{query}}\"\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "query", - "label": "query", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "query"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "id": "lEyy5QqyIBrK", - "valueType": "string", - "type": "dynamic", - "key": "result", - "label": "result" - } - ] - }, - { - "nodeId": "f1mRh1D85H2D", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": -28.511358745511643, - "y": -103.56127656499825 - }, - "version": "4811", - "inputs": [], - "outputs": [] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "hjnVuJAOwyXV", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "hjnVuJAOwyXV-target-left" - }, - { - "source": "hjnVuJAOwyXV", - "target": "pluginOutput", - "sourceHandle": "hjnVuJAOwyXV-source-right", - "targetHandle": "pluginOutput-target-left" - } - ], - "chatConfig": { - "welcomeText": "", - "variables": [], - "questionGuide": { - "open": false - }, - "ttsConfig": { - "type": "web" - }, - "whisperConfig": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - }, - "chatInputGuide": { - "open": false, - "textList": [], - "customUrl": "" - }, - "instruction": "", - "_id": "67075cd2702bd7168ef8cb2d" - } - } -} diff --git a/packages/plugins/tsconfig.json b/packages/plugins/tsconfig.json deleted file mode 100644 index 13c4daa3b..000000000 --- a/packages/plugins/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "target": "es2015", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "baseUrl": "." - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.d.ts", "../**/*.d.ts"], - "exclude": ["node_modules"] -} diff --git a/packages/plugins/type.d.ts b/packages/plugins/type.d.ts deleted file mode 100644 index 3748c234a..000000000 --- a/packages/plugins/type.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { PluginTemplateType } from '@fastgpt/global/core/plugin/type.d'; -import { systemPluginResponseEnum } from '@fastgpt/global/core/workflow/runtime/constants'; -import type { SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type'; -import type { PluginGroupSchemaType } from '@fastgpt/service/core/app/plugin/type'; - -export type SystemPluginResponseType = Promise>; -export type SystemPluginSpecialResponse = { - type: 'SYSTEM_PLUGIN_BASE64'; - value: string; - extension: string; -}; - -declare global { - var pluginGroups: PluginGroupSchemaType[]; - var systemPlugins: SystemPluginTemplateItemType[]; - var systemPluginCb: Record SystemPluginResponseType>; -} diff --git a/packages/service/common/middle/i18n.ts b/packages/service/common/middle/i18n.ts new file mode 100644 index 000000000..90f465e3a --- /dev/null +++ b/packages/service/common/middle/i18n.ts @@ -0,0 +1,15 @@ +import { LocaleList, type localeType } from '@fastgpt/global/common/i18n/type'; +import type { ApiRequestProps } from '../../type/next'; + +/** + * Get the locale from the request cookies + * @param req - The request object + * @returns The locale string, 'en' by default + */ +export const getLocale = (req: ApiRequestProps): localeType => { + const locale = req.cookies['NEXT_LOCALE']; + if (locale && LocaleList.includes(locale as localeType)) { + return locale as localeType; + } + return 'en'; +}; diff --git a/packages/service/common/secret/utils.ts b/packages/service/common/secret/utils.ts index 22251c5a8..8faca6ada 100644 --- a/packages/service/common/secret/utils.ts +++ b/packages/service/common/secret/utils.ts @@ -3,17 +3,22 @@ import type { SecretValueType } from '@fastgpt/global/common/secret/type'; import { type StoreSecretValueType } from '@fastgpt/global/common/secret/type'; import { HeaderSecretTypeEnum } from '@fastgpt/global/common/secret/constants'; -export const storeSecretValue = ( - storeSecret: StoreSecretValueType = {} -): Record => { +export const encryptSecretValue = (value: SecretValueType): SecretValueType => { + if (!value.value) { + return value; + } + + return { + secret: encryptSecret(value.value), + value: '' + }; +}; + +export const storeSecretValue = (storeSecret: StoreSecretValueType = {}): StoreSecretValueType => { return Object.fromEntries( - Object.entries(storeSecret).map(([key, value]) => [ - key, - { - secret: encryptSecret(value.value), - value: '' - } - ]) + Object.entries(storeSecret).map(([key, value]) => { + return [key, encryptSecretValue(value)]; + }) ); }; @@ -24,20 +29,22 @@ export const getSecretValue = ({ }): Record => { if (!storeSecret) return {}; - return Object.entries(storeSecret).reduce( - (acc: Record, [key, { secret, value }]) => { - const actualValue = value || decryptSecret(secret); - - if (key === HeaderSecretTypeEnum.Bearer) { - acc['Authorization'] = `Bearer ${actualValue}`; - } else if (key === HeaderSecretTypeEnum.Basic) { - acc['Authorization'] = `Basic ${actualValue}`; - } else { - acc[key] = actualValue; - } - + return Object.entries(storeSecret).reduce((acc: Record, [key, val]) => { + if (typeof val !== 'object') { return acc; - }, - {} - ); + } + + const { secret, value } = val; + const actualValue = value || decryptSecret(secret); + + if (key === HeaderSecretTypeEnum.Bearer) { + acc['Authorization'] = `Bearer ${actualValue}`; + } else if (key === HeaderSecretTypeEnum.Basic) { + acc['Authorization'] = `Basic ${actualValue}`; + } else { + acc[key] = actualValue; + } + + return acc; + }, {}); }; diff --git a/packages/service/common/system/constants.ts b/packages/service/common/system/constants.ts index e60e54f3d..facf9ab12 100644 --- a/packages/service/common/system/constants.ts +++ b/packages/service/common/system/constants.ts @@ -1,3 +1,4 @@ export const FastGPTProUrl = process.env.PRO_URL ? `${process.env.PRO_URL}/api` : ''; +export const FastGPTPluginUrl = process.env.PLUGIN_BASE_URL ? `${process.env.PLUGIN_BASE_URL}` : ''; // @ts-ignore export const isFastGPTProService = () => !!global.systemConfig; diff --git a/packages/service/core/ai/config/provider/Doubao.json b/packages/service/core/ai/config/provider/Doubao.json index 12a2cd685..06cc1ddd7 100644 --- a/packages/service/core/ai/config/provider/Doubao.json +++ b/packages/service/core/ai/config/provider/Doubao.json @@ -2,8 +2,8 @@ "provider": "Doubao", "list": [ { - "model": "Doubao-Seed-1.6", - "name": "Doubao-Seed-1.6", + "model": "doubao-seed-1-6-250615", + "name": "doubao-seed-1-6-250615", "maxContext": 220000, "maxResponse": 16000, "quoteMaxToken": 220000, @@ -24,8 +24,8 @@ "type": "llm" }, { - "model": "Doubao-Seed-1.6-thinking", - "name": "Doubao-Seed-1.6-thinking", + "model": "doubao-seed-1-6-flash-250615", + "name": "doubao-seed-1-6-flash-250615", "maxContext": 220000, "maxResponse": 16000, "quoteMaxToken": 220000, @@ -46,8 +46,8 @@ "type": "llm" }, { - "model": "Doubao-Seed-1.6-flash", - "name": "Doubao-Seed-1.6-flash", + "model": "doubao-seed-1-6-thinking-250615", + "name": "doubao-seed-1-6-thinking-250615", "maxContext": 220000, "maxResponse": 16000, "quoteMaxToken": 220000, diff --git a/packages/service/core/app/controller.ts b/packages/service/core/app/controller.ts index 89c5519fa..dfb3d7f75 100644 --- a/packages/service/core/app/controller.ts +++ b/packages/service/core/app/controller.ts @@ -3,7 +3,8 @@ import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { MongoApp } from './schema'; import type { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node'; -import { storeSecretValue } from '../../common/secret/utils'; +import { encryptSecretValue, storeSecretValue } from '../../common/secret/utils'; +import { SystemToolInputTypeEnum } from '@fastgpt/global/core/app/systemTool/constants'; export const beforeUpdateAppFormat = ({ nodes }: { nodes?: StoreNodeItemType[] }) => { if (!nodes) return; @@ -14,6 +15,17 @@ export const beforeUpdateAppFormat = ({ nodes }: { nodes?: StoreNodeItemType[] } if (input.key === NodeInputKeyEnum.headerSecret && typeof input.value === 'object') { input.value = storeSecretValue(input.value); } + if (input.key === NodeInputKeyEnum.systemInputConfig && typeof input.value === 'object') { + input.inputList?.forEach((inputItem) => { + if ( + inputItem.inputType === 'secret' && + input.value?.type === SystemToolInputTypeEnum.manual && + input.value?.value + ) { + input.value.value[inputItem.key] = encryptSecretValue(input.value.value[inputItem.key]); + } + }); + } }); // Format dataset search diff --git a/packages/service/core/app/plugin/controller.ts b/packages/service/core/app/plugin/controller.ts index cf72269f0..e08f9b638 100644 --- a/packages/service/core/app/plugin/controller.ts +++ b/packages/service/core/app/plugin/controller.ts @@ -6,31 +6,42 @@ import { toolData2FlowNodeIO, toolSetData2FlowNodeIO } from '@fastgpt/global/core/workflow/utils'; -import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; -import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants'; -import { getHandleConfig } from '@fastgpt/global/core/workflow/template/utils'; -import { getNanoid } from '@fastgpt/global/common/string/tools'; -import { cloneDeep } from 'lodash'; import { MongoApp } from '../schema'; -import { type SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type'; -import { getSystemPluginTemplates } from '../../../../plugins/register'; +import type { localeType } from '@fastgpt/global/common/i18n/type'; +import { parseI18nString } from '@fastgpt/global/common/i18n/utils'; +import type { WorkflowTemplateBasicType } from '@fastgpt/global/core/workflow/type'; +import { type SystemPluginTemplateItemType } from '@fastgpt/global/core/app/plugin/type'; import { checkIsLatestVersion, getAppLatestVersion, getAppVersionById } from '../version/controller'; -import { type PluginRuntimeType } from '@fastgpt/global/core/plugin/type'; +import { type PluginRuntimeType } from '@fastgpt/global/core/app/plugin/type'; import { MongoSystemPlugin } from './systemPluginSchema'; import { PluginErrEnum } from '@fastgpt/global/common/error/code/plugin'; -import { Types } from 'mongoose'; +import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants'; +import { + FlowNodeTemplateTypeEnum, + NodeInputKeyEnum +} from '@fastgpt/global/core/workflow/constants'; +import { getNanoid } from '@fastgpt/global/common/string/tools'; +import { getSystemToolList } from '../tool/api'; +import { Types } from '../../../common/mongo'; +import type { SystemPluginConfigSchemaType } from './type'; +import type { + FlowNodeInputItemType, + FlowNodeOutputItemType +} from '@fastgpt/global/core/workflow/type/io'; +import { isProduction } from '@fastgpt/global/common/system/constants'; -/* +/** plugin id rule: - personal: id - community: community-id - commercial: commercial-id + - personal: ObjectId + - commercial: commercial-ObjectId + - systemtool: systemTool-id + (deprecated) community: community-id */ -export function splitCombineToolId(id: string) { +export function splitCombinePluginId(id: string) { const splitRes = id.split('-'); if (splitRes.length === 1) { // app id @@ -40,92 +51,116 @@ export function splitCombineToolId(id: string) { }; } - const [source, pluginId] = id.split('-') as [PluginSourceEnum, string]; + const [source, pluginId] = id.split('-') as [PluginSourceEnum, string | undefined]; if (!source || !pluginId) throw new Error('pluginId not found'); + // 兼容4.10.0 之前的插件 + if (source === 'community' || id === 'commercial-dalle3') { + return { + source: PluginSourceEnum.systemTool, + pluginId: `${PluginSourceEnum.systemTool}-${pluginId}` + }; + } + return { source, pluginId: id }; } -type ChildAppType = SystemPluginTemplateItemType & { teamId?: string; tmbId?: string }; +type ChildAppType = SystemPluginTemplateItemType & { + teamId?: string; + tmbId?: string; + workflow?: WorkflowTemplateBasicType; + versionLabel?: string; // Auto computed + isLatestVersion?: boolean; // Auto computed +}; -const getSystemPluginTemplateById = async ( +export const getSystemPluginByIdAndVersionId = async ( pluginId: string, versionId?: string ): Promise => { - const item = getSystemPluginTemplates().find((plugin) => plugin.id === pluginId); - if (!item) return Promise.reject(PluginErrEnum.unExist); + const plugin = await (async (): Promise => { + const plugin = await getSystemPluginById(pluginId); - const plugin = cloneDeep(item); + // Admin selected system tool + if (plugin.associatedPluginId) { + // The verification plugin is set as a system plugin + const systemPlugin = await MongoSystemPlugin.findOne( + { pluginId: plugin.id, 'customConfig.associatedPluginId': plugin.associatedPluginId }, + 'associatedPluginId' + ).lean(); + if (!systemPlugin) return Promise.reject(PluginErrEnum.unExist); - if (plugin.associatedPluginId) { - // The verification plugin is set as a system plugin - const systemPlugin = await MongoSystemPlugin.findOne( - { pluginId: plugin.id, 'customConfig.associatedPluginId': plugin.associatedPluginId }, - 'associatedPluginId' - ).lean(); - if (!systemPlugin) return Promise.reject(PluginErrEnum.unExist); + const app = await MongoApp.findById(plugin.associatedPluginId).lean(); + if (!app) return Promise.reject(PluginErrEnum.unExist); - const app = await MongoApp.findById(plugin.associatedPluginId).lean(); - if (!app) return Promise.reject(PluginErrEnum.unExist); + const version = versionId + ? await getAppVersionById({ + appId: plugin.associatedPluginId, + versionId, + app + }) + : await getAppLatestVersion(plugin.associatedPluginId, app); + if (!version.versionId) return Promise.reject('App version not found'); + const isLatest = version.versionId + ? await checkIsLatestVersion({ + appId: plugin.associatedPluginId, + versionId: version.versionId + }) + : true; + + return { + ...plugin, + workflow: { + nodes: version.nodes, + edges: version.edges, + chatConfig: version.chatConfig + }, + version: versionId ? version?.versionId : '', + versionLabel: version?.versionName, + isLatestVersion: isLatest, + teamId: String(app.teamId), + tmbId: String(app.tmbId) + }; + } const version = versionId - ? await getAppVersionById({ - appId: plugin.associatedPluginId, - versionId, - app - }) - : await getAppLatestVersion(plugin.associatedPluginId, app); - if (!version.versionId) return Promise.reject('App version not found'); - const isLatest = version.versionId - ? await checkIsLatestVersion({ - appId: plugin.associatedPluginId, - versionId: version.versionId - }) - : true; + ? plugin.versionList?.find((item) => item.value === versionId) + : plugin.versionList?.[0]; + const lastVersion = plugin.versionList?.[0]; return { ...plugin, - workflow: { - nodes: version.nodes, - edges: version.edges, - chatConfig: version.chatConfig - }, - version: versionId ? version?.versionId : '', - versionLabel: version?.versionName, - isLatestVersion: isLatest, - teamId: String(app.teamId), - tmbId: String(app.tmbId) + version: versionId ? version?.value : '', + versionLabel: version ? version?.value : '', + isLatestVersion: !version || !lastVersion || version.value === lastVersion?.value }; - } + })(); - return { - ...plugin, - version: undefined, - isLatestVersion: true - }; + return plugin; }; /* Format plugin to workflow preview node data */ export async function getChildAppPreviewNode({ appId, - versionId + versionId, + lang = 'en' }: { appId: string; versionId?: string; + lang?: localeType; }): Promise { - const app: ChildAppType = await (async () => { - const { source, pluginId } = splitCombineToolId(appId); + const { source, pluginId } = splitCombinePluginId(appId); + const app: ChildAppType = await (async () => { if (source === PluginSourceEnum.personal) { - const item = await MongoApp.findById(appId).lean(); + const item = await MongoApp.findById(pluginId).lean(); if (!item) return Promise.reject(PluginErrEnum.unExist); - const version = await getAppVersionById({ appId, versionId, app: item }); + const version = await getAppVersionById({ appId: pluginId, versionId, app: item }); const isLatest = version.versionId && Types.ObjectId.isValid(version.versionId) ? await checkIsLatestVersion({ - appId, + appId: pluginId, versionId: version.versionId }) : true; @@ -154,38 +189,53 @@ export async function getChildAppPreviewNode({ pluginOrder: 0 }; } else { - return getSystemPluginTemplateById(pluginId, versionId); + return getSystemPluginByIdAndVersionId(pluginId, versionId); } })(); - const isPlugin = !!app.workflow.nodes.find( - (node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput - ); - - const isTool = - !!app.workflow.nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.tool) && - app.workflow.nodes.length === 1; - - const isToolSet = - !!app.workflow.nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.toolSet) && - app.workflow.nodes.length === 1; - - const { flowNodeType, nodeIOConfig } = (() => { - if (isToolSet) - return { - flowNodeType: FlowNodeTypeEnum.toolSet, - nodeIOConfig: toolSetData2FlowNodeIO({ nodes: app.workflow.nodes }) - }; - if (isTool) + const { flowNodeType, nodeIOConfig } = await (async () => { + if (source === PluginSourceEnum.systemTool) { return { flowNodeType: FlowNodeTypeEnum.tool, - nodeIOConfig: toolData2FlowNodeIO({ nodes: app.workflow.nodes }) + nodeIOConfig: { + inputs: app.inputs!, + outputs: app.outputs!, + toolConfig: { + systemTool: { + toolId: app.id + } + } + } }; - if (isPlugin) + } + + if (!!app.workflow.nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput)) { return { flowNodeType: FlowNodeTypeEnum.pluginModule, nodeIOConfig: pluginData2FlowNodeIO({ nodes: app.workflow.nodes }) }; + } + + if ( + !!app.workflow.nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.toolSet) && + app.workflow.nodes.length === 1 + ) { + return { + flowNodeType: FlowNodeTypeEnum.toolSet, + nodeIOConfig: toolSetData2FlowNodeIO({ nodes: app.workflow.nodes }) + }; + } + + if ( + !!app.workflow.nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.tool) && + app.workflow.nodes.length === 1 + ) { + return { + flowNodeType: FlowNodeTypeEnum.tool, + nodeIOConfig: toolData2FlowNodeIO({ nodes: app.workflow.nodes }) + }; + } + return { flowNodeType: FlowNodeTypeEnum.appModule, nodeIOConfig: appData2FlowNodeIO({ chatConfig: app.workflow.chatConfig }) @@ -198,45 +248,46 @@ export async function getChildAppPreviewNode({ templateType: app.templateType, flowNodeType, avatar: app.avatar, - name: app.name, - intro: app.intro, + name: parseI18nString(app.name, lang), + intro: parseI18nString(app.intro, lang), courseUrl: app.courseUrl, userGuide: app.userGuide, - showStatus: app.showStatus, + showStatus: true, isTool: true, version: app.version, versionLabel: app.versionLabel, isLatestVersion: app.isLatestVersion, + showSourceHandle: true, + showTargetHandle: true, + + currentCost: app.currentCost, + hasTokenFee: app.hasTokenFee, + hasSystemSecret: app.hasSystemSecret, - sourceHandle: isToolSet - ? getHandleConfig(false, false, false, false) - : getHandleConfig(true, true, true, true), - targetHandle: isToolSet - ? getHandleConfig(false, false, false, false) - : getHandleConfig(true, true, true, true), ...nodeIOConfig }; } -/* +/** Get runtime plugin data System plugin: plugin id Personal plugin: Version id */ export async function getChildAppRuntimeById( id: string, - versionId?: string + versionId?: string, + lang: localeType = 'en' ): Promise { const app = await (async () => { - const { source, pluginId } = splitCombineToolId(id); + const { source, pluginId } = splitCombinePluginId(id); if (source === PluginSourceEnum.personal) { - const item = await MongoApp.findById(id).lean(); + const item = await MongoApp.findById(pluginId).lean(); if (!item) return Promise.reject(PluginErrEnum.unExist); const version = await getAppVersionById({ - appId: id, + appId: pluginId, versionId, app: item }); @@ -262,8 +313,7 @@ export async function getChildAppRuntimeById( pluginOrder: 0 }; } else { - // System - return getSystemPluginTemplateById(pluginId, versionId); + return getSystemPluginByIdAndVersionId(pluginId, versionId); } })(); @@ -271,12 +321,171 @@ export async function getChildAppRuntimeById( id: app.id, teamId: app.teamId, tmbId: app.tmbId, - name: app.name, - avatar: app.avatar, - showStatus: app.showStatus, + name: parseI18nString(app.name, lang), + avatar: app.avatar || '', + showStatus: true, currentCost: app.currentCost, nodes: app.workflow.nodes, edges: app.workflow.edges, hasTokenFee: app.hasTokenFee }; } + +const dbPluginFormat = (item: SystemPluginConfigSchemaType): SystemPluginTemplateItemType => { + const { name, avatar, intro, version, weight, templateType, associatedPluginId, userGuide } = + item.customConfig!; + + return { + id: item.pluginId, + isActive: item.isActive, + isFolder: false, + parentId: null, + author: item.customConfig?.author || '', + version, + name, + avatar, + intro, + weight, + templateType, + originCost: item.originCost, + currentCost: item.currentCost, + hasTokenFee: item.hasTokenFee, + pluginOrder: item.pluginOrder, + associatedPluginId, + userGuide, + workflow: { + nodes: [], + edges: [] + } + }; +}; + +/* FastsGPT-Pluign api: */ +function getCachedSystemPlugins() { + if (!global.systemPlugins_cache) { + global.systemPlugins_cache = { + expires: 0, + data: [] as SystemPluginTemplateItemType[] + }; + } + return global.systemPlugins_cache; +} + +const cleanSystemPluginCache = () => { + global.systemPlugins_cache = undefined; +}; + +export const refetchSystemPlugins = () => { + const changeStream = MongoSystemPlugin.watch(); + + changeStream.on('change', () => { + try { + cleanSystemPluginCache(); + } catch (error) {} + }); +}; + +export const getSystemPlugins = async (): Promise => { + if (getCachedSystemPlugins().expires > Date.now() && isProduction) { + return getCachedSystemPlugins().data; + } else { + const tools = await getSystemToolList(); + + // 从数据库里加载插件配置进行替换 + const systemPluginsArray = await MongoSystemPlugin.find({}).lean(); + const systemPlugins = new Map(systemPluginsArray.map((plugin) => [plugin.pluginId, plugin])); + + tools.forEach((tool) => { + // 如果有插件的配置信息,则需要进行替换 + const dbPluginConfig = systemPlugins.get(tool.id); + + if (dbPluginConfig) { + const children = tools.filter((item) => item.parentId === tool.id); + const list = [tool, ...children]; + list.forEach((item) => { + item.isActive = dbPluginConfig.isActive ?? item.isActive ?? true; + item.originCost = dbPluginConfig.originCost ?? 0; + item.currentCost = dbPluginConfig.currentCost ?? 0; + item.hasTokenFee = dbPluginConfig.hasTokenFee ?? false; + item.pluginOrder = dbPluginConfig.pluginOrder ?? 0; + }); + } + }); + + const formatTools = tools.map((item) => { + const dbPluginConfig = systemPlugins.get(item.id); + const inputs = item.versionList[0]?.inputs as FlowNodeInputItemType[]; + const outputs = item.versionList[0]?.outputs as FlowNodeOutputItemType[]; + + return { + isActive: item.isActive, + id: item.id, + parentId: item.parentId, + isFolder: tools.some((tool) => tool.parentId === item.id), + name: item.name, + avatar: item.avatar, + intro: item.intro, + author: item.author, + courseUrl: item.courseUrl, + showStatus: true, + weight: item.weight, + templateType: item.templateType, + originCost: item.originCost, + currentCost: item.currentCost, + hasTokenFee: item.hasTokenFee, + pluginOrder: item.pluginOrder, + + workflow: { + nodes: [], + edges: [] + }, + versionList: item.versionList, + inputs, + outputs, + + inputList: inputs?.find((input) => input.key === NodeInputKeyEnum.systemInputConfig) + ?.inputList as any, + hasSystemSecret: !!dbPluginConfig?.inputListVal + }; + }); + + const dbPlugins = systemPluginsArray + .filter((item) => item.customConfig) + .map((item) => dbPluginFormat(item)); + + const plugins = [...formatTools, ...dbPlugins]; + plugins.sort((a, b) => (a.pluginOrder ?? 0) - (b.pluginOrder ?? 0)); + + global.systemPlugins_cache = { + expires: Date.now() + 30 * 60 * 1000, // 30 minutes + data: plugins + }; + + return plugins; + } +}; + +export const getSystemPluginById = async (id: string): Promise => { + const { source, pluginId } = splitCombinePluginId(id); + if (source === PluginSourceEnum.systemTool) { + const tools = await getSystemPlugins(); + const tool = tools.find((item) => item.id === pluginId); + if (tool) { + return tool; + } + return Promise.reject(PluginErrEnum.unExist); + } + + const dbPlugin = await MongoSystemPlugin.findOne({ pluginId }).lean(); + if (!dbPlugin) return Promise.reject(PluginErrEnum.unExist); + return dbPluginFormat(dbPlugin); +}; + +declare global { + var systemPlugins_cache: + | { + expires: number; + data: SystemPluginTemplateItemType[]; + } + | undefined; +} diff --git a/packages/service/core/app/plugin/systemPluginSchema.ts b/packages/service/core/app/plugin/systemPluginSchema.ts index 2bfb2136a..e45ab4f7b 100644 --- a/packages/service/core/app/plugin/systemPluginSchema.ts +++ b/packages/service/core/app/plugin/systemPluginSchema.ts @@ -12,10 +12,6 @@ const SystemPluginSchema = new Schema({ isActive: { type: Boolean }, - inputConfig: { - type: Array, - default: [] - }, originCost: { type: Number, default: 0 @@ -32,7 +28,11 @@ const SystemPluginSchema = new Schema({ type: Number, default: 0 }, - customConfig: Object + customConfig: Object, + inputListVal: Object, + + // @deprecated + inputConfig: Array }); SystemPluginSchema.index({ pluginId: 1 }); diff --git a/packages/service/core/app/plugin/type.d.ts b/packages/service/core/app/plugin/type.d.ts index 85bd1f58f..9f4600741 100644 --- a/packages/service/core/app/plugin/type.d.ts +++ b/packages/service/core/app/plugin/type.d.ts @@ -1,9 +1,6 @@ import { SystemPluginListItemType } from '@fastgpt/global/core/app/type'; import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants'; -import type { - SystemPluginTemplateItemType, - WorkflowTemplateBasicType -} from '@fastgpt/global/core/workflow/type'; +import type { WorkflowTemplateBasicType } from '@fastgpt/global/core/workflow/type'; export type SystemPluginConfigSchemaType = { pluginId: string; @@ -13,7 +10,6 @@ export type SystemPluginConfigSchemaType = { hasTokenFee: boolean; isActive: boolean; pluginOrder: number; - inputConfig?: SystemPluginTemplateItemType['inputConfig']; customConfig?: { name: string; @@ -21,12 +17,21 @@ export type SystemPluginConfigSchemaType = { intro?: string; version: string; weight?: number; - workflow: WorkflowTemplateBasicType; templateType: string; associatedPluginId: string; userGuide: string; author?: string; }; + inputListVal?: Record; + + // @deprecated + inputConfig?: { + // Render config input form. Find the corresponding node and replace the variable directly + key: string; + label: string; + description: string; + value?: string; + }[]; }; export type TGroupType = { diff --git a/packages/service/core/app/plugin/utils.ts b/packages/service/core/app/plugin/utils.ts index db4914d55..b813cf76e 100644 --- a/packages/service/core/app/plugin/utils.ts +++ b/packages/service/core/app/plugin/utils.ts @@ -1,7 +1,7 @@ import { type ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type'; -import { type PluginRuntimeType } from '@fastgpt/global/core/plugin/type'; -import { splitCombineToolId } from './controller'; -import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; +import { type PluginRuntimeType } from '@fastgpt/global/core/app/plugin/type'; +import { splitCombinePluginId } from './controller'; +import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants'; /* Plugin points calculation: @@ -20,7 +20,7 @@ export const computedPluginUsage = async ({ childrenUsage: ChatNodeUsageType[]; error?: boolean; }) => { - const { source } = splitCombineToolId(plugin.id); + const { source } = splitCombinePluginId(plugin.id); const childrenUsages = childrenUsage.reduce((sum, item) => sum + (item.totalPoints || 0), 0); if (source !== PluginSourceEnum.personal) { diff --git a/packages/service/core/app/tool/api.ts b/packages/service/core/app/tool/api.ts new file mode 100644 index 000000000..298dfbdd6 --- /dev/null +++ b/packages/service/core/app/tool/api.ts @@ -0,0 +1,51 @@ +import createClient, { type SystemVarType } from '@fastgpt-sdk/plugin'; +import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants'; + +const client = createClient({ + baseUrl: process.env.PLUGIN_BASE_URL || '', + token: process.env.PLUGIN_TOKEN || '' +}); + +export async function getSystemToolList() { + const res = await client.tool.list(); + + if (res.status === 200) { + return res.body.map((item) => { + return { + ...item, + id: `${PluginSourceEnum.systemTool}-${item.id}`, + parentId: item.parentId ? `${PluginSourceEnum.systemTool}-${item.parentId}` : undefined, + avatar: + item.avatar && item.avatar.startsWith('/imgs/tools/') + ? `/api/system/pluginImgs/${item.avatar.replace('/imgs/tools/', '')}` + : item.avatar + }; + }); + } + + return Promise.reject(res.body); +} + +export async function runTool({ + toolId, + inputs, + systemVar +}: { + toolId: string; + inputs: Record; + systemVar: SystemVarType; +}) { + const res = await client.tool.run({ + body: { + toolId, + inputs, + systemVar + } + }); + + if (res.status === 200 && res.body.output) { + return res.body.output; + } else { + return Promise.reject(res.body); + } +} diff --git a/packages/service/core/app/utils.ts b/packages/service/core/app/utils.ts index 89d055e02..1cf2d6db5 100644 --- a/packages/service/core/app/utils.ts +++ b/packages/service/core/app/utils.ts @@ -3,8 +3,8 @@ import { getEmbeddingModel } from '../ai/model'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import type { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node'; -import { getChildAppPreviewNode, splitCombineToolId } from './plugin/controller'; -import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; +import { getChildAppPreviewNode, splitCombinePluginId } from './plugin/controller'; +import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants'; import { authAppByTmbId } from '../../support/permission/app/auth'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { getErrText } from '@fastgpt/global/common/error/utils'; @@ -46,19 +46,19 @@ export async function rewriteAppWorkflowToDetail({ await Promise.all( nodes.map(async (node) => { if (!node.pluginId) return; - const { source } = splitCombineToolId(node.pluginId); + const { source, pluginId } = splitCombinePluginId(node.pluginId); try { const [preview] = await Promise.all([ getChildAppPreviewNode({ - appId: node.pluginId, + appId: pluginId, versionId: node.version }), ...(source === PluginSourceEnum.personal ? [ authAppByTmbId({ tmbId: ownerTmbId, - appId: node.pluginId, + appId: pluginId, per: ReadPermissionVal }) ] @@ -75,6 +75,10 @@ export async function rewriteAppWorkflowToDetail({ node.versionLabel = preview.versionLabel; node.isLatestVersion = preview.isLatestVersion; node.version = preview.version; + + node.currentCost = preview.currentCost; + node.hasTokenFee = preview.hasTokenFee; + node.hasSystemSecret = preview.hasSystemSecret; } catch (error) { node.pluginData = { error: getErrText(error) diff --git a/packages/service/core/plugin/schema.ts b/packages/service/core/plugin/schema.ts deleted file mode 100644 index 37179ea11..000000000 --- a/packages/service/core/plugin/schema.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { pluginTypeMap } from '@fastgpt/global/core/plugin/constants'; -import { connectionMongo, type Model } from '../../common/mongo'; -const { Schema, model, models } = connectionMongo; -import type { PluginItemSchema } from '@fastgpt/global/core/plugin/type.d'; -import { - TeamCollectionName, - TeamMemberCollectionName -} from '@fastgpt/global/support/user/team/constant'; - -export const PluginCollectionName = 'plugins'; - -const PluginSchema = new Schema({ - parentId: { - type: Schema.Types.ObjectId, - ref: PluginCollectionName, - default: null - }, - teamId: { - type: Schema.Types.ObjectId, - ref: TeamCollectionName, - required: true - }, - tmbId: { - type: Schema.Types.ObjectId, - ref: TeamMemberCollectionName, - required: true - }, - type: { - type: String, - enum: Object.keys(pluginTypeMap), - required: true - }, - name: { - type: String, - required: true - }, - avatar: { - type: String, - default: '/icon/logo.svg' - }, - intro: { - type: String, - default: '' - }, - updateTime: { - type: Date, - default: () => new Date() - }, - modules: { - type: Array, - default: [] - }, - edges: { - type: Array, - default: [] - }, - metadata: { - type: { - pluginUid: String, - apiSchemaStr: String, - customHeaders: String - } - }, - version: { - type: String, - enum: ['v1', 'v2'] - }, - nodeVersion: { - type: String, - default: '' - }, - - inited: Boolean -}); - -try { - PluginSchema.index({ type: 1, init: 1 }); - PluginSchema.index({ teamId: 1, parentId: 1 }); - PluginSchema.index({ teamId: 1, name: 1, intro: 1 }); -} catch (error) { - console.log(error); -} - -export const MongoPlugin: Model = - models[PluginCollectionName] || model(PluginCollectionName, PluginSchema); -MongoPlugin.syncIndexes(); diff --git a/packages/service/core/plugin/type.d.ts b/packages/service/core/plugin/type.d.ts deleted file mode 100644 index a1dcab2db..000000000 --- a/packages/service/core/plugin/type.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { PluginTemplateType } from '@fastgpt/global/core/plugin/type.d'; -import type { SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type'; - -declare global { - var communityPlugins: SystemPluginTemplateItemType[]; -} diff --git a/packages/service/core/workflow/dispatch/agent/runTool/constants.ts b/packages/service/core/workflow/dispatch/ai/agent/constants.ts similarity index 100% rename from packages/service/core/workflow/dispatch/agent/runTool/constants.ts rename to packages/service/core/workflow/dispatch/ai/agent/constants.ts diff --git a/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts b/packages/service/core/workflow/dispatch/ai/agent/functionCall.ts similarity index 99% rename from packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts rename to packages/service/core/workflow/dispatch/ai/agent/functionCall.ts index 6b052ef17..553296ae7 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts +++ b/packages/service/core/workflow/dispatch/ai/agent/functionCall.ts @@ -19,11 +19,7 @@ import { getLLMDefaultUsage } from '@fastgpt/global/core/ai/constants'; import { dispatchWorkFlow } from '../../index'; -import { - type DispatchToolModuleProps, - type RunToolResponse, - type ToolNodeItemType -} from './type.d'; +import { type DispatchToolModuleProps, type RunToolResponse, type ToolNodeItemType } from './type'; import json5 from 'json5'; import { type DispatchFlowResponse, type WorkflowResponseType } from '../../type'; import { countGptMessagesTokens } from '../../../../../common/string/tiktoken/index'; diff --git a/packages/service/core/workflow/dispatch/agent/runTool/index.ts b/packages/service/core/workflow/dispatch/ai/agent/index.ts similarity index 99% rename from packages/service/core/workflow/dispatch/agent/runTool/index.ts rename to packages/service/core/workflow/dispatch/ai/agent/index.ts index 20941ab12..44b1e27b1 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/index.ts +++ b/packages/service/core/workflow/dispatch/ai/agent/index.ts @@ -8,7 +8,7 @@ import type { import { getLLMModel } from '../../../../ai/model'; import { filterToolNodeIdByEdges, getHistories } from '../../utils'; import { runToolWithToolChoice } from './toolChoice'; -import { type DispatchToolModuleProps, type ToolNodeItemType } from './type.d'; +import { type DispatchToolModuleProps, type ToolNodeItemType } from './type'; import { type ChatItemType, type UserChatItemValueItemType } from '@fastgpt/global/core/chat/type'; import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; import { diff --git a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts b/packages/service/core/workflow/dispatch/ai/agent/promptCall.ts similarity index 99% rename from packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts rename to packages/service/core/workflow/dispatch/ai/agent/promptCall.ts index a3c0d28de..5b0066e51 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts +++ b/packages/service/core/workflow/dispatch/ai/agent/promptCall.ts @@ -14,11 +14,7 @@ import { getLLMDefaultUsage } from '@fastgpt/global/core/ai/constants'; import { dispatchWorkFlow } from '../../index'; -import { - type DispatchToolModuleProps, - type RunToolResponse, - type ToolNodeItemType -} from './type.d'; +import { type DispatchToolModuleProps, type RunToolResponse, type ToolNodeItemType } from './type'; import json5 from 'json5'; import { countGptMessagesTokens } from '../../../../../common/string/tiktoken/index'; import { diff --git a/packages/service/core/workflow/dispatch/agent/runTool/stopTool.ts b/packages/service/core/workflow/dispatch/ai/agent/stopTool.ts similarity index 100% rename from packages/service/core/workflow/dispatch/agent/runTool/stopTool.ts rename to packages/service/core/workflow/dispatch/ai/agent/stopTool.ts diff --git a/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts b/packages/service/core/workflow/dispatch/ai/agent/toolChoice.ts similarity index 99% rename from packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts rename to packages/service/core/workflow/dispatch/ai/agent/toolChoice.ts index 2e52b1bac..846de59e8 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts +++ b/packages/service/core/workflow/dispatch/ai/agent/toolChoice.ts @@ -15,11 +15,7 @@ import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/cons import { textAdaptGptResponse } from '@fastgpt/global/core/workflow/runtime/utils'; import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/global/core/ai/constants'; import { dispatchWorkFlow } from '../../index'; -import { - type DispatchToolModuleProps, - type RunToolResponse, - type ToolNodeItemType -} from './type.d'; +import { type DispatchToolModuleProps, type RunToolResponse, type ToolNodeItemType } from './type'; import json5 from 'json5'; import { type DispatchFlowResponse, type WorkflowResponseType } from '../../type'; import { countGptMessagesTokens } from '../../../../../common/string/tiktoken/index'; diff --git a/packages/service/core/workflow/dispatch/agent/runTool/toolParams.ts b/packages/service/core/workflow/dispatch/ai/agent/toolParams.ts similarity index 100% rename from packages/service/core/workflow/dispatch/agent/runTool/toolParams.ts rename to packages/service/core/workflow/dispatch/ai/agent/toolParams.ts diff --git a/packages/service/core/workflow/dispatch/agent/runTool/type.d.ts b/packages/service/core/workflow/dispatch/ai/agent/type.d.ts similarity index 97% rename from packages/service/core/workflow/dispatch/agent/runTool/type.d.ts rename to packages/service/core/workflow/dispatch/ai/agent/type.d.ts index 89ffa95ec..68c452d93 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/type.d.ts +++ b/packages/service/core/workflow/dispatch/ai/agent/type.d.ts @@ -10,7 +10,7 @@ import type { } from '@fastgpt/global/core/workflow/runtime/type'; import type { RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type'; import { ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type'; -import type { DispatchFlowResponse } from '../../type.d'; +import type { DispatchFlowResponse } from '../../type'; import type { AIChatItemValueItemType } from '@fastgpt/global/core/chat/type'; import { ChatItemValueItemType } from '@fastgpt/global/core/chat/type'; import type { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants'; diff --git a/packages/service/core/workflow/dispatch/agent/runTool/utils.ts b/packages/service/core/workflow/dispatch/ai/agent/utils.ts similarity index 100% rename from packages/service/core/workflow/dispatch/agent/runTool/utils.ts rename to packages/service/core/workflow/dispatch/ai/agent/utils.ts diff --git a/packages/service/core/workflow/dispatch/chat/oneapi.ts b/packages/service/core/workflow/dispatch/ai/chat.ts similarity index 100% rename from packages/service/core/workflow/dispatch/chat/oneapi.ts rename to packages/service/core/workflow/dispatch/ai/chat.ts diff --git a/packages/service/core/workflow/dispatch/agent/classifyQuestion.ts b/packages/service/core/workflow/dispatch/ai/classifyQuestion.ts similarity index 100% rename from packages/service/core/workflow/dispatch/agent/classifyQuestion.ts rename to packages/service/core/workflow/dispatch/ai/classifyQuestion.ts diff --git a/packages/service/core/workflow/dispatch/agent/extract.ts b/packages/service/core/workflow/dispatch/ai/extract.ts similarity index 100% rename from packages/service/core/workflow/dispatch/agent/extract.ts rename to packages/service/core/workflow/dispatch/ai/extract.ts diff --git a/packages/service/core/workflow/dispatch/dataset/search.ts b/packages/service/core/workflow/dispatch/dataset/search.ts index 80addbd73..c012877d1 100644 --- a/packages/service/core/workflow/dispatch/dataset/search.ts +++ b/packages/service/core/workflow/dispatch/dataset/search.ts @@ -3,7 +3,7 @@ import { type DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type.d'; import { formatModelChars2Points } from '../../../../support/wallet/usage/utils'; -import type { SelectedDatasetType } from '@fastgpt/global/core/workflow/api.d'; +import type { SelectedDatasetType } from '@fastgpt/global/core/workflow/type/io'; import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type'; import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type'; import { getEmbeddingModel, getRerankModel } from '../../../ai/model'; diff --git a/packages/service/core/workflow/dispatch/index.ts b/packages/service/core/workflow/dispatch/index.ts index 05e892f8b..9e5217dba 100644 --- a/packages/service/core/workflow/dispatch/index.ts +++ b/packages/service/core/workflow/dispatch/index.ts @@ -1,9 +1,21 @@ +import { getNanoid } from '@fastgpt/global/common/string/tools'; +import { getSystemTime } from '@fastgpt/global/common/time/timezone'; +import type { + AIChatItemValueItemType, + ChatHistoryItemResType, + NodeOutputItemType, + ToolRunResponseItemType +} from '@fastgpt/global/core/chat/type.d'; +import type { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; +import { + FlowNodeInputTypeEnum, + FlowNodeTypeEnum +} from '@fastgpt/global/core/workflow/node/constant'; import { DispatchNodeResponseKeyEnum, SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants'; -import type { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import type { ChatDispatchProps, DispatchNodeResultType, @@ -11,71 +23,58 @@ import type { SystemVariablesType } from '@fastgpt/global/core/workflow/runtime/type'; import type { RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type.d'; -import type { - AIChatItemValueItemType, - ChatHistoryItemResType, - NodeOutputItemType, - ToolRunResponseItemType -} from '@fastgpt/global/core/chat/type.d'; -import { - FlowNodeInputTypeEnum, - FlowNodeTypeEnum -} from '@fastgpt/global/core/workflow/node/constant'; -import { getNanoid } from '@fastgpt/global/common/string/tools'; -import { getSystemTime } from '@fastgpt/global/common/time/timezone'; - -import { dispatchWorkflowStart } from './init/workflowStart'; -import { dispatchChatCompletion } from './chat/oneapi'; -import { dispatchDatasetSearch } from './dataset/search'; -import { dispatchDatasetConcat } from './dataset/concat'; -import { dispatchAnswer } from './tools/answer'; -import { dispatchClassifyQuestion } from './agent/classifyQuestion'; -import { dispatchContentExtract } from './agent/extract'; -import { dispatchHttp468Request } from './tools/http468'; -import { dispatchAppRequest } from './abandoned/runApp'; -import { dispatchQueryExtension } from './tools/queryExternsion'; -import { dispatchRunPlugin } from './plugin/run'; -import { dispatchPluginInput } from './plugin/runInput'; -import { dispatchPluginOutput } from './plugin/runOutput'; -import { formatHttpError, removeSystemVariable, rewriteRuntimeWorkFlow } from './utils'; -import { valueTypeFormat } from '@fastgpt/global/core/workflow/runtime/utils'; -import { - filterWorkflowEdges, - checkNodeRunStatus, - textAdaptGptResponse, - replaceEditorVariable -} from '@fastgpt/global/core/workflow/runtime/utils'; -import type { ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type'; -import { dispatchRunTools } from './agent/runTool/index'; +import { getErrText } from '@fastgpt/global/common/error/utils'; import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants'; -import type { DispatchFlowResponse } from './type'; -import { dispatchStopToolCall } from './agent/runTool/stopTool'; -import { dispatchLafRequest } from './tools/runLaf'; -import { dispatchIfElse } from './tools/runIfElse'; +import { filterPublicNodeResponseData } from '@fastgpt/global/core/chat/utils'; +import { + checkNodeRunStatus, + filterWorkflowEdges, + getReferenceVariableValue, + replaceEditorVariable, + textAdaptGptResponse, + valueTypeFormat +} from '@fastgpt/global/core/workflow/runtime/utils'; +import type { + InteractiveNodeResponseType, + WorkflowInteractiveResponseType +} from '@fastgpt/global/core/workflow/template/system/interactive/type'; import type { RuntimeEdgeItemType } from '@fastgpt/global/core/workflow/type/edge'; -import { getReferenceVariableValue } from '@fastgpt/global/core/workflow/runtime/utils'; -import { dispatchSystemConfig } from './init/systemConfig'; -import { dispatchUpdateVariable } from './tools/runUpdateVar'; +import type { ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type'; import { addLog } from '../../../common/system/log'; import { surrenderProcess } from '../../../common/system/tools'; +import { dispatchAppRequest } from './abandoned/runApp'; +import { dispatchClassifyQuestion } from './ai/classifyQuestion'; +import { dispatchContentExtract } from './ai/extract'; +import { dispatchRunTools } from './ai/agent/index'; +import { dispatchStopToolCall } from './ai/agent/stopTool'; +import { dispatchToolParams } from './ai/agent/toolParams'; +import { dispatchChatCompletion } from './ai/chat'; import { dispatchRunCode } from './code/run'; -import { dispatchTextEditor } from './tools/textEditor'; -import { dispatchCustomFeedback } from './tools/customFeedback'; -import { dispatchReadFiles } from './tools/readFiles'; +import { dispatchDatasetConcat } from './dataset/concat'; +import { dispatchDatasetSearch } from './dataset/search'; +import { dispatchSystemConfig } from './init/systemConfig'; +import { dispatchWorkflowStart } from './init/workflowStart'; +import { dispatchFormInput } from './interactive/formInput'; import { dispatchUserSelect } from './interactive/userSelect'; -import type { - WorkflowInteractiveResponseType, - InteractiveNodeResponseType -} from '@fastgpt/global/core/workflow/template/system/interactive/type'; -import { dispatchRunAppNode } from './plugin/runApp'; import { dispatchLoop } from './loop/runLoop'; import { dispatchLoopEnd } from './loop/runLoopEnd'; import { dispatchLoopStart } from './loop/runLoopStart'; -import { dispatchFormInput } from './interactive/formInput'; -import { dispatchToolParams } from './agent/runTool/toolParams'; -import { getErrText } from '@fastgpt/global/common/error/utils'; -import { filterPublicNodeResponseData } from '@fastgpt/global/core/chat/utils'; +import { dispatchRunPlugin } from './plugin/run'; +import { dispatchRunAppNode } from './plugin/runApp'; +import { dispatchPluginInput } from './plugin/runInput'; +import { dispatchPluginOutput } from './plugin/runOutput'; import { dispatchRunTool } from './plugin/runTool'; +import { dispatchAnswer } from './tools/answer'; +import { dispatchCustomFeedback } from './tools/customFeedback'; +import { dispatchHttp468Request } from './tools/http468'; +import { dispatchQueryExtension } from './tools/queryExternsion'; +import { dispatchReadFiles } from './tools/readFiles'; +import { dispatchIfElse } from './tools/runIfElse'; +import { dispatchLafRequest } from './tools/runLaf'; +import { dispatchUpdateVariable } from './tools/runUpdateVar'; +import { dispatchTextEditor } from './tools/textEditor'; +import type { DispatchFlowResponse } from './type'; +import { formatHttpError, removeSystemVariable, rewriteRuntimeWorkFlow } from './utils'; const callbackMap: Record = { [FlowNodeTypeEnum.workflowStart]: dispatchWorkflowStart, @@ -91,7 +90,7 @@ const callbackMap: Record = { [FlowNodeTypeEnum.pluginInput]: dispatchPluginInput, [FlowNodeTypeEnum.pluginOutput]: dispatchPluginOutput, [FlowNodeTypeEnum.queryExtension]: dispatchQueryExtension, - [FlowNodeTypeEnum.tools]: dispatchRunTools, + [FlowNodeTypeEnum.agent]: dispatchRunTools, [FlowNodeTypeEnum.stopTool]: dispatchStopToolCall, [FlowNodeTypeEnum.toolParams]: dispatchToolParams, [FlowNodeTypeEnum.lafModule]: dispatchLafRequest, @@ -116,7 +115,8 @@ const callbackMap: Record = { [FlowNodeTypeEnum.comment]: () => Promise.resolve(), [FlowNodeTypeEnum.toolSet]: () => Promise.resolve(), - [FlowNodeTypeEnum.runApp]: dispatchAppRequest // abandoned + // @deprecated + [FlowNodeTypeEnum.runApp]: dispatchAppRequest }; type Props = ChatDispatchProps & { @@ -460,7 +460,7 @@ export async function dispatchWorkFlow(data: Props): Promise; +type SystemInputConfigType = { + type: SystemToolInputTypeEnum; + value: StoreSecretValueType; +}; -type RunToolResponse = DispatchNodeResultType<{ - [NodeOutputKeyEnum.rawResponse]?: any; -}>; +type RunToolProps = ModuleDispatchProps< + { + [NodeInputKeyEnum.toolData]?: McpToolDataType; + [NodeInputKeyEnum.systemInputConfig]?: SystemInputConfigType; + } & Record +>; + +type RunToolResponse = DispatchNodeResultType< + { + [NodeOutputKeyEnum.rawResponse]?: any; + } & Record +>; export const dispatchRunTool = async (props: RunToolProps): Promise => { const { params, - node: { avatar } + runningUserInfo, + runningAppInfo, + variables, + node: { name, avatar, toolConfig, version } } = props; - const { toolData, system_toolData, ...restParams } = params; - const { name: toolName, url, headerSecret } = toolData || system_toolData; - - const mcpClient = new MCPClient({ - url, - headers: getSecretValue({ - storeSecret: headerSecret - }) - }); - try { - const result = await mcpClient.toolCall(toolName, restParams); + // run system tool + if (toolConfig?.systemTool?.toolId) { + const tool = await getSystemPluginById(toolConfig.systemTool!.toolId); - return { - [DispatchNodeResponseKeyEnum.nodeResponse]: { - toolRes: result, - moduleLogo: avatar - }, - [DispatchNodeResponseKeyEnum.toolResponses]: result, - [NodeOutputKeyEnum.rawResponse]: result - }; + const inputConfigParams = await (async () => { + switch (params.system_input_config?.type) { + case SystemToolInputTypeEnum.team: + return Promise.reject(new Error('This is not supported yet')); + case SystemToolInputTypeEnum.manual: + const val = params.system_input_config.value || {}; + return getSecretValue({ + storeSecret: val + }); + case SystemToolInputTypeEnum.system: + default: + // read from mongo + const dbPlugin = await MongoSystemPlugin.findOne({ + pluginId: toolConfig.systemTool?.toolId + }).lean(); + return dbPlugin?.inputListVal || {}; + } + })(); + const inputs = { + ...Object.fromEntries( + Object.entries(params).filter(([key]) => key !== NodeInputKeyEnum.systemInputConfig) + ), + ...inputConfigParams + }; + + const formatToolId = tool.id.split('-')[1]; + const result = await runTool({ + toolId: formatToolId, + inputs, + systemVar: { + user: { + id: variables.userId, + teamId: runningUserInfo.teamId, + name: runningUserInfo.tmbId + }, + app: { + id: runningAppInfo.id, + name: runningAppInfo.id + }, + tool: { + id: formatToolId, + version + }, + time: variables.cTime + } + }); + + const usagePoints = await (async () => { + if ( + params.system_input_config?.type !== SystemToolInputTypeEnum.system || + result[NodeOutputKeyEnum.systemError] + ) { + return 0; + } + return tool.currentCost ?? 0; + })(); + + return { + [DispatchNodeResponseKeyEnum.nodeResponse]: { + toolRes: result, + moduleLogo: avatar, + totalPoints: usagePoints + }, + [DispatchNodeResponseKeyEnum.toolResponses]: result, + [DispatchNodeResponseKeyEnum.nodeDispatchUsages]: [ + { + moduleName: name, + totalPoints: usagePoints + } + ], + ...result + }; + } else { + // mcp tool + const { toolData, system_toolData, ...restParams } = params; + const { name: toolName, url, headerSecret } = toolData || system_toolData; + + const mcpClient = new MCPClient({ + url, + headers: getSecretValue({ + storeSecret: headerSecret + }) + }); + const result = await mcpClient.toolCall(toolName, restParams); + + return { + [DispatchNodeResponseKeyEnum.nodeResponse]: { + toolRes: result, + moduleLogo: avatar + }, + [DispatchNodeResponseKeyEnum.toolResponses]: result, + [NodeOutputKeyEnum.rawResponse]: result + }; + } } catch (error) { return { [DispatchNodeResponseKeyEnum.nodeResponse]: { diff --git a/packages/service/core/workflow/dispatch/tools/http468.ts b/packages/service/core/workflow/dispatch/tools/http468.ts index e7ce4dc4c..4a67b4b49 100644 --- a/packages/service/core/workflow/dispatch/tools/http468.ts +++ b/packages/service/core/workflow/dispatch/tools/http468.ts @@ -1,5 +1,6 @@ -import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type'; +import { getErrText } from '@fastgpt/global/common/error/utils'; import { + ContentTypes, NodeInputKeyEnum, NodeOutputKeyEnum, VARIABLE_NODE_ID, @@ -10,27 +11,22 @@ import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants'; import axios from 'axios'; -import { formatHttpError } from '../utils'; import { valueTypeFormat } from '@fastgpt/global/core/workflow/runtime/utils'; -import { SERVICE_LOCAL_HOST } from '../../../../common/system/tools'; -import { addLog } from '../../../../common/system/log'; import { type DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type'; -import { getErrText } from '@fastgpt/global/common/error/utils'; +import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type'; import { - textAdaptGptResponse, - replaceEditorVariable, formatVariableValByType, - getReferenceVariableValue + getReferenceVariableValue, + replaceEditorVariable, + textAdaptGptResponse } from '@fastgpt/global/core/workflow/runtime/utils'; -import { ContentTypes } from '@fastgpt/global/core/workflow/constants'; -import { uploadFileFromBase64Img } from '../../../../common/file/gridfs/controller'; -import { ReadFileBaseUrl } from '@fastgpt/global/common/file/constants'; -import { createFileToken } from '../../../../support/permission/controller'; -import { JSONPath } from 'jsonpath-plus'; -import type { SystemPluginSpecialResponse } from '../../../../../plugins/type'; import json5 from 'json5'; +import { JSONPath } from 'jsonpath-plus'; import { getSecretValue } from '../../../../common/secret/utils'; import type { StoreSecretValueType } from '@fastgpt/global/common/secret/type'; +import { addLog } from '../../../../common/system/log'; +import { SERVICE_LOCAL_HOST } from '../../../../common/system/tools'; +import { formatHttpError } from '../utils'; type PropsArrType = { key: string; @@ -302,19 +298,6 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise { - const systemPluginCb = global.systemPluginCb; - if (systemPluginCb[httpReqUrl]) { - const pluginResult = await replaceSystemPluginResponse({ - response: await systemPluginCb[httpReqUrl](requestBody), - teamId, - tmbId - }); - - return { - formatResponse: pluginResult, - rawResponse: pluginResult - }; - } return fetchData({ method: httpMethod, url: httpReqUrl, @@ -426,38 +409,3 @@ async function fetchData({ rawResponse: response }; } - -// Replace some special response from system plugin -async function replaceSystemPluginResponse({ - response, - teamId, - tmbId -}: { - response: Record; - teamId: string; - tmbId: string; -}) { - for await (const key of Object.keys(response)) { - if (typeof response[key] === 'object' && response[key].type === 'SYSTEM_PLUGIN_BASE64') { - const fileObj = response[key] as SystemPluginSpecialResponse; - const filename = `${tmbId}-${Date.now()}.${fileObj.extension}`; - try { - const fileId = await uploadFileFromBase64Img({ - teamId, - tmbId, - bucketName: 'chat', - base64: fileObj.value, - filename, - metadata: {} - }); - response[key] = `${ReadFileBaseUrl}/${filename}?token=${await createFileToken({ - bucketName: 'chat', - teamId, - uid: tmbId, - fileId - })}`; - } catch (error) {} - } - } - return response; -} diff --git a/packages/service/package.json b/packages/service/package.json index 1cc6f5472..c71e6f700 100644 --- a/packages/service/package.json +++ b/packages/service/package.json @@ -1,7 +1,9 @@ { "name": "@fastgpt/service", "version": "1.0.0", + "type": "module", "dependencies": { + "@fastgpt-sdk/plugin": "^0.1.0", "@fastgpt/global": "workspace:*", "@modelcontextprotocol/sdk": "^1.12.1", "@node-rs/jieba": "2.0.1", diff --git a/packages/service/support/permission/app/auth.ts b/packages/service/support/permission/app/auth.ts index 8f0bd1332..f60cb8e0b 100644 --- a/packages/service/support/permission/app/auth.ts +++ b/packages/service/support/permission/app/auth.ts @@ -10,8 +10,8 @@ import { AppPermission } from '@fastgpt/global/support/permission/app/controller import { type PermissionValueType } from '@fastgpt/global/support/permission/type'; import { AppFolderTypeList } from '@fastgpt/global/core/app/constants'; import { type ParentIdType } from '@fastgpt/global/common/parentFolder/type'; -import { splitCombineToolId } from '../../../core/app/plugin/controller'; -import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; +import { splitCombinePluginId } from '../../../core/app/plugin/controller'; +import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants'; import { type AuthModeType, type AuthResponseType } from '../type'; import { AppDefaultPermissionVal } from '@fastgpt/global/support/permission/app/constant'; @@ -24,7 +24,7 @@ export const authPluginByTmbId = async ({ appId: string; per: PermissionValueType; }) => { - const { source } = splitCombineToolId(appId); + const { source } = splitCombinePluginId(appId); if (source === PluginSourceEnum.personal) { const { app } = await authAppByTmbId({ appId, @@ -34,8 +34,6 @@ export const authPluginByTmbId = async ({ return app; } - - // commercial custom plugin already checked in "getSystemPluginTemplateById" }; export const authAppByTmbId = async ({ diff --git a/packages/service/worker/utils.ts b/packages/service/worker/utils.ts index 83bde7e38..1a2a35f53 100644 --- a/packages/service/worker/utils.ts +++ b/packages/service/worker/utils.ts @@ -21,7 +21,7 @@ export const getSafeEnv = () => { }; }; -export const getWorker = (name: WorkerNameEnum) => { +export const getWorker = (name: `${WorkerNameEnum}`) => { const workerPath = path.join(process.cwd(), '.next', 'server', 'worker', `${name}.js`); return new Worker(workerPath, { env: getSafeEnv() @@ -73,7 +73,7 @@ type WorkerResponse = { data: T; }; -/* +/* 多线程任务管理 * 全局只需要创建一个示例 * 可以设置最大常驻线程(不会被销毁),线程满了后,后续任务会等待执行。 @@ -133,7 +133,7 @@ export class WorkerPool, Response = any> { // addLog.debug(`${this.name} worker queueLength: ${this.workerQueue.length}`); return new Promise((resolve, reject) => { - /* + /* Whether the task is executed immediately or delayed, the promise callback will dispatch after task complete. */ this.runTask({ diff --git a/packages/templates/register.ts b/packages/templates/register.ts index a828e2e20..0c6b22310 100644 --- a/packages/templates/register.ts +++ b/packages/templates/register.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; import { isProduction } from '@fastgpt/global/common/system/constants'; -import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; +import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants'; import { MongoAppTemplate } from '@fastgpt/service/core/app/templates/templateSchema'; import { type AppTemplateSchemaType } from '@fastgpt/global/core/app/type'; diff --git a/packages/web/components/common/Input/NumberInput/index.tsx b/packages/web/components/common/Input/NumberInput/index.tsx index 74810c779..12e139585 100644 --- a/packages/web/components/common/Input/NumberInput/index.tsx +++ b/packages/web/components/common/Input/NumberInput/index.tsx @@ -36,6 +36,14 @@ const MyNumberInput = (props: Props) => { onBlur(numE); } } + if (onChange) { + if (numE === '') { + // @ts-ignore + onChange(''); + } else { + onChange(numE); + } + } if (register && name) { const event = { target: { @@ -47,12 +55,13 @@ const MyNumberInput = (props: Props) => { } }} onChange={(e) => { - const numE = e === '' ? '' : Number(e); + const numE = e === '' ? '' : e.endsWith('.') ? e : Number(e); if (onChange) { if (numE === '') { // @ts-ignore onChange(''); } else { + // @ts-ignore onChange(numE); } } diff --git a/packages/web/components/common/Radio/LeftRadio.tsx b/packages/web/components/common/Radio/LeftRadio.tsx index 9e244ba4c..95b19e0ea 100644 --- a/packages/web/components/common/Radio/LeftRadio.tsx +++ b/packages/web/components/common/Radio/LeftRadio.tsx @@ -5,7 +5,7 @@ import QuestionTip from '../MyTooltip/QuestionTip'; type Props = Omit & { list: { - title: string; + title: string | React.ReactNode; desc?: string; value: T; children?: React.ReactNode; @@ -22,7 +22,7 @@ const LeftRadio = ({ list, value, align = 'flex-top', - px = 3, + px = 3.5, py = 4, defaultBg = 'myGray.50', activeBg = 'primary.50', @@ -35,22 +35,21 @@ const LeftRadio = ({ return ( {list.map((item) => ( - 1 ? 'primary.400' : '', bg: activeBg, - boxShadow: 'focus' + boxShadow: list.length > 1 ? 'focus' : 'none' } : { bg: defaultBg, @@ -60,53 +59,66 @@ const LeftRadio = ({ })} onClick={() => onChange(item.value)} > - - + {/* Circle */} + + {list.length > 1 && ( - - - - - - {typeof item.title === 'string' ? t(item.title as any) : item.title} - {!!item.tooltip && } - - - {!!item.desc && ( - - {t(item.desc as any)} + + + )} - {item?.children} - - + + {typeof item.title === 'string' ? ( + + {t(item.title as any)} + {!!item.tooltip && } + + ) : ( + item.title + )} + + {!!item.desc && ( + + {t(item.desc as any)} + + )} + + + {item?.children && ( + + {item?.children} + + )} + ))} ); diff --git a/packages/web/core/workflow/constants.ts b/packages/web/core/workflow/constants.ts index fff236512..d727b880a 100644 --- a/packages/web/core/workflow/constants.ts +++ b/packages/web/core/workflow/constants.ts @@ -4,76 +4,85 @@ import type { PluginGroupSchemaType, TGroupType } from '../../../service/core/ap import { AppTemplateTypeEnum } from '@fastgpt/global/core/app/constants'; import { type TemplateTypeSchemaType } from '@fastgpt/global/core/app/type'; -export const workflowNodeTemplateList = [ - { - type: FlowNodeTemplateTypeEnum.systemInput, - label: i18nT('common:core.module.template.System input module'), - list: [] - }, - { - type: FlowNodeTemplateTypeEnum.ai, - label: i18nT('common:core.module.template.AI function'), - list: [] - }, - { - type: FlowNodeTemplateTypeEnum.search, - label: i18nT('common:core.workflow.template.Search'), - list: [] - }, - { - type: FlowNodeTemplateTypeEnum.interactive, - label: i18nT('common:core.workflow.template.Interactive'), - list: [] - }, - { - type: FlowNodeTemplateTypeEnum.multimodal, - label: i18nT('common:core.workflow.template.Multimodal'), - list: [] - }, - { - type: FlowNodeTemplateTypeEnum.tools, - label: i18nT('common:core.module.template.Tool module'), - list: [] - }, - { - type: FlowNodeTemplateTypeEnum.communication, - label: i18nT('common:workflow.template.communication'), - list: [] - }, - { - type: FlowNodeTemplateTypeEnum.other, - label: i18nT('common:Other'), - list: [] - }, - { - type: FlowNodeTemplateTypeEnum.teamApp, - label: '', - list: [] - } -]; - export const systemPluginTemplateList: TGroupType[] = [ { typeId: FlowNodeTemplateTypeEnum.tools, - typeName: i18nT('common:navbar.Tools') - }, - { - typeId: FlowNodeTemplateTypeEnum.search, - typeName: i18nT('common:Search') + typeName: i18nT('app:tool_type_tools') }, { typeId: FlowNodeTemplateTypeEnum.multimodal, - typeName: i18nT('common:core.workflow.template.Multimodal') + typeName: i18nT('app:tool_type_multimodal') + }, + { + typeId: FlowNodeTemplateTypeEnum.productivity, + typeName: i18nT('app:tool_type_productivity') + }, + { + typeId: FlowNodeTemplateTypeEnum.scientific, + typeName: i18nT('app:tool_type_scientific') + }, + { + typeId: FlowNodeTemplateTypeEnum.finance, + typeName: i18nT('app:tool_type_finance') + }, + { + typeId: FlowNodeTemplateTypeEnum.design, + typeName: i18nT('app:tool_type_design') + }, + { + typeId: FlowNodeTemplateTypeEnum.news, + typeName: i18nT('app:tool_type_news') + }, + { + typeId: FlowNodeTemplateTypeEnum.entertainment, + typeName: i18nT('app:tool_type_entertainment') }, { typeId: FlowNodeTemplateTypeEnum.communication, - typeName: i18nT('common:workflow.template.communication') + typeName: i18nT('app:tool_type_communication') + }, + { + typeId: FlowNodeTemplateTypeEnum.social, + typeName: i18nT('app:tool_type_social') }, { typeId: FlowNodeTemplateTypeEnum.other, typeName: i18nT('common:Other') } ]; + +export const workflowNodeTemplateList: { + type: string; + label: string; +}[] = [ + { + type: FlowNodeTemplateTypeEnum.systemInput, + label: i18nT('common:core.module.template.System input module') + }, + { + type: FlowNodeTemplateTypeEnum.ai, + label: i18nT('common:core.module.template.AI function') + }, + { + type: FlowNodeTemplateTypeEnum.search, + label: i18nT('common:core.workflow.template.Search') + }, + { + type: FlowNodeTemplateTypeEnum.interactive, + label: i18nT('common:core.workflow.template.Interactive') + }, + + ...systemPluginTemplateList.map((item) => ({ + type: item.typeId, + label: item.typeName + })), + + { + type: FlowNodeTemplateTypeEnum.teamApp, + label: '' + } +]; + export const defaultGroup: PluginGroupSchemaType = { groupId: 'systemPlugin', groupAvatar: 'core/app/type/pluginLight', diff --git a/packages/web/hooks/useI18n.ts b/packages/web/hooks/useI18n.ts index 40f22bbfd..016fbbda4 100644 --- a/packages/web/hooks/useI18n.ts +++ b/packages/web/hooks/useI18n.ts @@ -1,6 +1,6 @@ +import { LangEnum } from '@fastgpt/global/common/i18n/type'; import Cookies from 'js-cookie'; import { useTranslation } from 'next-i18next'; -import { LangEnum } from '../../../projects/app/src/web/common/utils/i18n'; const LANG_KEY = 'NEXT_LOCALE'; const isInIframe = () => { diff --git a/packages/web/i18n/en/account.json b/packages/web/i18n/en/account.json index b57baec0a..870cd61b7 100644 --- a/packages/web/i18n/en/account.json +++ b/packages/web/i18n/en/account.json @@ -1,4 +1,5 @@ { + "account_team.delete_dataset": "Delete the knowledge base", "active_model": "Available models", "add_default_model": "Add a preset model", "api_key": "API key", diff --git a/packages/web/i18n/en/account_team.json b/packages/web/i18n/en/account_team.json index 80d1dbacd..d2cc7e00a 100644 --- a/packages/web/i18n/en/account_team.json +++ b/packages/web/i18n/en/account_team.json @@ -46,6 +46,7 @@ "create_app_copy": "Create a copy of the application", "create_app_folder": "Create an application folder", "create_app_publish_channel": "Create a sharing channel", + "create_collection": "Create a collection", "create_data": "Insert data", "create_dataset": "Create a knowledge base", "create_dataset_folder": "Create a Knowledge Base Folder", @@ -170,6 +171,7 @@ "log_login": "【{{name}}】Logined in the system", "log_move_app": "【{{name}}】Move [{{appType}}] named [{{appName}}] to [{{targetFolderName}}]", "log_move_dataset": "【{{name}}】Move [{{datasetType}}] named [{{datasetName}}] to [{{targetFolderName}}]", + "log_purchase_plan": "【{{name}}】Purchased the set meal", "log_recover_team_member": "【{{name}}】Restored member【{{memberName}}】", "log_relocate_department": "【{{name}}】Displayed department【{{departmentName}}】", "log_retrain_collection": "[{{name}}] Retrained the collection named [{{collectionName}}] in [{{datasetType}}] called [{{datasetName}}].", diff --git a/packages/web/i18n/en/app.json b/packages/web/i18n/en/app.json index 84abdc731..2cd9eb63a 100644 --- a/packages/web/i18n/en/app.json +++ b/packages/web/i18n/en/app.json @@ -97,6 +97,7 @@ "logs_source": "source", "logs_title": "Title", "look_ai_point_price": "View all model billing standards", + "manual_secret": "Manual secret", "mark_count": "Number of Marked Answers", "max_histories_number": "Max histories", "max_histories_number_tip": "The maximum number of rounds of dialogue that the model can carry into memory. If the memory exceeds the model context, the system will force truncation. \nTherefore, even if 30 rounds of dialogue are configured, the actual number may not reach 30 rounds during operation.", @@ -136,6 +137,7 @@ "saved_success": "Saved successfully! \nTo use this version externally, click Save and Publish", "search_app": "Search apps", "search_tool": "Search Tools", + "secret_get_course": "Course", "setting_app": "Workflow", "setting_plugin": "Workflow", "show_top_p_tip": "An alternative method of temperature sampling, called Nucleus sampling, the model considers the results of tokens with TOP_P probability mass quality. \nTherefore, 0.1 means that only tokens containing the highest probability quality are considered. \nThe default is 1.", @@ -145,6 +147,7 @@ "stop_sign_placeholder": "Multiple serial numbers are separated by |, for example: aaa|stop", "stream_response": "Stream", "stream_response_tip": "Turning this switch off forces the model to use non-streaming mode and will not output content directly. \nIn the output of the AI ​​reply, the content output by this model can be obtained for secondary processing.", + "system_secret": "System secret", "team_tags_set": "Team tags", "temperature": "Temperature", "temperature_tip": "Range 0~10. \nThe larger the value, the more divergent the model’s answer is; the smaller the value, the more rigorous the answer.", @@ -171,8 +174,23 @@ "template_market_description": "Explore more features in the template market, with configuration tutorials and usage guides to help you understand and get started with various applications.", "template_market_empty_data": "No suitable templates found", "time_zone": "Time Zone", + "too_to_active": "Active", + "tool_active_manual_config_desc": "The temporary key is saved in this application and is only for use by this application.", + "tool_active_system_config_desc": "Use the system configured key", + "tool_active_system_config_price_desc": "Additional payment for key price ({{price}} points/time)", "tool_detail": "Tool details", "tool_input_param_tip": "This plugin requires configuration of related information to run properly.", + "tool_not_active": "This tool has not been activated yet", + "tool_type_communication": "Communication", + "tool_type_design": "design", + "tool_type_entertainment": "Business", + "tool_type_finance": "finance", + "tool_type_multimodal": "Multimodal", + "tool_type_news": "news", + "tool_type_productivity": "productive forces", + "tool_type_scientific": "research", + "tool_type_social": "Social", + "tool_type_tools": "tool", "tools_no_description": "This tool has not been introduced ~", "transition_to_workflow": "Convert to Workflow", "transition_to_workflow_create_new_placeholder": "Create a new app instead of modifying the current app", @@ -189,6 +207,7 @@ "type.Create simple bot tip": "Create a simple AI app by filling out a form, suitable for beginners.", "type.Create workflow bot": "Create Workflow", "type.Create workflow tip": "Build complex multi-turn dialogue AI applications through low-code methods, recommended for advanced users.", + "type.Folder": "Folder", "type.Http plugin": "HTTP Plugin", "type.Import from json": "Import JSON", "type.Import from json tip": "Create applications directly through JSON configuration files", @@ -197,10 +216,9 @@ "type.MCP tools": "MCP Toolset", "type.MCP_tools_url": "MCP Address", "type.Plugin": "Plugin", - "type.Folder": "Folder", - "type.Tool set": "Toolset", - "type.Tool": "Tool", "type.Simple bot": "Simple App", + "type.Tool": "Tool", + "type.Tool set": "Toolset", "type.Workflow bot": "Workflow", "type.error.Workflow data is empty": "No workflow data was obtained", "type.error.workflowresponseempty": "Response content is empty", @@ -236,9 +254,8 @@ "workflow.select_description_placeholder": "For example: \nAre there tomatoes in the fridge?", "workflow.select_description_tip": "You can add a description text to explain the meaning of each option to the user.", "workflow.select_result": "Selected Result", - "workflow.template.communication": "Communication", "workflow.user_file_input": "File Link", "workflow.user_file_input_desc": "Links to documents and images uploaded by users.", "workflow.user_select": "User Select", "workflow.user_select_tip": "This module can configure multiple options for selection during the dialogue. Different options can lead to different workflow branches." -} \ No newline at end of file +} diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index 5f6df8cd9..894ece4ed 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -50,6 +50,7 @@ "Intro": "Introduction", "Loading": "Loading...", "Login": "Login", + "Manual": "Manual", "More": "More", "Move": "Move", "Name": "Name", @@ -81,6 +82,7 @@ "Status": "Status", "Submit": "Submit", "Success": "Success", + "System": "System", "Team": "Team", "UnKnow": "Unknown", "Unlimited": "Unlimited", @@ -658,7 +660,6 @@ "core.module.template.System Plugin": "System Plugin", "core.module.template.System input module": "System Input", "core.module.template.Team app": "Team", - "core.module.template.Tool module": "Tool", "core.module.template.UnKnow Module": "Unknown Module", "core.module.template.ai_chat": "AI conversation", "core.module.template.ai_chat_intro": "AI large model dialogue", @@ -737,7 +738,6 @@ "core.workflow.publish.OnRevert version confirm": "Confirm to Revert to This Version? The configuration of the editing version will be saved, and a new release version will be created for the reverted version.", "core.workflow.publish.histories": "Release Records", "core.workflow.template.Interactive": "Interactive", - "core.workflow.template.Multimodal": "Multimodal", "core.workflow.template.Search": "Search", "core.workflow.tool.Handle": "Tool Connector", "core.workflow.tool.Select Tool": "Select Tool", @@ -1010,6 +1010,7 @@ "save_failed": "save_failed", "save_success": "Saved Successfully", "scan_code": "Scan the QR code to pay", + "secret_key": "Secret", "secret_tips": "The value will not return plaintext again after saving", "select_file_failed": "File Selection Failed", "select_reference_variable": "Select Reference Variable", @@ -1303,7 +1304,6 @@ "user_leaved": "Leaved", "value": "Value", "verification": "Verification", - "workflow.template.communication": "Communication", "xx_search_result": "{{key}} Search Results", "yes": "Yes", "yesterday": "yesterday", diff --git a/packages/web/i18n/en/dataset.json b/packages/web/i18n/en/dataset.json index a0cafa368..009a4f748 100644 --- a/packages/web/i18n/en/dataset.json +++ b/packages/web/i18n/en/dataset.json @@ -183,7 +183,6 @@ "sync_collection_failed": "Synchronization collection error, please check whether the source file can be accessed normally", "sync_schedule": "Timing synchronization", "sync_schedule_tip": "Only existing collections will be synchronized. \nIncludes linked collections and all collections in the API knowledge base. \nThe system will poll for updates every day, and the specific update time cannot be determined.", - "table_model_tip": "Store each row of data as a chunk", "tag.Add_new_tag": "add_new Tag", "tag.Edit_tag": "Edit Tag", "tag.add": "Create", @@ -200,18 +199,15 @@ "the_knowledge_base_has_indexes_that_are_being_trained_or_being_rebuilt": "The Dataset has indexes that are being trained or rebuilt", "total_num_files": "Total {{total}} files", "training.Error": "{{count}} Group exception", + "training.Image mode": "Image processing", "training.Normal": "Normal", "training_mode": "Chunk mode", - "training_queue_tip": "Training queue status", "training_ready": "{{count}} Group", "upload_by_template_format": "Upload by template file", "uploading_progress": "Uploading: {{num}}%", "vector_model_max_tokens_tip": "Each chunk of data has a maximum length of 3000 tokens", - "vector_training_queue": "Vector training queue", "vllm_model": "Image understanding model", - "vlm_model_required_tooltip": "A Vision Language Model is required to create image collections", "vlm_model_required_warning": "Image datasets require a Vision Language Model (VLM) to be configured. Please add a model that supports image understanding in the model configuration first.", - "waiting_for_training": "Waiting for training", "website_dataset": "Website Sync", "website_dataset_desc": "Build knowledge base by crawling web page data in batches", "website_info": "Website Information", diff --git a/packages/web/i18n/en/file.json b/packages/web/i18n/en/file.json index a95d7ca3a..b2946e2f3 100644 --- a/packages/web/i18n/en/file.json +++ b/packages/web/i18n/en/file.json @@ -12,12 +12,13 @@ "Loading_image failed": "Preview loading failed", "Only_support_uploading_one_image": "Only support uploading one image", "Please select the image to upload": "Please select the image to upload", - "Please select the image to upload select the image to upload": "", "Please wait for all files to upload": "Please wait for all files to be uploaded to complete", "bucket_chat": "Conversation Files", "bucket_file": "Dataset Documents", "click_to_view_raw_source": "Click to View Original Source", + "common.Some images failed to process": "Some images failed to process", "common.dataset_data_input_image_support_format": "Support .jpg, .jpeg, .png, .gif, .webp formats", + "count.core.dataset.collection.Create Success": "{{count}} picture successfully imported", "delete_image": "Delete pictures", "file_name": "Filename", "file_size": "Filesize", diff --git a/packages/web/i18n/en/user.json b/packages/web/i18n/en/user.json index adbe27abf..5dae70096 100644 --- a/packages/web/i18n/en/user.json +++ b/packages/web/i18n/en/user.json @@ -101,7 +101,6 @@ "team.group.manage_tip": "Can manage members, create groups, manage all groups, assign permissions to groups and members", "team.group.members": "member", "team.group.name": "Group name", - "team.group.permission.write": "Workbench/knowledge base creation", "team.group.permission_tip": "Members with individually configured permissions will follow the individual permission configuration and will no longer be affected by group permissions.\n\nIf a member is in multiple permission groups, the member's permissions are combined.", "team.group.role.admin": "administrator", "team.group.role.member": "member", diff --git a/packages/web/i18n/en/workflow.json b/packages/web/i18n/en/workflow.json index c49449457..8e1c5bf95 100644 --- a/packages/web/i18n/en/workflow.json +++ b/packages/web/i18n/en/workflow.json @@ -170,6 +170,8 @@ "start_with": "Starts With", "support_code_language": "Support import list: pandas,numpy", "target_fields_description": "A target field consists of 'description' and 'key'. Multiple target fields can be extracted.", + "template.agent": "Agent", + "template.agent_intro": "Automatically select one or more functional blocks for calling through the AI model, or call plugins.", "template.ai_chat": "AI Chat", "template.ai_chat_intro": "AI Large Model Chat", "template.dataset_search": "Dataset Search", @@ -179,8 +181,6 @@ "template.plugin_output": "Plugin output", "template.plugin_start": "Plugin start", "template.system_config": "System", - "template.tool_call": "Tool Call", - "template.tool_call_intro": "Automatically select one or more functional blocks for calling through the AI model, or call plugins.", "template.workflow_start": "Start", "text_concatenation": "Text Editor", "text_content_extraction": "Text Extract", @@ -189,6 +189,8 @@ "to_add_node": "to add", "to_connect_node": "to connect", "tool.tool_result": "Tool operation results", + "tool_active_config": "Tool active", + "tool_active_config_type": "Tool activation: {{type}}", "tool_call_termination": "Stop ToolCall", "tool_custom_field": "Custom Tool", "tool_field": " Tool Field Parameter Configuration", diff --git a/packages/web/i18n/zh-CN/app.json b/packages/web/i18n/zh-CN/app.json index a0bf8679f..7032056ff 100644 --- a/packages/web/i18n/zh-CN/app.json +++ b/packages/web/i18n/zh-CN/app.json @@ -97,6 +97,7 @@ "logs_source": "来源", "logs_title": "标题", "look_ai_point_price": "查看所有模型计费标准", + "manual_secret": "临时密钥", "mark_count": "标注答案数量", "max_histories_number": "记忆轮数", "max_histories_number_tip": "模型最多携带多少轮对话进入记忆中,如果记忆超出模型上下文,系统会强制截断。所以尽管配置 30 轮对话,实际运行时候,不一定会达到 30 轮。", @@ -136,6 +137,7 @@ "saved_success": "保存成功!如需在外部使用该版本,请点击“保存并发布”", "search_app": "搜索应用", "search_tool": "搜索工具", + "secret_get_course": "教程", "setting_app": "应用配置", "setting_plugin": "插件配置", "show_top_p_tip": "用温度采样的替代方法,称为Nucleus采样,该模型考虑了具有TOP_P概率质量质量的令牌的结果。因此,0.1表示仅考虑包含最高概率质量的令牌。默认为 1。", @@ -145,6 +147,7 @@ "stop_sign_placeholder": "多个序列号通过 | 隔开,例如:aaa|stop", "stream_response": "流输出", "stream_response_tip": "关闭该开关,可以强制模型使用非流模式,并且不会直接进行内容输出。可以在 AI 回复的输出中,获取本次模型输出的内容进行二次处理。", + "system_secret": "系统密钥", "team_tags_set": "团队标签", "temperature": "温度", "temperature_tip": "范围 0~10。值越大,代表模型回答越发散;值越小,代表回答越严谨。", @@ -171,8 +174,23 @@ "template_market_description": "在模板市场探索更多玩法,配置教程与使用引导,带你理解并上手各种应用", "template_market_empty_data": "找不到合适的模板", "time_zone": "时区", + "too_to_active": "去激活", + "tool_active_manual_config_desc": "临时密钥保存在本应用中,仅供该应用使用", + "tool_active_system_config_desc": "使用系统已配置好的密钥", + "tool_active_system_config_price_desc": "需额外支付密钥价格( {{price}} 积分/次)", "tool_detail": "工具详情", "tool_input_param_tip": "该插件正常运行需要配置相关信息", + "tool_not_active": "该工具尚未激活", + "tool_type_communication": "通讯", + "tool_type_design": "设计", + "tool_type_entertainment": "商业", + "tool_type_finance": "金融", + "tool_type_multimodal": "多模态", + "tool_type_news": "新闻", + "tool_type_productivity": "生产力", + "tool_type_scientific": "科研", + "tool_type_social": "社交", + "tool_type_tools": "工具", "tools_no_description": "这个工具没有介绍~", "transition_to_workflow": "转成工作流", "transition_to_workflow_create_new_placeholder": "创建一个新的应用,而不是修改当前应用", @@ -236,9 +254,8 @@ "workflow.select_description_placeholder": "例如: \n冰箱里是否有西红柿?", "workflow.select_description_tip": "你可以添加一段说明文字,用以向用户说明每个选项代表的含义。", "workflow.select_result": "选择结果", - "workflow.template.communication": "通信", "workflow.user_file_input": "文件链接", "workflow.user_file_input_desc": "用户上传的文档和图片链接", "workflow.user_select": "用户选择", "workflow.user_select_tip": "该模块可配置多个选项,以供对话时选择。不同选项可导向不同工作流支线" -} \ No newline at end of file +} diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json index 9a43b1eb5..2b474ce3f 100644 --- a/packages/web/i18n/zh-CN/common.json +++ b/packages/web/i18n/zh-CN/common.json @@ -50,6 +50,7 @@ "Intro": "介绍", "Loading": "加载中...", "Login": "登录", + "Manual": "临时", "More": "更多", "Move": "移动", "Name": "名称", @@ -81,6 +82,7 @@ "Status": "状态", "Submit": "提交", "Success": "成功", + "System": "系统", "Team": "团队", "UnKnow": "未知", "Unlimited": "无限制", @@ -658,7 +660,6 @@ "core.module.template.System Plugin": "系统插件", "core.module.template.System input module": "系统输入", "core.module.template.Team app": "团队应用", - "core.module.template.Tool module": "工具", "core.module.template.UnKnow Module": "未知模块", "core.module.template.ai_chat": "AI 对话", "core.module.template.ai_chat_intro": "AI 大模型对话", @@ -737,7 +738,6 @@ "core.workflow.publish.OnRevert version confirm": "确认回退至该版本?会为您保存编辑中版本的配置,并为回退版本创建一个新的发布版本。", "core.workflow.publish.histories": "发布记录", "core.workflow.template.Interactive": "交互", - "core.workflow.template.Multimodal": "多模态", "core.workflow.template.Search": "搜索", "core.workflow.tool.Handle": "工具连接器", "core.workflow.tool.Select Tool": "选择工具", @@ -1010,6 +1010,7 @@ "save_failed": "保存异常", "save_success": "保存成功", "scan_code": "扫码支付", + "secret_key": "密钥", "secret_tips": "值保存后不会再次明文返回", "select_file_failed": "选择文件异常", "select_reference_variable": "选择引用变量", @@ -1303,7 +1304,6 @@ "user_leaved": "已离开", "value": "值", "verification": "验证", - "workflow.template.communication": "通信", "xx_search_result": "{{key}} 的搜索结果", "yes": "是", "yesterday": "昨天", diff --git a/packages/web/i18n/zh-CN/user.json b/packages/web/i18n/zh-CN/user.json index 4015933ca..09e5b466b 100644 --- a/packages/web/i18n/zh-CN/user.json +++ b/packages/web/i18n/zh-CN/user.json @@ -102,7 +102,6 @@ "team.group.manage_tip": "可以管理成员、创建群组、管理所有群组、为群组和成员分配权限", "team.group.members": "成员", "team.group.name": "群组名称", - "team.group.permission.write": "", "team.group.permission_tip": "单独配置权限的成员,将遵循个人权限配置,不再受群组权限影响。\n若成员在多个权限组,则该成员的权限取并集。", "team.group.role.admin": "管理员", "team.group.role.member": "成员", diff --git a/packages/web/i18n/zh-CN/workflow.json b/packages/web/i18n/zh-CN/workflow.json index 6296b79e0..b08a0f69b 100644 --- a/packages/web/i18n/zh-CN/workflow.json +++ b/packages/web/i18n/zh-CN/workflow.json @@ -170,6 +170,8 @@ "start_with": "开始为", "support_code_language": "支持import列表:pandas,numpy", "target_fields_description": "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段", + "template.agent": "工具调用", + "template.agent_intro": "由 AI 自主决定工具调用。", "template.ai_chat": "AI 对话", "template.ai_chat_intro": "AI 大模型对话", "template.dataset_search": "知识库搜索", @@ -179,8 +181,6 @@ "template.plugin_output": "插件输出", "template.plugin_start": "插件开始", "template.system_config": "系统配置", - "template.tool_call": "工具调用", - "template.tool_call_intro": "通过AI模型自动选择一个或多个功能块进行调用,也可以对插件进行调用。", "template.workflow_start": "流程开始", "text_concatenation": "文本拼接", "text_content_extraction": "文本内容提取", @@ -189,6 +189,8 @@ "to_add_node": "添加节点", "to_connect_node": "连接节点", "tool.tool_result": "工具运行结果", + "tool_active_config": "工具激活", + "tool_active_config_type": "工具激活: {{type}}", "tool_call_termination": "工具调用终止", "tool_custom_field": "自定义工具变量", "tool_field": "工具参数配置", diff --git a/packages/web/i18n/zh-Hant/account.json b/packages/web/i18n/zh-Hant/account.json index e65f2fed1..d530ac216 100644 --- a/packages/web/i18n/zh-Hant/account.json +++ b/packages/web/i18n/zh-Hant/account.json @@ -1,4 +1,5 @@ { + "account_team.delete_dataset": "刪除知識庫", "active_model": "可用模型", "add_default_model": "新增預設模型", "api_key": "API 金鑰", diff --git a/packages/web/i18n/zh-Hant/account_team.json b/packages/web/i18n/zh-Hant/account_team.json index 31a641702..1d4545866 100644 --- a/packages/web/i18n/zh-Hant/account_team.json +++ b/packages/web/i18n/zh-Hant/account_team.json @@ -17,6 +17,7 @@ "admin_delete_template_type": "刪除模板分類", "admin_finish_invoice": "開具發票", "admin_login": "管理員登錄", + "admin_save_template_type": "更新模板分類", "admin_send_system_inform": "發送系統通知", "admin_update_app_template": "更新模板", "admin_update_plan": "編輯團隊套餐", @@ -45,6 +46,7 @@ "create_app_copy": "創建應用副本", "create_app_folder": "創建應用文件夾", "create_app_publish_channel": "創建分享渠道", + "create_collection": "創建集合", "create_data": "插入數據", "create_dataset": "創建知識庫", "create_dataset_folder": "創建知識庫文件夾", @@ -169,6 +171,7 @@ "log_login": "【{{name}}】登錄了系統", "log_move_app": "【{{name}}】將名為【{{appName}}】的【{{appType}}】移動到【{{targetFolderName}}】", "log_move_dataset": "【{{name}}】將名為【{{datasetName}}】的【{{datasetType}}】移動到【{{targetFolderName}}】", + "log_purchase_plan": "【{{name}}】購買了套餐", "log_recover_team_member": "【{{name}}】恢復了成員【{{memberName}}】", "log_relocate_department": "【{{name}}】移動了部門【{{departmentName}}】", "log_retrain_collection": "【{{name}}】在名為【{{datasetName}}】的【{{datasetType}}】重新訓練了名為【{{collectionName}}】的集合", diff --git a/packages/web/i18n/zh-Hant/app.json b/packages/web/i18n/zh-Hant/app.json index 73c3cfd23..aec9cc5f3 100644 --- a/packages/web/i18n/zh-Hant/app.json +++ b/packages/web/i18n/zh-Hant/app.json @@ -97,6 +97,7 @@ "logs_source": "來源", "logs_title": "標題", "look_ai_point_price": "檢視所有模型計費標準", + "manual_secret": "臨時密鑰", "mark_count": "標記答案數量", "max_histories_number": "記憶輪數", "max_histories_number_tip": "模型最多攜帶多少輪對話進入記憶中,如果記憶超出模型上下文,系統會強制截斷。\n所以儘管設定 30 輪對話,實際運作時候,不一定會達到 30 輪。", @@ -136,6 +137,7 @@ "saved_success": "儲存成功!\n如需在外部使用該版本,請點選“儲存並發布”", "search_app": "搜尋應用程式", "search_tool": "搜索工具", + "secret_get_course": "教程", "setting_app": "應用程式設定", "setting_plugin": "外掛設定", "show_top_p_tip": "用溫度取樣的替代方法,稱為 Nucleus 取樣,該模型考慮了具有 TOP_P 機率質量質量的令牌的結果。\n因此,0.1 表示僅考慮包含最高機率質量的令牌。\n預設為 1。", @@ -145,6 +147,7 @@ "stop_sign_placeholder": "多個序列號透過 | 隔開,例如:aaa|stop", "stream_response": "流輸出", "stream_response_tip": "關閉該開關​​,可以強制模型使用非流模式,並且不會直接進行內容輸出。\n可在 AI 回覆的輸出中,取得本次模型輸出的內容進行二次處理。", + "system_secret": "系統密鑰", "team_tags_set": "團隊標籤", "temperature": "溫度", "temperature_tip": "範圍 0~10。\n值越大,代表模型回答越發散;值越小,代表回答越嚴謹。", @@ -171,8 +174,23 @@ "template_market_description": "在範本市集探索更多玩法,設定教學與使用指引,帶您理解並上手各種應用程式", "template_market_empty_data": "找不到合適的範本", "time_zone": "時區", + "too_to_active": "去激活", + "tool_active_manual_config_desc": "臨時密鑰保存在本應用中,僅供該應用使用", + "tool_active_system_config_desc": "使用系統已配置好的密鑰", + "tool_active_system_config_price_desc": "需額外支付密鑰價格( {{price}} 積分/次)", "tool_detail": "工具詳情", "tool_input_param_tip": "這個外掛正常執行需要設定相關資訊", + "tool_not_active": "該工具尚未激活", + "tool_type_communication": "通訊", + "tool_type_design": "設計", + "tool_type_entertainment": "商業", + "tool_type_finance": "金融", + "tool_type_multimodal": "多模態", + "tool_type_news": "新聞", + "tool_type_productivity": "生產力", + "tool_type_scientific": "科研", + "tool_type_social": "社交", + "tool_type_tools": "工具", "tools_no_description": "這個工具沒有介紹~", "transition_to_workflow": "轉換成工作流程", "transition_to_workflow_create_new_placeholder": "建立新的應用程式,而不是修改目前應用程式", @@ -189,6 +207,7 @@ "type.Create simple bot tip": "透過填寫表單的方式,建立簡單的 AI 應用程式,適合新手", "type.Create workflow bot": "建立工作流程", "type.Create workflow tip": "透過低程式碼的方式,建立邏輯複雜的多輪對話 AI 應用程式,建議進階使用者使用", + "type.Folder": "資料夾", "type.Http plugin": "HTTP 外掛", "type.Import from json": "匯入 JSON 設定", "type.Import from json tip": "透過 JSON 設定文件,直接建立應用", @@ -198,9 +217,8 @@ "type.MCP_tools_url": "MCP 地址", "type.Plugin": "外掛", "type.Simple bot": "簡易應用程式", - "type.Folder": "資料夾", - "type.Tool set": "工具集", "type.Tool": "工具", + "type.Tool set": "工具集", "type.Workflow bot": "工作流程", "type.error.Workflow data is empty": "沒有獲取到工作流數據", "type.error.workflowresponseempty": "響應內容為空", @@ -236,9 +254,8 @@ "workflow.select_description_placeholder": "例如:\n冰箱裡是否有番茄?", "workflow.select_description_tip": "您可以新增一段說明文字,用來向使用者說明每個選項代表的意義。", "workflow.select_result": "選擇結果", - "workflow.template.communication": "通訊", "workflow.user_file_input": "檔案連結", "workflow.user_file_input_desc": "使用者上傳的檔案和圖片連結", "workflow.user_select": "使用者選擇", "workflow.user_select_tip": "這個模組可以設定多個選項,供對話時選擇。不同選項可以導向不同的工作流程支線" -} \ No newline at end of file +} diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json index 78a7302c4..8ecfbcef5 100644 --- a/packages/web/i18n/zh-Hant/common.json +++ b/packages/web/i18n/zh-Hant/common.json @@ -50,6 +50,7 @@ "Intro": "介紹", "Loading": "載入中...", "Login": "登入", + "Manual": "臨時", "More": "更多", "Move": "移動", "Name": "名稱", @@ -81,6 +82,7 @@ "Status": "狀態", "Submit": "送出", "Success": "成功", + "System": "系統", "Team": "團隊", "UnKnow": "未知", "Unlimited": "無限制", @@ -658,7 +660,6 @@ "core.module.template.System Plugin": "系統外掛", "core.module.template.System input module": "系統輸入模組", "core.module.template.Team app": "團隊應用程式", - "core.module.template.Tool module": "工具", "core.module.template.UnKnow Module": "未知模組", "core.module.template.ai_chat": "AI 對話", "core.module.template.ai_chat_intro": "AI 大型模型對話", @@ -737,7 +738,6 @@ "core.workflow.publish.OnRevert version confirm": "確認回復至此版本?將為您儲存編輯中版本的設定,並為回復版本建立一個新的發布版本。", "core.workflow.publish.histories": "發布記錄", "core.workflow.template.Interactive": "互動", - "core.workflow.template.Multimodal": "多模態", "core.workflow.template.Search": "搜尋", "core.workflow.tool.Handle": "工具聯結器", "core.workflow.tool.Select Tool": "選擇工具", @@ -1010,6 +1010,7 @@ "save_failed": "儲存失敗", "save_success": "儲存成功", "scan_code": "掃碼支付", + "secret_key": "密鑰", "secret_tips": "值保存後不會再次明文返回", "select_file_failed": "選擇檔案失敗", "select_reference_variable": "選擇引用變數", @@ -1303,7 +1304,6 @@ "user_leaved": "已離開", "value": "值", "verification": "驗證", - "workflow.template.communication": "通訊", "xx_search_result": "{{key}} 的搜尋結果", "yes": "是", "yesterday": "昨天", diff --git a/packages/web/i18n/zh-Hant/dataset.json b/packages/web/i18n/zh-Hant/dataset.json index 169f865fa..504c1d86d 100644 --- a/packages/web/i18n/zh-Hant/dataset.json +++ b/packages/web/i18n/zh-Hant/dataset.json @@ -20,6 +20,7 @@ "chunk_trigger_force_chunk": "強制分塊", "chunk_trigger_max_size": "原文長度大於文件處理模型最大上下文70%", "chunk_trigger_min_size": "原文長度大於", + "chunk_trigger_tips": "當滿足一定條件時才觸發分塊存儲,否則會直接完整存儲原文", "close_auto_sync": "確認關閉自動同步功能?", "collection.Create update time": "建立/更新時間", "collection.Training type": "分段模式", @@ -203,6 +204,7 @@ "training_mode": "分段模式", "training_ready": "{{count}} 組", "upload_by_template_format": "按模版文件上傳", + "uploading_progress": "上傳中: {{num}}%", "vector_model_max_tokens_tip": "每個分塊資料,最大長度為 3000 tokens", "vllm_model": "圖片理解模型", "vlm_model_required_warning": "需要圖片理解模型", diff --git a/packages/web/i18n/zh-Hant/file.json b/packages/web/i18n/zh-Hant/file.json index eb7223cbd..488717523 100644 --- a/packages/web/i18n/zh-Hant/file.json +++ b/packages/web/i18n/zh-Hant/file.json @@ -9,20 +9,22 @@ "Image_does_not_belong_to_current_team": "圖片不屬於當前團隊", "Image_file_does_not_exist": "圖片不存在", "Loading_image": "加載圖片中...", - "Loading_image_failed": "預覽加載失敗", + "Loading_image failed": "預覽加載失敗", "Only_support_uploading_one_image": "僅支持上傳一張圖片", "Please select the image to upload": "請選擇要上傳的圖片", - "Please select the image to upload select the image to upload": "", "Please wait for all files to upload": "請等待所有文件上傳完成", "bucket_chat": "對話檔案", "bucket_file": "知識庫檔案", "click_to_view_raw_source": "點選檢視原始來源", - "dataset_data_input_image_support_format": "支持 .jpg, .jpeg, .png, .gif, .webp 格式", + "common.Some images failed to process": "部分圖片處理失敗", + "common.dataset_data_input_image_support_format": "支持 .jpg, .jpeg, .png, .gif, .webp 格式", + "count.core.dataset.collection.Create Success": "成功導入 {{count}} 張圖片", "delete_image": "刪除圖片", "file_name": "檔案名稱", "file_size": "檔案大小", "image": "圖片", "image_collection": "圖片集合", + "image_description": "圖片描述", "image_description_tip": "請輸入圖片的描述內容", "please_upload_image_first": "請先上傳圖片", "reached_max_file_count": "已達檔案數量上限", diff --git a/packages/web/i18n/zh-Hant/user.json b/packages/web/i18n/zh-Hant/user.json index 2e0b76190..0d951ee6a 100644 --- a/packages/web/i18n/zh-Hant/user.json +++ b/packages/web/i18n/zh-Hant/user.json @@ -101,7 +101,6 @@ "team.group.manage_tip": "可以管理成員、建立群組、管理所有群組、為群組和成員分配權限", "team.group.members": "成員", "team.group.name": "群組名稱", - "team.group.permission.write": "工作臺/知識庫建立", "team.group.permission_tip": "單獨設定權限的成員,將依照個人權限設定,不再受群組權限影響。\n若成員屬於多個權限群組,該成員的權限將會合併。", "team.group.role.admin": "管理員", "team.group.role.member": "成員", diff --git a/packages/web/i18n/zh-Hant/workflow.json b/packages/web/i18n/zh-Hant/workflow.json index 2dd7c3a31..7392a69aa 100644 --- a/packages/web/i18n/zh-Hant/workflow.json +++ b/packages/web/i18n/zh-Hant/workflow.json @@ -170,6 +170,8 @@ "start_with": "開頭為", "support_code_language": "支援 import 列表:pandas,numpy", "target_fields_description": "由「描述」和「鍵值」組成一個目標欄位,可以擷取多個目標欄位", + "template.agent": "工具调用", + "template.agent_intro": "透過 AI 模型自動選擇一或多個功能區塊進行呼叫,也可以呼叫外掛程式。", "template.ai_chat": "AI 對話", "template.ai_chat_intro": "AI 大型語言模型對話", "template.dataset_search": "知識庫搜尋", @@ -179,8 +181,6 @@ "template.plugin_output": "外掛程式輸出", "template.plugin_start": "外掛程式啟動", "template.system_config": "系統設定", - "template.tool_call": "工具呼叫", - "template.tool_call_intro": "透過 AI 模型自動選擇一或多個功能區塊進行呼叫,也可以呼叫外掛程式。", "template.workflow_start": "流程開始", "text_concatenation": "文字串接", "text_content_extraction": "文字內容擷取", @@ -189,6 +189,8 @@ "to_add_node": "添加節點", "to_connect_node": "連接節點", "tool.tool_result": "工具運行結果", + "tool_active_config": "工具激活", + "tool_active_config_type": "工具激活: {{type}}", "tool_call_termination": "工具呼叫終止", "tool_custom_field": "自訂工具變數", "tool_field": "工具參數設定", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a1275a0f..b1df91099 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,7 +46,7 @@ importers: version: 10.1.4(socks@2.8.4) next-i18next: specifier: 15.4.2 - version: 15.4.2(i18next@23.16.8)(next@14.2.28(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 15.4.2(i18next@23.16.8)(next@14.2.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) prettier: specifier: 3.2.4 version: 3.2.4 @@ -100,7 +100,7 @@ importers: version: 14.2.28(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) openai: specifier: 4.61.0 - version: 4.61.0(encoding@0.1.13)(zod@3.24.2) + version: 4.61.0(encoding@0.1.13)(zod@3.25.51) openapi-types: specifier: ^12.1.3 version: 12.1.3 @@ -118,66 +118,11 @@ importers: specifier: 20.14.0 version: 20.14.0 - packages/plugins: - dependencies: - '@types/nodemailer': - specifier: ^6.4.17 - version: 6.4.17 - '@types/pg': - specifier: ^8.6.6 - version: 8.11.11 - axios: - specifier: ^1.8.2 - version: 1.8.4 - cheerio: - specifier: 1.0.0-rc.12 - version: 1.0.0-rc.12 - duck-duck-scrape: - specifier: ^2.2.5 - version: 2.2.7 - echarts: - specifier: 5.4.1 - version: 5.4.1 - expr-eval: - specifier: ^2.0.2 - version: 2.0.2 - json5: - specifier: ^2.2.3 - version: 2.2.3 - lodash: - specifier: ^4.17.21 - version: 4.17.21 - mssql: - specifier: ^11.0.1 - version: 11.0.1 - mysql2: - specifier: ^3.11.3 - version: 3.13.0 - nodemailer: - specifier: ^6.10.0 - version: 6.10.0 - pg: - specifier: ^8.10.0 - version: 8.14.0 - wikijs: - specifier: ^6.4.1 - version: 6.4.1(encoding@0.1.13) - devDependencies: - '@fastgpt/global': - specifier: workspace:* - version: link:../global - '@fastgpt/service': - specifier: workspace:* - version: link:../service - '@types/lodash': - specifier: ^4.14.191 - version: 4.17.16 - '@types/node': - specifier: 20.14.0 - version: 20.14.0 - packages/service: dependencies: + '@fastgpt-sdk/plugin': + specifier: ^0.1.0 + version: 0.1.0(@types/node@20.17.24) '@fastgpt/global': specifier: workspace:* version: link:../global @@ -349,7 +294,7 @@ importers: version: 2.1.1(@chakra-ui/system@2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1))(react@18.3.1) '@chakra-ui/next-js': specifier: 2.4.2 - version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.28(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1) + version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1) '@chakra-ui/react': specifier: 2.10.7 version: 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -412,7 +357,7 @@ importers: version: 4.17.21 next-i18next: specifier: 15.4.2 - version: 15.4.2(i18next@23.16.8)(next@14.2.28(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 15.4.2(i18next@23.16.8)(next@14.2.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) papaparse: specifier: ^5.4.1 version: 5.4.1 @@ -476,7 +421,7 @@ importers: version: 2.1.1(@chakra-ui/system@2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1))(react@18.3.1) '@chakra-ui/next-js': specifier: 2.4.2 - version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.28(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1) + version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1) '@chakra-ui/react': specifier: 2.10.7 version: 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -498,9 +443,6 @@ importers: '@fastgpt/global': specifier: workspace:* version: link:../../packages/global - '@fastgpt/plugins': - specifier: workspace:* - version: link:../../packages/plugins '@fastgpt/service': specifier: workspace:* version: link:../../packages/service @@ -578,7 +520,7 @@ importers: version: 14.2.28(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1) next-i18next: specifier: 15.4.2 - version: 15.4.2(i18next@23.16.8)(next@14.2.28(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 15.4.2(i18next@23.16.8)(next@14.2.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) nprogress: specifier: ^0.2.0 version: 0.2.0 @@ -857,70 +799,6 @@ packages: peerDependencies: openapi-types: '>=7' - '@azure/abort-controller@2.1.2': - resolution: {integrity: sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==} - engines: {node: '>=18.0.0'} - - '@azure/core-auth@1.9.0': - resolution: {integrity: sha512-FPwHpZywuyasDSLMqJ6fhbOK3TqUdviZNF8OqRGA4W5Ewib2lEEZ+pBsYcBa88B2NGO/SEnYPGhyBqNlE8ilSw==} - engines: {node: '>=18.0.0'} - - '@azure/core-client@1.9.3': - resolution: {integrity: sha512-/wGw8fJ4mdpJ1Cum7s1S+VQyXt1ihwKLzfabS1O/RDADnmzVc01dHn44qD0BvGH6KlZNzOMW95tEpKqhkCChPA==} - engines: {node: '>=18.0.0'} - - '@azure/core-http-compat@2.2.0': - resolution: {integrity: sha512-1kW8ZhN0CfbNOG6C688z5uh2yrzALE7dDXHiR9dY4vt+EbhGZQSbjDa5bQd2rf3X2pdWMsXbqbArxUyeNdvtmg==} - engines: {node: '>=18.0.0'} - - '@azure/core-lro@2.7.2': - resolution: {integrity: sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==} - engines: {node: '>=18.0.0'} - - '@azure/core-paging@1.6.2': - resolution: {integrity: sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==} - engines: {node: '>=18.0.0'} - - '@azure/core-rest-pipeline@1.19.1': - resolution: {integrity: sha512-zHeoI3NCs53lLBbWNzQycjnYKsA1CVKlnzSNuSFcUDwBp8HHVObePxrM7HaX+Ha5Ks639H7chNC9HOaIhNS03w==} - engines: {node: '>=18.0.0'} - - '@azure/core-tracing@1.2.0': - resolution: {integrity: sha512-UKTiEJPkWcESPYJz3X5uKRYyOcJD+4nYph+KpfdPRnQJVrZfk0KJgdnaAWKfhsBBtAf/D58Az4AvCJEmWgIBAg==} - engines: {node: '>=18.0.0'} - - '@azure/core-util@1.11.0': - resolution: {integrity: sha512-DxOSLua+NdpWoSqULhjDyAZTXFdP/LKkqtYuxxz1SCN289zk3OG8UOpnCQAz/tygyACBtWp/BoO72ptK7msY8g==} - engines: {node: '>=18.0.0'} - - '@azure/identity@4.8.0': - resolution: {integrity: sha512-l9ALUGHtFB/JfsqmA+9iYAp2a+cCwdNO/cyIr2y7nJLJsz1aae6qVP8XxT7Kbudg0IQRSIMXj0+iivFdbD1xPA==} - engines: {node: '>=18.0.0'} - - '@azure/keyvault-common@2.0.0': - resolution: {integrity: sha512-wRLVaroQtOqfg60cxkzUkGKrKMsCP6uYXAOomOIysSMyt1/YM0eUn9LqieAWM8DLcU4+07Fio2YGpPeqUbpP9w==} - engines: {node: '>=18.0.0'} - - '@azure/keyvault-keys@4.9.0': - resolution: {integrity: sha512-ZBP07+K4Pj3kS4TF4XdkqFcspWwBHry3vJSOFM5k5ZABvf7JfiMonvaFk2nBF6xjlEbMpz5PE1g45iTMme0raQ==} - engines: {node: '>=18.0.0'} - - '@azure/logger@1.1.4': - resolution: {integrity: sha512-4IXXzcCdLdlXuCG+8UKEwLA1T1NHqUfanhXYHiQTn+6sfWCZXduqbtXDGceg3Ce5QxTGo7EqmbV6Bi+aqKuClQ==} - engines: {node: '>=18.0.0'} - - '@azure/msal-browser@4.7.0': - resolution: {integrity: sha512-H4AIPhIQVe1qW4+BJaitqod6UGQiXE3juj7q2ZBsOPjuZicQaqcbnBp2gCroF/icS0+TJ9rGuyCBJbjlAqVOGA==} - engines: {node: '>=0.8.0'} - - '@azure/msal-common@15.2.1': - resolution: {integrity: sha512-eZHtYE5OHDN0o2NahCENkczQ6ffGc0MoUSAI3hpwGpZBHJXaEQMMZPWtIx86da2L9w7uT+Tr/xgJbGwIkvTZTQ==} - engines: {node: '>=0.8.0'} - - '@azure/msal-node@3.3.0': - resolution: {integrity: sha512-ulsT3EHF1RQ29X55cxBLgKsIKWni9JdbUqG7sipGVP4uhWcBpmm/vhKOMH340+27Acm9+kHGnN/5XmQ5LrIDgA==} - engines: {node: '>=16'} - '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} @@ -2065,6 +1943,9 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@fastgpt-sdk/plugin@0.1.0': + resolution: {integrity: sha512-XesoJDaZ7p2U0el9rAFcbA8A6dp8l4jrwTOoShTODupJS+7ksY8PVLeC8N8uLCzimXtslB+G9H2nRXih3kBo7Q==} + '@fastify/accept-negotiator@1.1.0': resolution: {integrity: sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==} engines: {node: '>=14'} @@ -2235,9 +2116,6 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@js-joda/core@5.6.4': - resolution: {integrity: sha512-ChdLDTYMEoYoiKZMT90wZMEdGvZ2/QZMnhvjvEqeO5oLoxUfSiLzfe6Lhf3g88+MhZ+utbAu7PAxX1sZkLo5pA==} - '@js-sdsl/ordered-map@4.4.2': resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} @@ -3228,9 +3106,6 @@ packages: react-native: optional: true - '@tediousjs/connection-string@0.5.0': - resolution: {integrity: sha512-7qSgZbincDDDFyRweCIEvZULFAw5iz/DeunhvuxpL31nfntX3P4Yd4HkHBRg9H8CdqY1e5WFN1PZIz/REL9MVQ==} - '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} @@ -3238,6 +3113,17 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} + '@ts-rest/core@3.52.1': + resolution: {integrity: sha512-tAjz7Kxq/grJodcTA1Anop4AVRDlD40fkksEV5Mmal88VoZeRKAG8oMHsDwdwPZz+B/zgnz0q2sF+cm5M7Bc7g==} + peerDependencies: + '@types/node': ^18.18.7 || >=20.8.4 + zod: ^3.22.3 + peerDependenciesMeta: + '@types/node': + optional: true + zod: + optional: true + '@tsconfig/node10@1.0.11': resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} @@ -3493,9 +3379,6 @@ packages: '@types/node@20.17.24': resolution: {integrity: sha512-d7fGCyB96w9BnWQrOsJtpyiSaBcAYYr75bnK6ZRjDbql2cGLj/3GsL5OYmLPNq76l7Gf2q4Rv9J2o6h5CrD9sA==} - '@types/nodemailer@6.4.17': - resolution: {integrity: sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==} - '@types/nprogress@0.2.3': resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} @@ -3535,9 +3418,6 @@ packages: '@types/react@18.3.1': resolution: {integrity: sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==} - '@types/readable-stream@4.0.18': - resolution: {integrity: sha512-21jK/1j+Wg+7jVw1xnSwy/2Q1VgVjWuFssbYGTREPUBeZ+rqVFl2udq0IkxzPC0ZhOzVceUbyIACFZKLqKEBlA==} - '@types/request-ip@0.0.37': resolution: {integrity: sha512-uw6/i3rQnpznxD7LtLaeuZytLhKZK6bRoTS6XVJlwxIOoOpEBU7bgKoVXDNtOg4Xl6riUKHa9bjMVrL6ESqYlQ==} @@ -4122,9 +4002,6 @@ packages: bl@5.1.0: resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} - bl@6.1.0: - resolution: {integrity: sha512-ClDyJGQkc8ZtzdAAbAwBmhMSpwN/sC9HA8jxdYm6nVUbCfZbe2mgza4qh7AuEYyEPB/c4Kznf9s66bnsKMQDjw==} - bluebird@3.4.7: resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} @@ -4199,10 +4076,6 @@ packages: bundle-n-require@1.1.2: resolution: {integrity: sha512-bEk2jakVK1ytnZ9R2AAiZEeK/GxPUM8jvcRxHZXifZDMcjkI4EG/GlsJ2YGSVYT9y/p/gA9/0yDY8rCGsSU6Tg==} - bundle-name@4.1.0: - resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} - engines: {node: '>=18'} - busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} @@ -4246,10 +4119,6 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - camelcase@4.1.0: - resolution: {integrity: sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==} - engines: {node: '>=4'} - camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -4615,9 +4484,6 @@ packages: resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} engines: {node: '>=12.0.0'} - cross-fetch@3.2.0: - resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -4918,14 +4784,6 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - default-browser-id@5.0.0: - resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} - engines: {node: '>=18'} - - default-browser@5.2.1: - resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} - engines: {node: '>=18'} - defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} @@ -4937,10 +4795,6 @@ packages: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} - define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} - define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -5067,9 +4921,6 @@ packages: resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} engines: {node: '>=12'} - duck-duck-scrape@2.2.7: - resolution: {integrity: sha512-BEcglwnfx5puJl90KQfX+Q2q5vCguqyMpZcSRPBWk8OY55qWwV93+E+7DbIkrGDW4qkqPfUvtOUdi0lXz6lEMQ==} - duck@0.1.12: resolution: {integrity: sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==} @@ -5421,9 +5272,6 @@ packages: exponential-backoff@3.1.2: resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==} - expr-eval@2.0.2: - resolution: {integrity: sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg==} - express-rate-limit@7.5.0: resolution: {integrity: sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==} engines: {node: '>= 16'} @@ -5907,9 +5755,6 @@ packages: hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - html-entities@2.5.2: - resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} - html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -5961,10 +5806,6 @@ packages: engines: {node: '>=14'} hasBin: true - hyntax@1.1.9: - resolution: {integrity: sha512-xjxyDLbVDdLgjPnl4NM+Iu6il3UPmk6PNCBXruQKeuKDc/HtaZx1hk1AtMgw3vsn9YnLZRfoBpPxYMXcoT5KAA==} - engines: {node: '>=6.11.1', npm: '>=5.3.0'} - hyperdown@2.4.29: resolution: {integrity: sha512-vwpa65JOmo6zBdvmNV3tM5IxNMbTRCXmCz4rajM9NHuiI9aAMw9tGzp8FBO8NT7ZnyWND0HEY6vKCVYl//U8kA==} @@ -6023,9 +5864,6 @@ packages: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - infobox-parser@3.6.2: - resolution: {integrity: sha512-lasdwvbtjCtDDO6mArAs/ueFEnBJRyo2UbZPAkd5rEG5NVJ3XFCOvbMwNTT/rJlFv1+ORw8D3UvZV4brpgATCg==} - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -6148,11 +5986,6 @@ packages: is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -6187,11 +6020,6 @@ packages: is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - is-installed-globally@0.4.0: resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} engines: {node: '>=10'} @@ -6317,10 +6145,6 @@ packages: is-word-character@1.0.4: resolution: {integrity: sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==} - is-wsl@3.1.0: - resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} - engines: {node: '>=16'} - is-yarn-global@0.4.1: resolution: {integrity: sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==} engines: {node: '>=12'} @@ -6533,9 +6357,6 @@ packages: resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} engines: {node: '>=14'} - js-md4@0.3.2: - resolution: {integrity: sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -6631,15 +6452,9 @@ packages: jwa@1.4.1: resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} - jwa@2.0.0: - resolution: {integrity: sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==} - jws@3.2.2: resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} - jws@4.0.0: - resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==} - kareem@2.6.3: resolution: {integrity: sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==} engines: {node: '>=12.0.0'} @@ -7361,11 +7176,6 @@ packages: msgpackr@1.11.2: resolution: {integrity: sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==} - mssql@11.0.1: - resolution: {integrity: sha512-KlGNsugoT90enKlR8/G36H0kTxPthDhmtNUCwEHvgRza5Cjpjoj+P2X6eMpFUDN7pFrJZsKadL4x990G8RBE1w==} - engines: {node: '>=18'} - hasBin: true - multer@2.0.1: resolution: {integrity: sha512-Ug8bXeTIUlxurg8xLTEskKShvcKDZALo1THEX5E41pYCD2sCVub5/kIRIGqWNoqV6szyLyQKV6mD4QUrWE5GCQ==} engines: {node: '>= 10.16.0'} @@ -7398,17 +7208,9 @@ packages: napi-build-utils@2.0.0: resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} - native-duplexpair@1.0.0: - resolution: {integrity: sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA==} - natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - needle@3.3.1: - resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==} - engines: {node: '>= 4.4.x'} - hasBin: true - negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} @@ -7515,10 +7317,6 @@ packages: engines: {node: '>=10.0.0'} hasBin: true - nodemailer@6.10.0: - resolution: {integrity: sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA==} - engines: {node: '>=6.0.0'} - non-layered-tidy-tree-layout@2.0.2: resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==} @@ -7609,10 +7407,6 @@ packages: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} - open@10.1.0: - resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} - engines: {node: '>=18'} - openai@4.61.0: resolution: {integrity: sha512-xkygRBRLIUumxzKGb1ug05pWmJROQsHkGuj/N6Jiw2dj0dI19JvbFpErSZKmJ/DA+0IvpcugZqCAyk8iLpyM6Q==} hasBin: true @@ -7999,10 +7793,6 @@ packages: process-warning@5.0.0: resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} - process@0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - promise-retry@2.0.1: resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} engines: {node: '>=10'} @@ -8256,10 +8046,6 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} - readable-stream@4.7.0: - resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -8465,10 +8251,6 @@ packages: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} - run-applescript@7.0.0: - resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} - engines: {node: '>=18'} - run-async@2.4.1: resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} engines: {node: '>=0.12.0'} @@ -8526,9 +8308,6 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - sax@1.4.1: - resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} - scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} @@ -8773,10 +8552,6 @@ packages: resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - stoppable@1.1.0: - resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} - engines: {node: '>=4', npm: '>=6'} - streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} @@ -8965,14 +8740,6 @@ packages: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} - tarn@3.0.2: - resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==} - engines: {node: '>=8.0.0'} - - tedious@18.6.1: - resolution: {integrity: sha512-9AvErXXQTd6l7TDd5EmM+nxbOGyhnmdbp/8c3pw+tjaiSXW9usME90ET/CRG1LN1Y9tPMtz/p83z4Q97B4DDpw==} - engines: {node: '>=18'} - terser-webpack-plugin@5.3.14: resolution: {integrity: sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==} engines: {node: '>= 10.13.0'} @@ -9751,10 +9518,6 @@ packages: resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} engines: {node: '>=12'} - wikijs@6.4.1: - resolution: {integrity: sha512-fnYyT9ISD9hFgAxFJu7Kzsomz48w7FpvvAfTuArvkMQY1bG9JPXoyURqUzYGcQA8FCq6MuZfjqT/6hP8Mh4hQA==} - engines: {node: '>=0.10.4'} - winston-transport@4.9.0: resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} engines: {node: '>= 12.0.0'} @@ -9885,6 +9648,9 @@ packages: zod@3.24.2: resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} + zod@3.25.51: + resolution: {integrity: sha512-TQSnBldh+XSGL+opiSIq0575wvDPqu09AqWe1F7JhUMKY+M91/aGlK4MhpVNO7MgYfHcVCB1ffwAUTJzllKJqg==} + zrender@5.4.1: resolution: {integrity: sha512-M4Z05BHWtajY2241EmMPHglDQAJ1UyHQcYsxDNzD9XLSkPDqMq4bB28v9Pb4mvHnVQ0GxyTklZ/69xCFP6RXBA==} @@ -9969,134 +9735,6 @@ snapshots: call-me-maybe: 1.0.2 openapi-types: 12.1.3 - '@azure/abort-controller@2.1.2': - dependencies: - tslib: 2.8.1 - - '@azure/core-auth@1.9.0': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-util': 1.11.0 - tslib: 2.8.1 - - '@azure/core-client@1.9.3': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-auth': 1.9.0 - '@azure/core-rest-pipeline': 1.19.1 - '@azure/core-tracing': 1.2.0 - '@azure/core-util': 1.11.0 - '@azure/logger': 1.1.4 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@azure/core-http-compat@2.2.0': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-client': 1.9.3 - '@azure/core-rest-pipeline': 1.19.1 - transitivePeerDependencies: - - supports-color - - '@azure/core-lro@2.7.2': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-util': 1.11.0 - '@azure/logger': 1.1.4 - tslib: 2.8.1 - - '@azure/core-paging@1.6.2': - dependencies: - tslib: 2.8.1 - - '@azure/core-rest-pipeline@1.19.1': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-auth': 1.9.0 - '@azure/core-tracing': 1.2.0 - '@azure/core-util': 1.11.0 - '@azure/logger': 1.1.4 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@azure/core-tracing@1.2.0': - dependencies: - tslib: 2.8.1 - - '@azure/core-util@1.11.0': - dependencies: - '@azure/abort-controller': 2.1.2 - tslib: 2.8.1 - - '@azure/identity@4.8.0': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-auth': 1.9.0 - '@azure/core-client': 1.9.3 - '@azure/core-rest-pipeline': 1.19.1 - '@azure/core-tracing': 1.2.0 - '@azure/core-util': 1.11.0 - '@azure/logger': 1.1.4 - '@azure/msal-browser': 4.7.0 - '@azure/msal-node': 3.3.0 - events: 3.3.0 - jws: 4.0.0 - open: 10.1.0 - stoppable: 1.1.0 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@azure/keyvault-common@2.0.0': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-auth': 1.9.0 - '@azure/core-client': 1.9.3 - '@azure/core-rest-pipeline': 1.19.1 - '@azure/core-tracing': 1.2.0 - '@azure/core-util': 1.11.0 - '@azure/logger': 1.1.4 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@azure/keyvault-keys@4.9.0': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-auth': 1.9.0 - '@azure/core-client': 1.9.3 - '@azure/core-http-compat': 2.2.0 - '@azure/core-lro': 2.7.2 - '@azure/core-paging': 1.6.2 - '@azure/core-rest-pipeline': 1.19.1 - '@azure/core-tracing': 1.2.0 - '@azure/core-util': 1.11.0 - '@azure/keyvault-common': 2.0.0 - '@azure/logger': 1.1.4 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - - '@azure/logger@1.1.4': - dependencies: - tslib: 2.8.1 - - '@azure/msal-browser@4.7.0': - dependencies: - '@azure/msal-common': 15.2.1 - - '@azure/msal-common@15.2.1': {} - - '@azure/msal-node@3.3.0': - dependencies: - '@azure/msal-common': 15.2.1 - jsonwebtoken: 9.0.2 - uuid: 8.3.2 - '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.25.9 @@ -10937,7 +10575,7 @@ snapshots: '@chakra-ui/system': 2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1) react: 18.3.1 - '@chakra-ui/next-js@2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.28(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)': + '@chakra-ui/next-js@2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)': dependencies: '@chakra-ui/react': 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@emotion/cache': 11.14.0 @@ -11360,6 +10998,13 @@ snapshots: '@eslint/js@8.57.1': {} + '@fastgpt-sdk/plugin@0.1.0(@types/node@20.17.24)': + dependencies: + '@ts-rest/core': 3.52.1(@types/node@20.17.24)(zod@3.25.51) + zod: 3.25.51 + transitivePeerDependencies: + - '@types/node' + '@fastify/accept-negotiator@1.1.0': {} '@fastify/ajv-compiler@3.6.0': @@ -11660,8 +11305,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@js-joda/core@5.6.4': {} - '@js-sdsl/ordered-map@4.4.2': {} '@jsdevtools/ono@7.1.3': {} @@ -12566,12 +12209,15 @@ snapshots: optionalDependencies: react-dom: 18.3.1(react@18.3.1) - '@tediousjs/connection-string@0.5.0': {} - '@tokenizer/token@0.3.0': {} '@trysound/sax@0.2.0': {} + '@ts-rest/core@3.52.1(@types/node@20.17.24)(zod@3.25.51)': + optionalDependencies: + '@types/node': 20.17.24 + zod: 3.25.51 + '@tsconfig/node10@1.0.11': {} '@tsconfig/node12@1.0.11': {} @@ -12882,10 +12528,6 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/nodemailer@6.4.17': - dependencies: - '@types/node': 20.17.24 - '@types/nprogress@0.2.3': {} '@types/papaparse@5.3.7': @@ -12934,11 +12576,6 @@ snapshots: '@types/prop-types': 15.7.14 csstype: 3.1.3 - '@types/readable-stream@4.0.18': - dependencies: - '@types/node': 20.17.24 - safe-buffer: 5.1.2 - '@types/request-ip@0.0.37': dependencies: '@types/node': 20.17.24 @@ -13763,13 +13400,6 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - bl@6.1.0: - dependencies: - '@types/readable-stream': 4.0.18 - buffer: 6.0.3 - inherits: 2.0.4 - readable-stream: 4.7.0 - bluebird@3.4.7: {} body-parser@1.20.3: @@ -13888,10 +13518,6 @@ snapshots: esbuild: 0.25.1 node-eval: 2.0.0 - bundle-name@4.1.0: - dependencies: - run-applescript: 7.0.0 - busboy@1.6.0: dependencies: streamsearch: 1.1.0 @@ -13948,8 +13574,6 @@ snapshots: callsites@3.1.0: {} - camelcase@4.1.0: {} - camelcase@5.3.1: {} camelcase@6.3.0: {} @@ -14312,12 +13936,6 @@ snapshots: dependencies: luxon: 3.5.0 - cross-fetch@3.2.0(encoding@0.1.13): - dependencies: - node-fetch: 2.7.0(encoding@0.1.13) - transitivePeerDependencies: - - encoding - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -14648,13 +14266,6 @@ snapshots: deepmerge@4.3.1: {} - default-browser-id@5.0.0: {} - - default-browser@5.2.1: - dependencies: - bundle-name: 4.1.0 - default-browser-id: 5.0.0 - defaults@1.0.4: dependencies: clone: 1.0.4 @@ -14667,8 +14278,6 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - define-lazy-prop@3.0.0: {} - define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -14782,11 +14391,6 @@ snapshots: dotenv@16.5.0: {} - duck-duck-scrape@2.2.7: - dependencies: - html-entities: 2.5.2 - needle: 3.3.1 - duck@0.1.12: dependencies: underscore: 1.13.7 @@ -15475,8 +15079,6 @@ snapshots: exponential-backoff@3.1.2: {} - expr-eval@2.0.2: {} - express-rate-limit@7.5.0(express@5.1.0): dependencies: express: 5.1.0 @@ -16132,8 +15734,6 @@ snapshots: dependencies: react-is: 16.13.1 - html-entities@2.5.2: {} - html-escaper@2.0.2: {} html-parse-stringify@3.0.1: @@ -16190,8 +15790,6 @@ snapshots: husky@8.0.3: {} - hyntax@1.1.9: {} - hyperdown@2.4.29: {} i18next-fs-backend@2.6.0: {} @@ -16239,10 +15837,6 @@ snapshots: once: 1.4.0 wrappy: 1.0.2 - infobox-parser@3.6.2: - dependencies: - camelcase: 4.1.0 - inherits@2.0.4: {} ini@1.3.8: {} @@ -16398,8 +15992,6 @@ snapshots: is-decimal@2.0.1: {} - is-docker@3.0.0: {} - is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: @@ -16427,10 +16019,6 @@ snapshots: is-hexadecimal@2.0.1: {} - is-inside-container@1.0.0: - dependencies: - is-docker: 3.0.0 - is-installed-globally@0.4.0: dependencies: global-dirs: 3.0.1 @@ -16524,10 +16112,6 @@ snapshots: is-word-character@1.0.4: {} - is-wsl@3.1.0: - dependencies: - is-inside-container: 1.0.0 - is-yarn-global@0.4.1: {} isarray@1.0.0: {} @@ -16942,8 +16526,6 @@ snapshots: js-cookie@3.0.5: {} - js-md4@0.3.2: {} - js-tokens@4.0.0: {} js-tokens@9.0.1: {} @@ -17042,22 +16624,11 @@ snapshots: ecdsa-sig-formatter: 1.0.11 safe-buffer: 5.2.1 - jwa@2.0.0: - dependencies: - buffer-equal-constant-time: 1.0.1 - ecdsa-sig-formatter: 1.0.11 - safe-buffer: 5.2.1 - jws@3.2.2: dependencies: jwa: 1.4.1 safe-buffer: 5.2.1 - jws@4.0.0: - dependencies: - jwa: 2.0.0 - safe-buffer: 5.2.1 - kareem@2.6.3: {} katex@0.16.21: @@ -17079,9 +16650,9 @@ snapshots: langbase@1.1.44(encoding@0.1.13)(react@18.3.1): dependencies: dotenv: 16.4.7 - openai: 4.87.3(encoding@0.1.13)(zod@3.24.2) - zod: 3.24.2 - zod-validation-error: 3.4.0(zod@3.24.2) + openai: 4.87.3(encoding@0.1.13)(zod@3.25.51) + zod: 3.25.51 + zod-validation-error: 3.4.0(zod@3.25.51) optionalDependencies: react: 18.3.1 transitivePeerDependencies: @@ -18131,17 +17702,6 @@ snapshots: optionalDependencies: msgpackr-extract: 3.0.3 - mssql@11.0.1: - dependencies: - '@tediousjs/connection-string': 0.5.0 - commander: 11.1.0 - debug: 4.4.0 - rfdc: 1.4.1 - tarn: 3.0.2 - tedious: 18.6.1 - transitivePeerDependencies: - - supports-color - multer@2.0.1: dependencies: append-field: 1.0.0 @@ -18178,15 +17738,8 @@ snapshots: napi-build-utils@2.0.0: {} - native-duplexpair@1.0.0: {} - natural-compare@1.4.0: {} - needle@3.3.1: - dependencies: - iconv-lite: 0.6.3 - sax: 1.4.1 - negotiator@0.6.3: {} negotiator@0.6.4: {} @@ -18201,7 +17754,7 @@ snapshots: transitivePeerDependencies: - supports-color - next-i18next@15.4.2(i18next@23.16.8)(next@14.2.28(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + next-i18next@15.4.2(i18next@23.16.8)(next@14.2.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.10 '@types/hoist-non-react-statics': 3.3.6 @@ -18301,8 +17854,6 @@ snapshots: dependencies: xlsx: https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz - nodemailer@6.10.0: {} - non-layered-tidy-tree-layout@2.0.2: {} nopt@7.2.1: @@ -18395,14 +17946,7 @@ snapshots: dependencies: mimic-fn: 4.0.0 - open@10.1.0: - dependencies: - default-browser: 5.2.1 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - is-wsl: 3.1.0 - - openai@4.61.0(encoding@0.1.13)(zod@3.24.2): + openai@4.61.0(encoding@0.1.13)(zod@3.25.51): dependencies: '@types/node': 18.19.80 '@types/node-fetch': 2.6.12 @@ -18414,11 +17958,11 @@ snapshots: node-fetch: 2.7.0(encoding@0.1.13) qs: 6.14.0 optionalDependencies: - zod: 3.24.2 + zod: 3.25.51 transitivePeerDependencies: - encoding - openai@4.87.3(encoding@0.1.13)(zod@3.24.2): + openai@4.87.3(encoding@0.1.13)(zod@3.25.51): dependencies: '@types/node': 18.19.80 '@types/node-fetch': 2.6.12 @@ -18428,7 +17972,7 @@ snapshots: formdata-node: 4.4.1 node-fetch: 2.7.0(encoding@0.1.13) optionalDependencies: - zod: 3.24.2 + zod: 3.25.51 transitivePeerDependencies: - encoding @@ -18803,8 +18347,6 @@ snapshots: process-warning@5.0.0: {} - process@0.11.10: {} - promise-retry@2.0.1: dependencies: err-code: 2.0.3 @@ -19113,14 +18655,6 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 - readable-stream@4.7.0: - dependencies: - abort-controller: 3.0.0 - buffer: 6.0.3 - events: 3.3.0 - process: 0.11.10 - string_decoder: 1.3.0 - readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -19411,8 +18945,6 @@ snapshots: transitivePeerDependencies: - supports-color - run-applescript@7.0.0: {} - run-async@2.4.1: {} run-async@3.0.0: {} @@ -19474,8 +19006,6 @@ snapshots: optionalDependencies: '@parcel/watcher': 2.5.1 - sax@1.4.1: {} - scheduler@0.23.2: dependencies: loose-envify: 1.4.0 @@ -19745,8 +19275,6 @@ snapshots: dependencies: bl: 5.1.0 - stoppable@1.1.0: {} - streamsearch@1.1.0: {} streamx@2.22.0: @@ -19990,23 +19518,6 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 - tarn@3.0.2: {} - - tedious@18.6.1: - dependencies: - '@azure/core-auth': 1.9.0 - '@azure/identity': 4.8.0 - '@azure/keyvault-keys': 4.9.0 - '@js-joda/core': 5.6.4 - '@types/node': 20.17.24 - bl: 6.1.0 - iconv-lite: 0.6.3 - js-md4: 0.3.2 - native-duplexpair: 1.0.0 - sprintf-js: 1.1.3 - transitivePeerDependencies: - - supports-color - terser-webpack-plugin@5.3.14(webpack@5.97.1): dependencies: '@jridgewell/trace-mapping': 0.3.25 @@ -20828,14 +20339,6 @@ snapshots: dependencies: string-width: 5.1.2 - wikijs@6.4.1(encoding@0.1.13): - dependencies: - cross-fetch: 3.2.0(encoding@0.1.13) - hyntax: 1.1.9 - infobox-parser: 3.6.2 - transitivePeerDependencies: - - encoding - winston-transport@4.9.0: dependencies: logform: 2.7.0 @@ -20993,12 +20496,14 @@ snapshots: dependencies: zod: 3.24.2 - zod-validation-error@3.4.0(zod@3.24.2): + zod-validation-error@3.4.0(zod@3.25.51): dependencies: - zod: 3.24.2 + zod: 3.25.51 zod@3.24.2: {} + zod@3.25.51: {} + zrender@5.4.1: dependencies: tslib: 2.3.0 diff --git a/projects/app/.env.template b/projects/app/.env.template index cfe77df89..e69fe3b26 100644 --- a/projects/app/.env.template +++ b/projects/app/.env.template @@ -9,16 +9,23 @@ FILE_TOKEN_KEY=filetokenkey AES256_SECRET_KEY=fastgptsecret # root key, 最高权限 ROOT_KEY=fdafasd -# openai 基本地址,可用作中转。 -OPENAI_BASE_URL=https://api.openai.com/v1 -# OpenAI API Key -CHAT_API_KEY=sk-xxxx +# 强制将图片转成 base64 传递给模型 +MULTIPLE_DATA_TO_BASE64=true + +# Service url +# 商业版地址 +PRO_URL= +# Plugin +PLUGIN_BASE_URL= +PLUGIN_TOKEN= +# code sandbox url +SANDBOX_URL=http://localhost:3001 # ai proxy api AIPROXY_API_ENDPOINT=https://xxx.come AIPROXY_API_TOKEN=xxxxx - -# 强制将图片转成 base64 传递给模型 -MULTIPLE_DATA_TO_BASE64=true +# OpenAI Base URL +OPENAI_BASE_URL=https://api.openai.com/v1 +CHAT_API_KEY=sk-xxxx # Redis URL REDIS_URL=redis://default:password@127.0.0.1:6379 @@ -35,10 +42,7 @@ OCEANBASE_URL= MILVUS_ADDRESS= MILVUS_TOKEN= -# code sandbox url -SANDBOX_URL=http://localhost:3001 -# 商业版地址 -PRO_URL= + # 页面的地址,用于自动补全相对路径资源的 domain,注意后面不要跟 / FE_DOMAIN=http://localhost:3000 # 文件域名,也是指向 FastGPT 服务,但是如果希望内容足够安全,可以独立分配一个域名,避免高危文件读取到主域名的内容。 diff --git a/projects/app/next.config.js b/projects/app/next.config.js index bf45c195e..39ea4e1c7 100644 --- a/projects/app/next.config.js +++ b/projects/app/next.config.js @@ -36,7 +36,7 @@ const nextConfig = { key: 'Permissions-Policy', value: 'geolocation=(self), microphone=(self), camera=(self)' } - ] + ], } ]; }, @@ -71,6 +71,7 @@ const nextConfig = { if (isServer) { config.externals.push('@node-rs/jieba'); + if (nextRuntime === 'nodejs') { const oldEntry = config.entry; config = { @@ -79,11 +80,7 @@ const nextConfig = { const entries = await oldEntry(...args); return { ...entries, - ...getWorkerConfig(), - 'worker/systemPluginRun': path.resolve( - process.cwd(), - '../../packages/plugins/runtime/worker.ts' - ) + ...getWorkerConfig() }; } }; diff --git a/projects/app/package.json b/projects/app/package.json index 4730dc226..52343e063 100644 --- a/projects/app/package.json +++ b/projects/app/package.json @@ -19,7 +19,6 @@ "@emotion/react": "11.11.1", "@emotion/styled": "11.11.0", "@fastgpt/global": "workspace:*", - "@fastgpt/plugins": "workspace:*", "@fastgpt/service": "workspace:*", "@fastgpt/templates": "workspace:*", "@fastgpt/web": "workspace:*", diff --git a/projects/app/src/components/Markdown/utils.ts b/projects/app/src/components/Markdown/utils.ts index d274be4ac..544585bba 100644 --- a/projects/app/src/components/Markdown/utils.ts +++ b/projects/app/src/components/Markdown/utils.ts @@ -29,12 +29,13 @@ export const mdTextFormat = (text: string) => { // 处理 [quote:id] 格式引用,将 [quote:675934a198f46329dfc6d05a] 转换为 [675934a198f46329dfc6d05a](CITE) text = text - // .replace( - // /([\u4e00-\u9fa5\u3000-\u303f])([a-zA-Z0-9])|([a-zA-Z0-9])([\u4e00-\u9fa5\u3000-\u303f])/g, - // '$1$3 $2$4' - // ) // 处理 格式引用,将 [675934a198f46329dfc6d05a] 转换为 [675934a198f46329dfc6d05a](CITE) .replace(/\[([a-f0-9]{24})\](?!\()/g, '[$1](CITE)'); + // 将 "http://localhost:3000[675934a198f46329dfc6d05a](CITE)" -> "http://localhost:3000 [675934a198f46329dfc6d05a](CITE)" + text = text.replace( + /(https?:\/\/[^\s,。!?;:、\[\]]+?)(?=\[([a-f0-9]{24})\]\(CITE\))/g, + '$1 ' + ); // 处理链接后的中文标点符号,增加空格 text = text.replace(/(https?:\/\/[^\s,。!?;:、]+)([,。!?;:、])/g, '$1 $2'); diff --git a/projects/app/src/components/Select/I18nLngSelector.tsx b/projects/app/src/components/Select/I18nLngSelector.tsx index 38dae39fa..552dfe521 100644 --- a/projects/app/src/components/Select/I18nLngSelector.tsx +++ b/projects/app/src/components/Select/I18nLngSelector.tsx @@ -1,10 +1,10 @@ -import { langMap } from '@/web/common/utils/i18n'; import { Box, Flex } from '@chakra-ui/react'; import MySelect from '@fastgpt/web/components/common/MySelect'; import { useI18nLng } from '@fastgpt/web/hooks/useI18n'; import { useTranslation } from 'next-i18next'; import { useMemo } from 'react'; import MyIcon from '@fastgpt/web/components/common/Icon'; +import { langMap } from '@fastgpt/global/common/i18n/type'; const I18nLngSelector = () => { const { i18n } = useTranslation(); diff --git a/projects/app/src/components/common/secret/HeaderAuthConfig.tsx b/projects/app/src/components/common/secret/HeaderAuthConfig.tsx index aa2043634..4ac3656c3 100644 --- a/projects/app/src/components/common/secret/HeaderAuthConfig.tsx +++ b/projects/app/src/components/common/secret/HeaderAuthConfig.tsx @@ -8,7 +8,6 @@ import { Input, ModalBody, ModalFooter, - Slider, useDisclosure } from '@chakra-ui/react'; import { HeaderSecretTypeEnum } from '@fastgpt/global/common/secret/constants'; diff --git a/projects/app/src/components/core/app/DatasetSelectModal.tsx b/projects/app/src/components/core/app/DatasetSelectModal.tsx index 561d3c1c6..2b26cba35 100644 --- a/projects/app/src/components/core/app/DatasetSelectModal.tsx +++ b/projects/app/src/components/core/app/DatasetSelectModal.tsx @@ -11,7 +11,7 @@ import { Divider } from '@chakra-ui/react'; import Avatar from '@fastgpt/web/components/common/Avatar'; -import type { SelectedDatasetType } from '@fastgpt/global/core/workflow/api.d'; +import type { SelectedDatasetType } from '@fastgpt/global/core/workflow/type/io'; import { useToast } from '@fastgpt/web/hooks/useToast'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import MyIcon from '@fastgpt/web/components/common/Icon'; diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ContextModal.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ContextModal.tsx index a045d1aec..8fb9081e9 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ContextModal.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ContextModal.tsx @@ -9,7 +9,7 @@ import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { useTranslation } from 'next-i18next'; import { getFlatAppResponses } from '@/global/core/chat/utils'; const isLLMNode = (item: ChatHistoryItemResType) => - item.moduleType === FlowNodeTypeEnum.chatNode || item.moduleType === FlowNodeTypeEnum.tools; + item.moduleType === FlowNodeTypeEnum.chatNode || item.moduleType === FlowNodeTypeEnum.agent; const ContextModal = ({ onClose, dataId }: { onClose: () => void; dataId: string }) => { const { getHistoryResponseData } = useContextSelector(ChatBoxContext, (v) => v); diff --git a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/renderPluginInput.tsx b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/renderPluginInput.tsx index ae398fe1d..bff701bbe 100644 --- a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/renderPluginInput.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/renderPluginInput.tsx @@ -1,5 +1,5 @@ -import { Box, Button, Flex, Switch, Textarea, useDisclosure } from '@chakra-ui/react'; -import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants'; +import { Box, Button, Flex, Switch, Textarea } from '@chakra-ui/react'; +import { NodeInputKeyEnum, WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants'; import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { type FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; @@ -12,7 +12,7 @@ import { useContextSelector } from 'use-context-selector'; import MyIcon from '@fastgpt/web/components/common/Icon'; import FilePreview from '../../components/FilePreview'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; -import { useEffect, useMemo } from 'react'; +import { useEffect } from 'react'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; import { useFieldArray } from 'react-hook-form'; import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput'; @@ -22,6 +22,11 @@ import { ChatRecordContext } from '@/web/core/chat/context/chatRecordContext'; import { PluginRunContext } from '../context'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import AIModelSelector from '@/components/Select/AIModelSelector'; +import SecretInputModal, { + type ToolParamsFormType +} from '@/pageComponents/app/plugin/SecretInputModal'; +import { SystemToolInputTypeMap } from '@fastgpt/global/core/app/systemTool/constants'; +import { useBoolean } from 'ahooks'; const JsonEditor = dynamic(() => import('@fastgpt/web/components/common/Textarea/JsonEditor')); @@ -143,7 +148,11 @@ const RenderPluginInput = ({ isDisabled, isInvalid, input, - setUploading + setUploading, + + hasSystemSecret, + secretCost, + courseUrl }: { value: any; onChange: (...event: any[]) => void; @@ -151,11 +160,18 @@ const RenderPluginInput = ({ isInvalid: boolean; input: FlowNodeInputItemType; setUploading: React.Dispatch>; + + hasSystemSecret?: boolean; + secretCost?: number; + courseUrl?: string; }) => { const { t } = useTranslation(); const inputType = input.renderTypeList[0]; const { llmModelList } = useSystemStore(); + const [isOpenSecretModal, { setTrue: setTrueSecretModal, setFalse: setFalseSecretModal }] = + useBoolean(false); + const render = (() => { if (inputType === FlowNodeInputTypeEnum.select && input.list) { return ( @@ -215,6 +231,48 @@ const RenderPluginInput = ({ /> ); } + if (input.key === NodeInputKeyEnum.systemInputConfig && input.inputList) { + return ( + + {t('common:secret_key')} + + + {isOpenSecretModal && ( + { + onChange(data); + setFalseSecretModal(); + }} + /> + )} + + ); + } return ( - item.moduleType === FlowNodeTypeEnum.chatNode || item.moduleType === FlowNodeTypeEnum.tools; + item.moduleType === FlowNodeTypeEnum.chatNode || item.moduleType === FlowNodeTypeEnum.agent; export function transformPreviewHistories( histories: ChatItemType[], diff --git a/projects/app/src/instrumentation.ts b/projects/app/src/instrumentation.ts index 186a52cee..2616b56d0 100644 --- a/projects/app/src/instrumentation.ts +++ b/projects/app/src/instrumentation.ts @@ -14,7 +14,6 @@ export async function register() { { initGlobalVariables, getInitConfig, initSystemPluginGroups, initAppTemplateTypes }, { initVectorStore }, { initRootUser }, - { getSystemPluginCb }, { startMongoWatch }, { startCron }, { startTrainingQueue }, @@ -27,7 +26,6 @@ export async function register() { import('@/service/common/system'), import('@fastgpt/service/common/vectorDB/controller'), import('@/service/mongo'), - import('@/service/core/app/plugin'), import('@/service/common/system/volumnMongoWatch'), import('@/service/common/system/cron'), import('@/service/core/dataset/training/utils'), @@ -55,7 +53,7 @@ export async function register() { // 异步加载 initSystemPluginGroups(); initAppTemplateTypes(); - getSystemPluginCb(); + // getSystemPlugins(true); startMongoWatch(); startCron(); startTrainingQueue(true); diff --git a/projects/app/src/pageComponents/app/detail/SimpleApp/components/ConfigToolModal.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/components/ConfigToolModal.tsx index 5054a2c0b..ec244b9e8 100644 --- a/projects/app/src/pageComponents/app/detail/SimpleApp/components/ConfigToolModal.tsx +++ b/projects/app/src/pageComponents/app/detail/SimpleApp/components/ConfigToolModal.tsx @@ -49,7 +49,7 @@ const ConfigToolModal = ({ > - + {t('app:tool_input_param_tip')} {!!(configTool?.courseUrl || configTool?.userGuide) && ( {}} + hasSystemSecret={configTool.hasSystemSecret} + secretCost={configTool.currentCost} + courseUrl={configTool.courseUrl} /> ); }} @@ -103,7 +106,7 @@ const ConfigToolModal = ({ ); })} - + diff --git a/projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelectModal.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelectModal.tsx index 135e465b8..ccda4ea86 100644 --- a/projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelectModal.tsx +++ b/projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelectModal.tsx @@ -35,7 +35,6 @@ import { type ParentIdType } from '@fastgpt/global/common/parentFolder/type'; import { getAppFolderPath } from '@/web/core/app/api/app'; import FolderPath from '@/components/common/folder/Path'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; -import CostTooltip from '@/components/core/app/plugin/CostTooltip'; import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { useContextSelector } from 'use-context-selector'; import { AppContext } from '../../context'; @@ -190,13 +189,15 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void }) )} - - + + + + ); @@ -269,38 +270,27 @@ const RenderList = React.memo(function RenderList({ if (input.key === NodeInputKeyEnum.forbidStream) { return false; } - if (input.renderTypeList.includes(FlowNodeInputTypeEnum.input)) { + if (input.key === NodeInputKeyEnum.systemInputConfig) { return true; } - if (input.renderTypeList.includes(FlowNodeInputTypeEnum.textarea)) { - return true; - } - if (input.renderTypeList.includes(FlowNodeInputTypeEnum.numberInput)) { - return true; - } - if (input.renderTypeList.includes(FlowNodeInputTypeEnum.switch)) { - return true; - } - if (input.renderTypeList.includes(FlowNodeInputTypeEnum.select)) { - return true; - } - if (input.renderTypeList.includes(FlowNodeInputTypeEnum.JSONEditor)) { - return true; - } - return false; + + // Check if input has any of the form render types + const formRenderTypes = [ + FlowNodeInputTypeEnum.input, + FlowNodeInputTypeEnum.textarea, + FlowNodeInputTypeEnum.numberInput, + FlowNodeInputTypeEnum.switch, + FlowNodeInputTypeEnum.select, + FlowNodeInputTypeEnum.JSONEditor + ]; + + return formRenderTypes.some((type) => input.renderTypeList.includes(type)); }); // 构建默认表单数据 const defaultForm = { ...res, inputs: res.inputs.map((input) => { - // 如果是模型选择类型,使用当前选中的模型 - // if (input.renderTypeList.includes(FlowNodeInputTypeEnum.selectLLMModel)) { - // return { - // ...input, - // value: selectedModel.model - // }; - // } // 如果是文件上传类型,设置为从工作流开始节点获取用户文件 if (input.renderTypeList.includes(FlowNodeInputTypeEnum.fileSelect)) { return { @@ -423,12 +413,12 @@ const RenderList = React.memo(function RenderList({ {t(template.intro as any) || t('common:core.workflow.Not intro')} - {type === TemplateTypeEnum.systemPlugin && ( + {/* {type === TemplateTypeEnum.systemPlugin && ( - )} + )} */} } > @@ -535,7 +525,7 @@ const RenderList = React.memo(function RenderList({ return templates.length === 0 ? ( ) : ( - + <> {formatTemplatesArray.length > 1 ? ( <> @@ -571,6 +561,6 @@ const RenderList = React.memo(function RenderList({ onAddTool={onAddTool} /> )} - + ); }); diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/NodeTemplatesModal.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/NodeTemplatesModal.tsx index 24398948e..78a2d5209 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/NodeTemplatesModal.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/NodeTemplatesModal.tsx @@ -1,14 +1,15 @@ -import React from 'react'; -import { Box } from '@chakra-ui/react'; import type { FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node.d'; import { type Node } from 'reactflow'; -import { useContextSelector } from 'use-context-selector'; -import MyBox from '@fastgpt/web/components/common/MyBox'; -import { WorkflowNodeEdgeContext } from '../context/workflowInitContext'; -import { useMemoizedFn } from 'ahooks'; import NodeTemplateListHeader from './components/NodeTemplates/header'; import NodeTemplateList from './components/NodeTemplates/list'; import { useNodeTemplates } from './components/NodeTemplates/useNodeTemplates'; +import { Box } from '@chakra-ui/react'; +import MyBox from '@fastgpt/web/components/common/MyBox'; +import { useMemoizedFn } from 'ahooks'; +import React from 'react'; +import { XYPosition } from 'reactflow'; +import { useContextSelector } from 'use-context-selector'; +import { WorkflowNodeEdgeContext } from '../context/workflowInitContext'; type ModuleTemplateListProps = { isOpen: boolean; diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/HelperLines.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/HelperLines.tsx index 9b048df6f..35489e9a1 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/HelperLines.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/HelperLines.tsx @@ -1,4 +1,4 @@ -import { type THelperLine } from '@fastgpt/global/core/workflow/type'; +import { type THelperLine } from '@/web/core/workflow/type'; import { type CSSProperties, useEffect, useRef } from 'react'; import { type ReactFlowState, useStore, useViewport } from 'reactflow'; diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/IOTitle.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/IOTitle.tsx index 942136bcc..0b0833c62 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/IOTitle.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/IOTitle.tsx @@ -1,11 +1,24 @@ import React from 'react'; import { Box, type StackProps, HStack } from '@chakra-ui/react'; +import type { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io'; +import ToolParamConfig from './ToolParamConfig'; -const IOTitle = ({ text, ...props }: { text?: 'Input' | 'Output' | string } & StackProps) => { +const IOTitle = ({ + text, + inputs, + nodeId, + ...props +}: { + text?: 'Input' | 'Output' | string; + inputs?: FlowNodeInputItemType[]; + nodeId?: string; +} & StackProps) => { return ( {text} + + ); }; diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/list.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/list.tsx index 4b01f95fc..792e53ce2 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/list.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/list.tsx @@ -9,8 +9,7 @@ import { Grid, Flex, HStack, - css, - useToast + css } from '@chakra-ui/react'; import { useTranslation } from 'react-i18next'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; @@ -45,6 +44,7 @@ import { useReactFlow, type Node } from 'reactflow'; import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { nodeTemplate2FlowNode } from '@/web/core/workflow/utils'; import { WorkflowEventContext } from '../../../context/workflowEventContext'; +import { useToast } from '@fastgpt/web/hooks/useToast'; export type TemplateListProps = { onAddNode: ({ newNodes }: { newNodes: Node[] }) => void; @@ -93,9 +93,9 @@ const NodeTemplateListItem = ({ {t(template.intro as any) || t('common:core.workflow.Not intro')} - {templateType === TemplateTypeEnum.systemPlugin && ( + {/* {templateType === TemplateTypeEnum.systemPlugin && ( - )} + )} */} } shouldWrapChildren={false} @@ -160,7 +160,7 @@ const NodeTemplateListItem = ({ {/* Folder right arrow */} - {template.isFolder && templateType === TemplateTypeEnum.teamPlugin && ( + {template.isFolder && ( { const { t } = useTranslation(); - const toast = useToast(); + const { toast } = useToast(); const { computedNewNodeName } = useWorkflowUtils(); const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList); const handleParams = useContextSelector(WorkflowEventContext, (v) => v.handleParams); @@ -227,8 +227,7 @@ const NodeTemplateList = ({ const templateNode = await (async () => { try { if (AppNodeFlowNodeTypeMap[template.flowNodeType]) { - const res = await getPreviewPluginNode({ appId: template.id }); - return res; + return await getPreviewPluginNode({ appId: template.id }); } const baseTemplate = moduleTemplatesFlat.find((item) => item.id === template.id); @@ -239,7 +238,7 @@ const NodeTemplateList = ({ } catch (e) { toast({ status: 'error', - title: getErrText(e, t('common:core.plugin.Get Plugin Module Detail Failed')) + title: t(getErrText(e, t('common:core.plugin.Get Plugin Module Detail Failed'))) }); return Promise.reject(e); } @@ -277,7 +276,7 @@ const NodeTemplateList = ({ .filter((input) => input.deprecated !== true) .map((input) => ({ ...input, - value: defaultValueMap[input.key] ?? input.value, + value: defaultValueMap[input.key] ?? input.value ?? input.defaultValue, valueDesc: t(input.valueDesc as any), label: t(input.label as any), description: t(input.description as any), @@ -355,7 +354,10 @@ const NodeTemplateList = ({ }); } - const copy: NodeTemplateListType = cloneDeep(workflowNodeTemplateList); + const copy: NodeTemplateListType = cloneDeep(workflowNodeTemplateList).map((item) => ({ + ...item, + list: [] + })); templates.forEach((item) => { const index = copy.findIndex((template) => template.type === item.templateType); if (index === -1) return; diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/useNodeTemplates.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/useNodeTemplates.tsx index 00f83566f..50892ba1b 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/useNodeTemplates.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/useNodeTemplates.tsx @@ -19,7 +19,7 @@ export const useNodeTemplates = () => { const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList); const hasToolNode = useMemo( - () => nodeList.some((node) => node.flowNodeType === FlowNodeTypeEnum.tools), + () => nodeList.some((node) => node.flowNodeType === FlowNodeTypeEnum.agent), [nodeList] ); diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/ToolParamConfig.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/ToolParamConfig.tsx new file mode 100644 index 000000000..0fbaef78e --- /dev/null +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/ToolParamConfig.tsx @@ -0,0 +1,76 @@ +import React, { useMemo } from 'react'; +import type { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io'; +import { useTranslation } from 'next-i18next'; +import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; +import { Box, Button } from '@chakra-ui/react'; +import { useBoolean } from 'ahooks'; +import { useContextSelector } from 'use-context-selector'; +import { WorkflowContext } from '../../context'; +import { SystemToolInputTypeMap } from '@fastgpt/global/core/app/systemTool/constants'; +import SecretInputModal, { + type ToolParamsFormType +} from '@/pageComponents/app/plugin/SecretInputModal'; + +const ToolConfig = ({ nodeId, inputs }: { nodeId?: string; inputs?: FlowNodeInputItemType[] }) => { + const { t } = useTranslation(); + const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode); + const node = useContextSelector(WorkflowContext, (v) => + v.nodeList.find((item) => item.nodeId === nodeId) + ); + + const inputConfig = inputs?.find((item) => item.key === NodeInputKeyEnum.systemInputConfig); + const inputList = inputConfig?.inputList; + const [isOpen, { setTrue, setFalse }] = useBoolean(false); + + const activeButtonText = useMemo(() => { + const val = inputConfig?.value as ToolParamsFormType; + if (!val) { + return t('workflow:tool_active_config'); + } + + return t('workflow:tool_active_config_type', { + type: t(SystemToolInputTypeMap[val.type]?.text as any) + }); + }, [inputConfig?.value, t]); + + const onSubmit = (data: ToolParamsFormType) => { + if (!inputConfig) return; + + onChangeNode({ + nodeId: nodeId as string, + type: 'updateInput', + key: inputConfig.key, + value: { + ...inputConfig, + value: data + } + }); + setFalse(); + }; + + return nodeId && !!inputList && inputList.length > 0 ? ( + <> + + {isOpen && ( + + )} + + ) : null; +}; + +export default React.memo(ToolConfig); diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useWorkflow.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useWorkflow.tsx index 486a644b1..60a149b16 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useWorkflow.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useWorkflow.tsx @@ -21,7 +21,7 @@ import { useTranslation } from 'next-i18next'; import { useKeyboard } from './useKeyboard'; import { useContextSelector } from 'use-context-selector'; import { WorkflowContext } from '../../context'; -import { type THelperLine } from '@fastgpt/global/core/workflow/type'; +import { type THelperLine } from '@/web/core/workflow/type'; import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { useDebounceEffect, useMemoizedFn } from 'ahooks'; import { type FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node'; @@ -662,7 +662,7 @@ export const useWorkflow = () => { // 1. Add file input if ( node.flowNodeType === FlowNodeTypeEnum.chatNode || - node.flowNodeType === FlowNodeTypeEnum.tools || + node.flowNodeType === FlowNodeTypeEnum.agent || node.flowNodeType === FlowNodeTypeEnum.appModule ) { const input = node.inputs.find((i) => i.key === NodeInputKeyEnum.fileUrlList); diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/index.tsx index 4dd9d1ff1..b692f7d6a 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/index.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/index.tsx @@ -1,26 +1,25 @@ -import React from 'react'; -import ReactFlow, { type NodeProps, SelectionMode } from 'reactflow'; -import { Box, IconButton, useDisclosure } from '@chakra-ui/react'; -import { EDGE_TYPE, FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; - import dynamic from 'next/dynamic'; - import ButtonEdge from './components/ButtonEdge'; import NodeTemplatesModal from './NodeTemplatesModal'; - import 'reactflow/dist/style.css'; import { type FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node.d'; import { connectionLineStyle, defaultEdgeOptions, maxZoom, minZoom } from '../constants'; +import 'reactflow/dist/style.css'; import { useContextSelector } from 'use-context-selector'; -import { useWorkflow } from './hooks/useWorkflow'; -import HelperLines from './components/HelperLines'; -import FlowController from './components/FlowController'; -import ContextMenu from './components/ContextMenu'; -import { WorkflowNodeEdgeContext, WorkflowInitContext } from '../context/workflowInitContext'; import { WorkflowEventContext } from '../context/workflowEventContext'; import NodeTemplatesPopover from './NodeTemplatesPopover'; import SearchButton from '../../Workflow/components/SearchButton'; import MyIcon from '@fastgpt/web/components/common/Icon'; +import { WorkflowInitContext, WorkflowNodeEdgeContext } from '../context/workflowInitContext'; +import ContextMenu from './components/ContextMenu'; +import FlowController from './components/FlowController'; +import HelperLines from './components/HelperLines'; +import { useWorkflow } from './hooks/useWorkflow'; +import { EDGE_TYPE, FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; +import type { NodeProps } from 'reactflow'; +import ReactFlow, { SelectionMode } from 'reactflow'; +import { Box, IconButton, useDisclosure } from '@chakra-ui/react'; +import React from 'react'; const NodeSimple = dynamic(() => import('./nodes/NodeSimple')); const nodeTypes: Record = { @@ -45,11 +44,11 @@ const nodeTypes: Record = { [FlowNodeTypeEnum.pluginOutput]: dynamic(() => import('./nodes/NodePluginIO/PluginOutput')), [FlowNodeTypeEnum.pluginModule]: NodeSimple, [FlowNodeTypeEnum.queryExtension]: NodeSimple, - [FlowNodeTypeEnum.tools]: dynamic(() => import('./nodes/NodeTools')), + [FlowNodeTypeEnum.agent]: dynamic(() => import('./nodes/NodeTools')), [FlowNodeTypeEnum.stopTool]: (data: NodeProps) => ( ), - [FlowNodeTypeEnum.tool]: dynamic(() => import('./nodes/NodeTool')), + [FlowNodeTypeEnum.tool]: NodeSimple, [FlowNodeTypeEnum.toolSet]: dynamic(() => import('./nodes/NodeToolSet')), [FlowNodeTypeEnum.toolParams]: dynamic(() => import('./nodes/NodeToolParams')), [FlowNodeTypeEnum.lafModule]: dynamic(() => import('./nodes/NodeLaf')), diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx index 6feb10e0e..a547c4e5c 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx @@ -38,7 +38,7 @@ const NodeDatasetConcat = ({ data, selected }: NodeProps) => { let maxTokens = 0; nodeList.forEach((item) => { - if ([FlowNodeTypeEnum.chatNode, FlowNodeTypeEnum.tools].includes(item.flowNodeType)) { + if ([FlowNodeTypeEnum.chatNode, FlowNodeTypeEnum.agent].includes(item.flowNodeType)) { const model = item.inputs.find((item) => item.key === NodeInputKeyEnum.aiModel)?.value || ''; const quoteMaxToken = getWebLLMModel(model)?.quoteMaxToken || 0; diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeSimple.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeSimple.tsx index 517fb970f..697bce661 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeSimple.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeSimple.tsx @@ -24,7 +24,6 @@ const NodeSimple = ({ const Render = useMemo(() => { const { isTool, commonInputs } = splitToolInputs(inputs, nodeId); - const filterHiddenInputs = commonInputs.filter((item) => true); return ( @@ -35,10 +34,10 @@ const NodeSimple = ({ )} - {filterHiddenInputs.length > 0 && ( + {commonInputs.length > 0 && ( <> - + diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolSet.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolSet.tsx index 428b31f2d..efd263456 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolSet.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolSet.tsx @@ -13,7 +13,6 @@ const NodeToolSet = ({ data, selected }: NodeProps) => { const { inputs } = data; const toolList: McpToolConfigType[] = inputs[0]?.value?.toolList; - return ( diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeTools.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeTools.tsx index b463b1ce0..dd43902f4 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeTools.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeTools.tsx @@ -16,7 +16,7 @@ const NodeTools = ({ data, selected }: NodeProps) => { const { nodeId, inputs, outputs } = data; return ( - + diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx index 4f253982c..32234b812 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx @@ -44,7 +44,7 @@ export const ConnectionSourceHandle = ({ */ if ( !(isFoldNode && node?.outputs.length) && - (!node || !node?.sourceHandle?.right || rightTargetConnected) + (!node || !node?.showSourceHandle || rightTargetConnected) ) return null; @@ -125,7 +125,7 @@ export const ConnectionTargetHandle = React.memo(function ConnectionTargetHandle })(); const LeftHandle = (() => { - if (!node || !node?.targetHandle?.left) return null; + if (!node || !node?.showTargetHandle) return null; const handleId = getHandleId(nodeId, 'target', Position.Left); diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/NodeCard.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/NodeCard.tsx index 4025b4017..eecf112ed 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/NodeCard.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/NodeCard.tsx @@ -30,13 +30,14 @@ import MyImage from '@fastgpt/web/components/common/Image/MyImage'; import MyIconButton from '@fastgpt/web/components/common/Icon/button'; import UseGuideModal from '@/components/common/Modal/UseGuideModal'; import NodeDebugResponse from './RenderDebug/NodeDebugResponse'; -import { getAppVersionList } from '@/web/core/app/api/version'; import { useScrollPagination } from '@fastgpt/web/hooks/useScrollPagination'; import MyTag from '@fastgpt/web/components/common/Tag/index'; import MySelect from '@fastgpt/web/components/common/MySelect'; -import { useCreation } from 'ahooks'; +import { useBoolean, useCreation } from 'ahooks'; import { formatToolError } from '@fastgpt/global/core/app/utils'; import HighlightText from '@fastgpt/web/components/common/String/HighlightText'; +import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; +import SecretInputModal from '@/pageComponents/app/plugin/SecretInputModal'; type Props = FlowNodeItemType & { children?: React.ReactNode | React.ReactNode[] | string; @@ -78,13 +79,20 @@ const NodeCard = (props: Props) => { isError = false, debugResult, isFolded, - customStyle + customStyle, + inputs } = props; const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList); const onUpdateNodeError = useContextSelector(WorkflowContext, (v) => v.onUpdateNodeError); const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode); const setHoverNodeId = useContextSelector(WorkflowEventContext, (v) => v.setHoverNodeId); + const inputConfig = inputs?.find((item) => item.key === NodeInputKeyEnum.systemInputConfig); + const [ + isOpenToolParamConfigModal, + { setTrue: onOpenToolParamConfigModal, setFalse: onCloseToolParamConfigModal } + ] = useBoolean(false); + // custom title edit const { onOpenModal: onOpenCustomTitleModal, EditModal: EditTitleModal } = useEditTitle({ title: t('common:custom_title'), @@ -92,7 +100,7 @@ const NodeCard = (props: Props) => { }); const showToolHandle = useMemo( - () => isTool && !!nodeList.find((item) => item?.flowNodeType === FlowNodeTypeEnum.tools), + () => isTool && !!nodeList.find((item) => item?.flowNodeType === FlowNodeTypeEnum.agent), [isTool, nodeList] ); @@ -107,9 +115,12 @@ const NodeCard = (props: Props) => { }, [nodeList, nodeId]); const isAppNode = node && AppNodeFlowNodeTypeMap[node?.flowNodeType]; const showVersion = useMemo(() => { - if (!isAppNode || !node?.pluginId || node?.pluginData?.error) return false; - if ([FlowNodeTypeEnum.tool, FlowNodeTypeEnum.toolSet].includes(node.flowNodeType)) return false; - return typeof node.version === 'string'; + // 1. Team app/System commercial plugin + if (isAppNode && node?.pluginId && !node?.pluginData?.error) return true; + // 2. System tool + if (isAppNode && node.toolConfig) return true; + + return false; }, [isAppNode, node]); const { data: nodeTemplate } = useRequest2( @@ -315,7 +326,7 @@ const NodeCard = (props: Props) => { }, [nodeId, isFolded]); const RenderToolHandle = useMemo( () => - node?.flowNodeType === FlowNodeTypeEnum.tools ? : null, + node?.flowNodeType === FlowNodeTypeEnum.agent ? : null, [node?.flowNodeType, nodeId] ); @@ -361,13 +372,60 @@ const NodeCard = (props: Props) => { > {debugResult && } {Header} - - {!isFolded ? children : } + + + {!isFolded ? ( + <> + {inputConfig && !inputConfig?.value ? ( + + {t('app:tool_not_active')} + + + ) : ( + children + )} + + ) : ( + + )} + {RenderHandle} {RenderToolHandle} + {inputConfig && isOpenToolParamConfigModal && ( + { + onChangeNode({ + nodeId: nodeId as string, + type: 'updateInput', + key: inputConfig.key, + value: { + ...inputConfig, + value: data + } + }); + onCloseToolParamConfigModal(); + }} + courseUrl={node?.courseUrl} + inputConfig={inputConfig} + hasSystemSecret={node?.hasSystemSecret} + secretCost={node?.currentCost} + /> + )} ); }; @@ -626,7 +684,7 @@ const NodeVersion = React.memo(function NodeVersion({ node }: { node: FlowNodeIt const { ScrollData, data: versionList } = useScrollPagination(getToolVersionList, { pageSize: 20, params: { - toolId: node.pluginId + pluginId: node.pluginId }, refreshDeps: [node.pluginId, isOpen], disalbed: !isOpen, diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/DynamicInputs/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/DynamicInputs/index.tsx index 517ad4aa7..c79f6bec6 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/DynamicInputs/index.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/DynamicInputs/index.tsx @@ -12,7 +12,7 @@ import { import { useContextSelector } from 'use-context-selector'; import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { defaultInput } from '../../FieldEditModal'; -import { getInputComponentProps } from '@fastgpt/global/core/workflow/node/io/utils'; +import { getInputComponentProps } from '@/web/core/workflow/utils'; import { ReferSelector, useReference } from '../Reference'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import ValueTypeLabel from '../../../ValueTypeLabel'; diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/NumberInput.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/NumberInput.tsx index 3f3ee3192..8bb6ef81b 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/NumberInput.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/NumberInput.tsx @@ -13,6 +13,7 @@ const NumberInputRender = ({ item, nodeId }: RenderInputProps) => { value={item.value} min={item.min} max={item.max} + precision={item.precision} inputFieldProps={{ bg: 'white' }} rounded={'md'} onChange={(e) => { diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDataset.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDataset.tsx index 22fbc24b6..e66719531 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDataset.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDataset.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import type { RenderInputProps } from '../type'; import { Box, Button, Flex, Grid, Switch, useDisclosure, useTheme } from '@chakra-ui/react'; -import { type SelectedDatasetType } from '@fastgpt/global/core/workflow/api'; +import { type SelectedDatasetType } from '@fastgpt/global/core/workflow/type/io'; import Avatar from '@fastgpt/web/components/common/Avatar'; import { useTranslation } from 'next-i18next'; import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants'; diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDatasetParams.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDatasetParams.tsx index 60b744122..4fa622577 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDatasetParams.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/SelectDatasetParams.tsx @@ -38,7 +38,7 @@ const SelectDatasetParam = ({ inputs = [], nodeId }: RenderInputProps) => { let maxTokens = 0; nodeList.forEach((item) => { - if ([FlowNodeTypeEnum.chatNode, FlowNodeTypeEnum.tools].includes(item.flowNodeType)) { + if ([FlowNodeTypeEnum.chatNode, FlowNodeTypeEnum.agent].includes(item.flowNodeType)) { const model = item.inputs.find((item) => item.key === NodeInputKeyEnum.aiModel)?.value || ''; const quoteMaxToken = getWebLLMModel(model)?.quoteMaxToken ?? 0; diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx index 21e8f7345..25fb70a4c 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx @@ -7,7 +7,6 @@ import { } from '@/web/core/workflow/utils'; import { getErrText } from '@fastgpt/global/common/error/utils'; import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; -import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { type RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type'; import { type FlowNodeItemType, @@ -18,8 +17,10 @@ import { type RuntimeEdgeItemType, type StoreEdgeItemType } from '@fastgpt/global/core/workflow/type/edge'; -import { type FlowNodeChangeProps } from '@fastgpt/global/core/workflow/type/fe'; -import { type FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io'; +import { + type FlowNodeOutputItemType, + type FlowNodeInputItemType +} from '@fastgpt/global/core/workflow/type/io'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { useMemoizedFn, useUpdateEffect } from 'ahooks'; import React, { @@ -98,6 +99,52 @@ export type WorkflowSnapshotsType = WorkflowStateType & { diff?: any; }; +type FlowNodeChangeProps = { nodeId: string } & ( + | { + type: 'attr'; // key: attr, value: new value + key: string; + value: any; + } + | { + type: 'updateInput'; // key: update input key, value: new input value + key: string; + value: FlowNodeInputItemType; + } + | { + type: 'replaceInput'; // key: old input key, value: new input value + key: string; + value: FlowNodeInputItemType; + } + | { + type: 'addInput'; // key: null, value: new input value + value: FlowNodeInputItemType; + index?: number; + } + | { + type: 'delInput'; // key: delete input key, value: null + key: string; + } + | { + type: 'updateOutput'; // key: update output key, value: new output value + key: string; + value: FlowNodeOutputItemType; + } + | { + type: 'replaceOutput'; // key: old output key, value: new output value + key: string; + value: FlowNodeOutputItemType; + } + | { + type: 'addOutput'; // key: null, value: new output value + value: FlowNodeOutputItemType; + index?: number; + } + | { + type: 'delOutput'; // key: delete output key, value: null + key: string; + } +); + type WorkflowContextType = { appId?: string; basicNodeTemplates: FlowNodeTemplateType[]; diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/utils.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/utils.tsx index 839b4e6d0..2ad07e67c 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/utils.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/utils.tsx @@ -8,7 +8,7 @@ import { type StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node.d'; import { type TFunction } from 'i18next'; -import { type Node, type Edge } from 'reactflow'; +import { type Edge, type Node } from 'reactflow'; export const uiWorkflow2StoreWorkflow = ({ nodes, @@ -29,8 +29,9 @@ export const uiWorkflow2StoreWorkflow = ({ version: item.data.version, inputs: item.data.inputs, outputs: item.data.outputs, + isFolded: item.data.isFolded, pluginId: item.data.pluginId, - isFolded: item.data.isFolded + toolConfig: item.data.toolConfig })); // get all handle diff --git a/projects/app/src/pageComponents/app/plugin/SecretInputModal.tsx b/projects/app/src/pageComponents/app/plugin/SecretInputModal.tsx new file mode 100644 index 000000000..af895764a --- /dev/null +++ b/projects/app/src/pageComponents/app/plugin/SecretInputModal.tsx @@ -0,0 +1,247 @@ +import { Box, Button, Flex, HStack, Input, ModalBody, ModalFooter, Switch } from '@chakra-ui/react'; +import { SystemToolInputTypeEnum } from '@fastgpt/global/core/app/systemTool/constants'; +import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; +import LeftRadio from '@fastgpt/web/components/common/Radio/LeftRadio'; +import { useTranslation } from 'next-i18next'; +import React, { useState } from 'react'; +import MyIcon from '@fastgpt/web/components/common/Icon'; +import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; +import type { FlowNodeInputItemType, InputConfigType } from '@fastgpt/global/core/workflow/type/io'; +import { useForm } from 'react-hook-form'; +import type { StoreSecretValueType } from '@fastgpt/global/common/secret/type'; +import IconButton from '@/pageComponents/account/team/OrgManage/IconButton'; +import MyModal from '@fastgpt/web/components/common/MyModal'; +import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput'; +import MySelect from '@fastgpt/web/components/common/MySelect'; + +export type ToolParamsFormType = { + type: SystemToolInputTypeEnum; + value?: StoreSecretValueType; +}; + +const SecretInputModal = ({ + hasSystemSecret, + secretCost = 0, + inputConfig, + courseUrl, + onClose, + onSubmit +}: { + inputConfig: FlowNodeInputItemType; + hasSystemSecret?: boolean; + secretCost?: number; + courseUrl?: string; + onClose: () => void; + onSubmit: (data: ToolParamsFormType) => void; +}) => { + const { t } = useTranslation(); + const [editIndex, setEditIndex] = useState(); + const inputList = inputConfig?.inputList || []; + + const { register, watch, setValue, getValues, handleSubmit } = useForm({ + defaultValues: (() => { + const defaultValue = inputConfig.value; + return ( + defaultValue || { + type: hasSystemSecret ? SystemToolInputTypeEnum.system : SystemToolInputTypeEnum.manual, + value: + inputList?.reduce( + (acc, item) => { + acc[item.key] = { secret: '', value: '' }; + return acc; + }, + {} as Record + ) || {} + } + ); + })() + }); + const configType = watch('type'); + + return ( + + + + {t('common:secret_key')} + + + + + + {t('app:tool_active_system_config_price_desc', { + price: secretCost || 0 + })} + + + ) : null + } + ] + : []), + { + title: courseUrl ? ( + + {t('app:manual_secret')} + { + e.stopPropagation(); + window.open(courseUrl, '_blank'); + }} + > + + {t('app:secret_get_course')} + + + ) : ( + t('app:manual_secret') + ), + desc: t('app:tool_active_manual_config_desc'), + value: SystemToolInputTypeEnum.manual, + children: + configType === SystemToolInputTypeEnum.manual ? ( + <> + {inputList.map((item, i) => { + const inputKey = `value.${item.key}.value` as any; + const value = getValues(`value.${item.key}`); + const showInput = !!value?.value || !value?.secret || editIndex === i; + + return ( + + + + {t(item.label as any)} + + {item.description && } + + + {item.inputType === 'input' && ( + + )} + {item.inputType === 'secret' && ( + + {showInput ? ( + + ) : ( + <> + + + + {t('common:had_auth_value')} + + + setEditIndex(i)} /> + + )} + + )} + {item.inputType === 'switch' && ( + + + + )} + {item.inputType === 'numberInput' && ( + + )} + {item.inputType === 'select' && ( + { + setValue(inputKey, e); + }} + /> + )} + + ); + })} + + ) : null + } + ]} + value={configType} + onChange={(e) => setValue('type', e)} + /> + + + + + + + + ); +}; + +export default SecretInputModal; diff --git a/projects/app/src/pages/api/admin/initv47.ts b/projects/app/src/pages/api/admin/initv47.ts deleted file mode 100644 index 45ef63769..000000000 --- a/projects/app/src/pages/api/admin/initv47.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from 'next'; -import { jsonRes } from '@fastgpt/service/common/response'; -import { authCert } from '@fastgpt/service/support/permission/auth/common'; -import { MongoPlugin } from '@fastgpt/service/core/plugin/schema'; -import { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants'; - -/* pg 中的数据搬到 mongo dataset.datas 中,并做映射 */ -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - try { - await authCert({ req, authRoot: true }); - - await MongoPlugin.updateMany( - { type: { $exists: false } }, - { - $set: { - type: PluginTypeEnum.custom - } - } - ); - await MongoPlugin.updateMany( - { parentId: { $exists: false } }, - { - $set: { - parentId: null - } - } - ); - - jsonRes(res, { - message: 'success' - }); - } catch (error) { - console.log(error); - - jsonRes(res, { - code: 500, - error - }); - } -} diff --git a/projects/app/src/pages/api/admin/initv485.ts b/projects/app/src/pages/api/admin/initv485.ts deleted file mode 100644 index 53c2b7d88..000000000 --- a/projects/app/src/pages/api/admin/initv485.ts +++ /dev/null @@ -1,197 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from 'next'; -import { authCert } from '@fastgpt/service/support/permission/auth/common'; -import { MongoPlugin } from '@fastgpt/service/core/plugin/schema'; -import { MongoApp } from '@fastgpt/service/core/app/schema'; -import { NextAPI } from '@/service/middleware/entry'; -import { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants'; -import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun'; -import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; -import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema'; - -/* - 1. 先读取 HTTP plugin 内容,并找到所有的子plugin,然后事务批量创建,最后修改 inited - 2. 读取剩下未 inited 的plugin,逐一创建 -*/ - -let success = 0; -async function handler(req: NextApiRequest, res: NextApiResponse) { - await authCert({ req, authRoot: true }); - - const { teamId } = req.body as { teamId?: string }; - - const total = await MongoPlugin.countDocuments({ - inited: { $ne: true } - }); - - console.log('Total plugin', total); - - await initHttp(teamId); - await initPlugin(teamId); -} - -async function initHttp(teamId?: string): Promise { - /* 读取http插件和他的children */ - const plugin = await MongoPlugin.findOne({ - ...(teamId && { teamId }), - type: PluginTypeEnum.folder, - inited: { $ne: true } - }).lean(); - if (!plugin) return; - - const children = await MongoPlugin.find({ - teamId: plugin.teamId, - parentId: plugin._id, - inited: { $ne: true } - }).lean(); - - await mongoSessionRun(async (session) => { - /* 创建HTTP插件作为目录 */ - const [{ _id }] = await MongoApp.create( - [ - { - teamId: plugin.teamId, - tmbId: plugin.tmbId, - type: AppTypeEnum.httpPlugin, - name: plugin.name, - avatar: plugin.avatar, - intro: plugin.intro, - metadata: plugin.metadata, - version: plugin.version, - pluginData: { - apiSchemaStr: plugin.metadata?.apiSchemaStr, - customHeaders: plugin.metadata?.customHeaders - } - } - ], - { session, ordered: true } - ); - - /* 批量创建子插件 */ - for await (const item of children) { - const [{ _id: newPluginId }] = await MongoApp.create( - [ - { - _id: item._id, - parentId: _id, - teamId: item.teamId, - tmbId: item.tmbId, - type: AppTypeEnum.plugin, - name: item.name, - avatar: item.avatar, - intro: item.intro, - version: plugin.version, - modules: item.modules, - edges: item.edges, - pluginData: { - nodeVersion: item.nodeVersion, - pluginUniId: plugin.metadata?.pluginUid - } - } - ], - { session, ordered: true } - ); - if (item.version === 'v2') { - await MongoAppVersion.create( - [ - { - tmbId: plugin.tmbId, - appId: newPluginId, - nodes: item.modules, - edges: item.edges - } - ], - { session, ordered: true } - ); - } - } - - /* 更新插件信息 */ - await MongoPlugin.findOneAndUpdate( - { - _id: plugin._id - }, - { - $set: { inited: true } - }, - { session } - ); - await MongoPlugin.updateMany( - { - teamId: plugin.teamId, - parentId: plugin._id - }, - { - $set: { inited: true } - }, - { session } - ); - - success += children.length + 1; - console.log(success); - }); - - return initHttp(); -} - -async function initPlugin(teamId?: string): Promise { - const plugin = await MongoPlugin.findOne({ - ...(teamId && { teamId }), - type: PluginTypeEnum.custom, - inited: { $ne: true } - }).lean(); - if (!plugin) return; - - await mongoSessionRun(async (session) => { - const [{ _id: newPluginId }] = await MongoApp.create( - [ - { - _id: plugin._id, - teamId: plugin.teamId, - tmbId: plugin.tmbId, - type: AppTypeEnum.plugin, - name: plugin.name, - avatar: plugin.avatar, - intro: plugin.intro, - version: plugin.version, - modules: plugin.modules, - edges: plugin.edges, - pluginData: { - nodeVersion: plugin.nodeVersion - } - } - ], - { session, ordered: true } - ); - - if (plugin.version === 'v2') { - await MongoAppVersion.create( - [ - { - tmbId: plugin.tmbId, - appId: newPluginId, - nodes: plugin.modules, - edges: plugin.edges - } - ], - { session, ordered: true } - ); - } - - await MongoPlugin.findOneAndUpdate( - { - _id: plugin._id - }, - { - $set: { inited: true } - }, - { session } - ); - - success++; - console.log(success); - }); - - return initPlugin(); -} - -export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/app/detail.ts b/projects/app/src/pages/api/core/app/detail.ts index f8f2515f5..f383fab9b 100644 --- a/projects/app/src/pages/api/core/app/detail.ts +++ b/projects/app/src/pages/api/core/app/detail.ts @@ -4,6 +4,7 @@ import { NextAPI } from '@/service/middleware/entry'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { CommonErrEnum } from '@fastgpt/global/common/error/code/common'; import { rewriteAppWorkflowToDetail } from '@fastgpt/service/core/app/utils'; + /* 获取应用详情 */ async function handler(req: NextApiRequest, res: NextApiResponse) { const { appId } = req.query as { appId: string }; diff --git a/projects/app/src/pages/api/core/app/httpPlugin/create.ts b/projects/app/src/pages/api/core/app/httpPlugin/create.ts index 6936a4cf9..1e1658510 100644 --- a/projects/app/src/pages/api/core/app/httpPlugin/create.ts +++ b/projects/app/src/pages/api/core/app/httpPlugin/create.ts @@ -1,7 +1,6 @@ import { authUserPer } from '@fastgpt/service/support/permission/user/auth'; import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun'; import { httpApiSchema2Plugins } from '@fastgpt/global/core/app/httpPlugin/utils'; -import { WritePermissionVal } from '@fastgpt/global/support/permission/constant'; import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; import { NextAPI } from '@/service/middleware/entry'; diff --git a/projects/app/src/pages/api/core/app/plugin/getPreviewNode.ts b/projects/app/src/pages/api/core/app/plugin/getPreviewNode.ts index f0451858d..a0cbccbc2 100644 --- a/projects/app/src/pages/api/core/app/plugin/getPreviewNode.ts +++ b/projects/app/src/pages/api/core/app/plugin/getPreviewNode.ts @@ -1,17 +1,18 @@ -/* - get plugin preview modules +/* + get plugin preview modules */ -import type { NextApiResponse } from 'next'; +import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants'; +import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { getChildAppPreviewNode, - splitCombineToolId + splitCombinePluginId } from '@fastgpt/service/core/app/plugin/controller'; import { type FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node.d'; import { NextAPI } from '@/service/middleware/entry'; import { type ApiRequestProps } from '@fastgpt/service/type/next'; import { authApp } from '@fastgpt/service/support/permission/app/auth'; -import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; -import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; +import type { NextApiResponse } from 'next'; +import { getLocale } from '@fastgpt/service/common/middle/i18n'; export type GetPreviewNodeQuery = { appId: string; versionId?: string }; @@ -21,13 +22,13 @@ async function handler( ): Promise { const { appId, versionId } = req.query; - const { source } = splitCombineToolId(appId); + const { source, pluginId } = splitCombinePluginId(appId); if (source === PluginSourceEnum.personal) { - await authApp({ req, authToken: true, appId, per: ReadPermissionVal }); + await authApp({ req, authToken: true, appId: pluginId, per: ReadPermissionVal }); } - return getChildAppPreviewNode({ appId, versionId }); + return getChildAppPreviewNode({ appId: pluginId, versionId, lang: getLocale(req) }); } export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts b/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts index 17e0d09da..7b72ae76b 100644 --- a/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts +++ b/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts @@ -1,13 +1,15 @@ -import type { NextApiResponse } from 'next'; -import { authCert } from '@fastgpt/service/support/permission/auth/common'; import { type NodeTemplateListItemType } from '@fastgpt/global/core/workflow/type/node.d'; import { NextAPI } from '@/service/middleware/entry'; -import { getSystemPluginCb, getSystemPlugins } from '@/service/core/app/plugin'; -import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { type ParentIdType } from '@fastgpt/global/common/parentFolder/type'; import { type ApiRequestProps } from '@fastgpt/service/type/next'; import { replaceRegChars } from '@fastgpt/global/common/string/tools'; import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants'; +import { parseI18nString } from '@fastgpt/global/common/i18n/utils'; +import { getLocale } from '@fastgpt/service/common/middle/i18n'; +import { authCert } from '@fastgpt/service/support/permission/auth/common'; +import type { NextApiResponse } from 'next'; +import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; +import { getSystemPlugins } from '@fastgpt/service/core/app/plugin/controller'; export type GetSystemPluginTemplatesBody = { searchKey?: string; @@ -16,47 +18,33 @@ export type GetSystemPluginTemplatesBody = { async function handler( req: ApiRequestProps, - res: NextApiResponse + _res: NextApiResponse ): Promise { await authCert({ req, authToken: true }); - const { searchKey, parentId } = req.body; - const formatParentId = parentId || null; + const lang = getLocale(req); - // Make sure system plugin callbacks are loaded - if (!global.systemPluginCb || Object.keys(global.systemPluginCb).length === 0) - await getSystemPluginCb(); + const plugins = await getSystemPlugins(); - return getSystemPlugins().then((res) => - res - // Just show the active plugins - .filter((item) => item.isActive) - .map((plugin) => ({ - id: plugin.id, - isFolder: plugin.isFolder, - parentId: plugin.parentId, - templateType: plugin.templateType ?? FlowNodeTemplateTypeEnum.other, - flowNodeType: FlowNodeTypeEnum.pluginModule, - avatar: plugin.avatar, - name: plugin.name, - intro: plugin.intro, - isTool: plugin.isTool, - currentCost: plugin.currentCost, - hasTokenFee: plugin.hasTokenFee, - author: plugin.author, - instructions: plugin.userGuide, - courseUrl: plugin.courseUrl - })) - .filter((item) => { - if (searchKey) { - if (item.isFolder) return false; - const regx = new RegExp(`${replaceRegChars(searchKey)}`, 'i'); - return regx.test(item.name) || regx.test(item.intro || ''); - } - return item.parentId === formatParentId; - }) - ); + return plugins // Just show the active plugins + .filter((item) => item.isActive) + .map((plugin) => ({ + ...plugin, + parentId: plugin.parentId === undefined ? null : plugin.parentId, + templateType: plugin.templateType ?? FlowNodeTemplateTypeEnum.other, + flowNodeType: FlowNodeTypeEnum.tool, + name: parseI18nString(plugin.name, lang), + intro: parseI18nString(plugin.intro ?? '', lang) + })) + .filter((item) => { + if (searchKey) { + if (item.isFolder) return false; + const regx = new RegExp(`${replaceRegChars(searchKey)}`, 'i'); + return regx.test(String(item.name)) || regx.test(String(item.intro || '')); + } + return item.parentId === formatParentId; + }); } export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/app/plugin/getVersionList.ts b/projects/app/src/pages/api/core/app/plugin/getVersionList.ts index 8b483c9f0..b774c3a47 100644 --- a/projects/app/src/pages/api/core/app/plugin/getVersionList.ts +++ b/projects/app/src/pages/api/core/app/plugin/getVersionList.ts @@ -6,14 +6,16 @@ import { type ApiRequestProps } from '@fastgpt/service/type/next'; import { authApp } from '@fastgpt/service/support/permission/app/auth'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { parsePaginationRequest } from '@fastgpt/service/common/api/pagination'; -import { splitCombineToolId } from '@fastgpt/service/core/app/plugin/controller'; -import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; -import { getSystemPluginTemplates } from '@fastgpt/plugins/register'; +import { + getSystemPluginByIdAndVersionId, + splitCombinePluginId +} from '@fastgpt/service/core/app/plugin/controller'; +import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants'; import { PluginErrEnum } from '@fastgpt/global/common/error/code/plugin'; import { Types } from '@fastgpt/service/common/mongo'; export type getToolVersionListProps = PaginationProps<{ - toolId?: string; + pluginId?: string; }>; export type getToolVersionResponse = PaginationResponse<{ @@ -25,30 +27,44 @@ async function handler( req: ApiRequestProps, _res: NextApiResponse ): Promise { - const { toolId } = req.body; + const { pluginId } = req.body; const { offset, pageSize } = parsePaginationRequest(req); - if (!toolId) { + if (!pluginId) { return { total: 0, list: [] }; } + const { source, pluginId: formatPluginId } = splitCombinePluginId(pluginId); - const { source, pluginId: formatToolId } = splitCombineToolId(toolId); + // System tool plugin + if (source === PluginSourceEnum.systemTool) { + const item = await getSystemPluginByIdAndVersionId(formatPluginId); - // Auth + return { + total: 0, + list: + item.versionList?.map((item) => ({ + _id: item.value, + versionName: item.value + })) || [] + }; + } + + // Workflow plugin const appId = await (async () => { if (source === PluginSourceEnum.personal) { const { app } = await authApp({ - appId: formatToolId, + appId: formatPluginId, req, per: ReadPermissionVal, authToken: true }); return app._id; } else { - const item = getSystemPluginTemplates().find((plugin) => plugin.id === formatToolId); + const item = await getSystemPluginByIdAndVersionId(formatPluginId); + // const item = getSystemTools if (!item) return Promise.reject(PluginErrEnum.unAuth); return item.associatedPluginId; } diff --git a/projects/app/src/pages/api/core/app/plugin/path.ts b/projects/app/src/pages/api/core/app/plugin/path.ts index 78540cb16..b61423bfb 100644 --- a/projects/app/src/pages/api/core/app/plugin/path.ts +++ b/projects/app/src/pages/api/core/app/plugin/path.ts @@ -4,7 +4,9 @@ import { type GetPathProps, type ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type'; -import { getSystemPlugins } from '@/service/core/app/plugin'; +import { parseI18nString } from '@fastgpt/global/common/i18n/utils'; +import { getLocale } from '@fastgpt/service/common/middle/i18n'; +import { getSystemPlugins } from '@fastgpt/service/core/app/plugin/controller'; export type pathQuery = GetPathProps; @@ -17,6 +19,7 @@ async function handler( res: ApiResponseType ): Promise { const { sourceId: pluginId, type } = req.query; + const lang = getLocale(req); if (!pluginId) return []; @@ -28,7 +31,7 @@ async function handler( return [ { parentId: type === 'current' ? plugin.id : plugin.parentId, - parentName: plugin.name + parentName: parseI18nString(plugin.name, lang) } ]; } diff --git a/projects/app/src/pages/api/plugins/TFSwitch/index.ts b/projects/app/src/pages/api/plugins/TFSwitch/index.ts deleted file mode 100644 index e77be0ec0..000000000 --- a/projects/app/src/pages/api/plugins/TFSwitch/index.ts +++ /dev/null @@ -1,72 +0,0 @@ -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 deleted file mode 100644 index c8b8b8732..000000000 --- a/projects/app/src/pages/api/plugins/customFeedback/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -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 { addCustomFeedbacks } from '@fastgpt/service/core/chat/controller'; -import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common'; - -type Props = HttpBodyType<{ - appId: string; - chatId?: string; - responseChatItemId?: string; - defaultFeedback: string; - customFeedback: string; -}>; - -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - try { - const { - appId, - chatId, - responseChatItemId: dataId, - defaultFeedback, - customFeedback - } = req.body as Props; - - await authRequestFromLocal({ req }); - - const feedback = customFeedback || defaultFeedback; - - if (!feedback) { - return res.json({ - response: '' - }); - } - - // wait the chat finish - setTimeout(() => { - addCustomFeedbacks({ - appId, - chatId, - dataId, - feedbacks: [feedback] - }); - }, 60000); - - if (!chatId || !dataId) { - return res.json({ - response: `\\n\\n**自动反馈调试**: ${feedback}\\n\\n` - }); - } - - 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 deleted file mode 100644 index 5b905cb34..000000000 --- a/projects/app/src/pages/api/plugins/customFeedback/v2/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -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 { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; -import { type SystemVariablesType } from '@fastgpt/global/core/workflow/runtime/type'; -import { replaceVariable } from '@fastgpt/global/common/string/tools'; - -type Props = HttpBodyType< - SystemVariablesType & { - customFeedback: string; - customInputs: Record; - } ->; - -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - try { - const { - customFeedback, - appId, - chatId, - responseChatItemId: dataId, - customInputs - } = req.body as Props; - - await authRequestFromLocal({ req }); - - if (!customFeedback) { - return res.json({}); - } - - const feedbackText = replaceVariable(customFeedback, customInputs); - - // wait the chat finish - setTimeout(() => { - addCustomFeedbacks({ - appId, - chatId, - dataId, - feedbacks: [feedbackText] - }); - }, 60000); - - if (!chatId || !dataId) { - return res.json({ - [NodeOutputKeyEnum.answerText]: `\\n\\n**自动反馈调试**: "${feedbackText}"\\n\\n`, - text: feedbackText - }); - } - - res.json({ - text: feedbackText - }); - } 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 deleted file mode 100644 index 07d564110..000000000 --- a/projects/app/src/pages/api/plugins/textEditor/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -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 { replaceVariable } from '@fastgpt/global/common/string/tools'; -import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common'; - -type Props = HttpBodyType<{ - text: string; - [key: string]: any; -}>; - -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - try { - const { - text, - DYNAMIC_INPUT_KEY: { ...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)); - } -} diff --git a/projects/app/src/pages/api/plugins/textEditor/v2/index.ts b/projects/app/src/pages/api/plugins/textEditor/v2/index.ts deleted file mode 100644 index 5421ff597..000000000 --- a/projects/app/src/pages/api/plugins/textEditor/v2/index.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { 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 { type ApiRequestProps } from '@fastgpt/service/type/next'; - -type Props = HttpBodyType<{ - text: string; - customInputs: Record; -}>; - -export default async function handler(req: ApiRequestProps, res: NextApiResponse) { - try { - const { text, customInputs: obj = {} } = req.body; - - 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)); - } -} - -export const config = { - api: { - bodyParser: { - sizeLimit: '16mb' - }, - responseLimit: '16mb' - } -}; diff --git a/projects/app/src/pages/api/system/pluginImgs/[...path].ts b/projects/app/src/pages/api/system/pluginImgs/[...path].ts new file mode 100644 index 000000000..983868ce1 --- /dev/null +++ b/projects/app/src/pages/api/system/pluginImgs/[...path].ts @@ -0,0 +1,56 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; +import { jsonRes } from '@fastgpt/service/common/response'; +import { request } from 'http'; +import { FastGPTPluginUrl } from '@fastgpt/service/common/system/constants'; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + try { + const { path = [] } = req.query as any; + const requestPath = `/imgs/tools/${path?.join('/')}`; + + if (!requestPath) { + throw new Error('url is empty'); + } + if (!FastGPTPluginUrl) { + throw new Error(`未配置插件服务链接: ${path}`); + } + + const parsedUrl = new URL(FastGPTPluginUrl); + delete req.headers?.rootkey; + + const requestResult = request({ + protocol: parsedUrl.protocol, + hostname: parsedUrl.hostname, + port: parsedUrl.port, + path: requestPath, + method: req.method, + headers: req.headers + }); + req.pipe(requestResult); + + requestResult.on('response', (response) => { + Object.keys(response.headers).forEach((key) => { + // @ts-ignore + res.setHeader(key, response.headers[key]); + }); + response.statusCode && res.writeHead(response.statusCode); + response.pipe(res); + }); + + requestResult.on('error', (e) => { + res.send(e); + res.end(); + }); + } catch (error) { + jsonRes(res, { + code: 500, + error + }); + } +} + +export const config = { + api: { + bodyParser: false + } +}; diff --git a/projects/app/src/service/common/system/cronTask.ts b/projects/app/src/service/common/system/cronTask.ts index b1e9dea85..18507c994 100644 --- a/projects/app/src/service/common/system/cronTask.ts +++ b/projects/app/src/service/common/system/cronTask.ts @@ -15,7 +15,7 @@ import { MongoDatasetData } from '@fastgpt/service/core/dataset/data/schema'; import { MongoDatasetTraining } from '@fastgpt/service/core/dataset/training/schema'; import { addDays } from 'date-fns'; -/* +/* check dataset.files data. If there is no match in dataset.collections, delete it 可能异常情况: 1. 上传了文件,未成功创建集合 @@ -65,7 +65,7 @@ export async function checkInvalidDatasetFiles(start: Date, end: Date) { addLog.info(`Clear invalid dataset files finish, remove ${deleteFileAmount} files`); } -/* +/* Remove 7 days ago chat files */ export const removeExpiredChatFiles = async () => { @@ -96,7 +96,7 @@ export const removeExpiredChatFiles = async () => { addLog.info(`Remove expired chat files finish, remove ${deleteFileAmount} files`); }; -/* +/* 检测无效的 Mongo 数据 异常情况: 1. 训练过程删除知识库,可能导致还会有新的数据继续插入,导致无效。 diff --git a/projects/app/src/service/common/system/index.ts b/projects/app/src/service/common/system/index.ts index d6f59e5fc..7ce0aa18c 100644 --- a/projects/app/src/service/common/system/index.ts +++ b/projects/app/src/service/common/system/index.ts @@ -73,7 +73,6 @@ export function initGlobalVariables() { }; } - global.communityPlugins = []; global.qaQueueLen = global.qaQueueLen ?? 0; global.vectorQueueLen = global.vectorQueueLen ?? 0; initHttpAgent(); diff --git a/projects/app/src/service/common/system/volumnMongoWatch.ts b/projects/app/src/service/common/system/volumnMongoWatch.ts index 342986079..bd31565cd 100644 --- a/projects/app/src/service/common/system/volumnMongoWatch.ts +++ b/projects/app/src/service/common/system/volumnMongoWatch.ts @@ -1,20 +1,19 @@ -import { getSystemPluginCb } from '@/service/core/app/plugin'; import { initSystemConfig } from '.'; import { createDatasetTrainingMongoWatch } from '@/service/core/dataset/training/utils'; import { MongoSystemConfigs } from '@fastgpt/service/common/system/config/schema'; -import { MongoSystemPlugin } from '@fastgpt/service/core/app/plugin/systemPluginSchema'; import { debounce } from 'lodash'; import { MongoAppTemplate } from '@fastgpt/service/core/app/templates/templateSchema'; import { getAppTemplatesAndLoadThem } from '@fastgpt/templates/register'; import { watchSystemModelUpdate } from '@fastgpt/service/core/ai/config/utils'; import { SystemConfigsTypeEnum } from '@fastgpt/global/common/system/config/constants'; +import { refetchSystemPlugins } from '@fastgpt/service/core/app/plugin/controller'; export const startMongoWatch = async () => { reloadConfigWatch(); - refetchSystemPlugins(); createDatasetTrainingMongoWatch(); refetchAppTemplates(); watchSystemModelUpdate(); + refetchSystemPlugins(); }; const reloadConfigWatch = () => { @@ -36,21 +35,6 @@ const reloadConfigWatch = () => { }); }; -const refetchSystemPlugins = () => { - const changeStream = MongoSystemPlugin.watch(); - - changeStream.on( - 'change', - debounce(async (change) => { - setTimeout(() => { - try { - getSystemPluginCb(true); - } catch (error) {} - }, 5000); - }, 500) - ); -}; - const refetchAppTemplates = () => { const changeStream = MongoAppTemplate.watch(); diff --git a/projects/app/src/service/core/app/plugin.ts b/projects/app/src/service/core/app/plugin.ts deleted file mode 100644 index ffd059407..000000000 --- a/projects/app/src/service/core/app/plugin.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { FastGPTProUrl } from '@fastgpt/service/common/system/constants'; -import { isProduction } from '@fastgpt/global/common/system/constants'; -import { cloneDeep } from 'lodash'; -import { getCommunityCb, getCommunityPlugins } from '@fastgpt/plugins/register'; -import { GET, POST } from '@fastgpt/service/common/api/plusRequest'; -import { type SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type'; -import { addLog } from '@fastgpt/service/common/system/log'; -import { type SystemPluginResponseType } from '@fastgpt/plugins/type'; - -/* Get plugins */ -const getCommercialPlugins = () => { - return GET('/core/app/plugin/getSystemPlugins'); -}; - -export const getSystemPlugins = async (refresh = false) => { - if (isProduction && global.systemPlugins && global.systemPlugins.length > 0 && !refresh) - return cloneDeep(global.systemPlugins); - - try { - if (!global.systemPlugins) { - global.systemPlugins = []; - } - - global.systemPlugins = FastGPTProUrl - ? await getCommercialPlugins() - : await getCommunityPlugins(); - - addLog.info(`Load system plugin successfully: ${global.systemPlugins.length}`); - - return cloneDeep(global.systemPlugins); - } catch (error) { - //@ts-ignore - global.systemPlugins = undefined; - return Promise.reject(error); - } -}; - -/* Get plugin callback */ -const getCommercialCb = async () => { - const plugins = await getSystemPlugins(); - const result = plugins.map((plugin) => { - const name = plugin.id.split('-')[1]; - - return { - name, - cb: (e: any) => - POST>('/core/app/plugin/run', { - pluginName: name, - data: e - }) - }; - }); - - return result.reduce SystemPluginResponseType>>( - (acc, { name, cb }) => { - acc[name] = cb; - return acc; - }, - {} - ); -}; - -export const getSystemPluginCb = async (refresh = false) => { - if ( - isProduction && - global.systemPluginCb && - Object.keys(global.systemPluginCb).length > 0 && - !refresh - ) - return global.systemPluginCb; - - try { - global.systemPluginCb = {}; - await getSystemPlugins(refresh); - global.systemPluginCb = FastGPTProUrl ? await getCommercialCb() : await getCommunityCb(); - return global.systemPluginCb; - } catch (error) { - return Promise.reject(error); - } -}; diff --git a/projects/app/src/service/core/app/utils.ts b/projects/app/src/service/core/app/utils.ts index 2986fe53a..21185b5ef 100644 --- a/projects/app/src/service/core/app/utils.ts +++ b/projects/app/src/service/core/app/utils.ts @@ -22,15 +22,6 @@ import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runti import { type UserChatItemValueItemType } from '@fastgpt/global/core/chat/type'; import { saveChat } from '@fastgpt/service/core/chat/saveChat'; import { getAppLatestVersion } from '@fastgpt/service/core/app/version/controller'; -import { - getChildAppPreviewNode, - splitCombineToolId -} from '@fastgpt/service/core/app/plugin/controller'; -import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; -import { authAppByTmbId } from '@fastgpt/service/support/permission/app/auth'; -import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; -import { type StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node'; -import { getErrText } from '@fastgpt/global/common/error/utils'; export const getScheduleTriggerApp = async () => { // 1. Find all the app diff --git a/projects/app/src/web/core/app/utils.ts b/projects/app/src/web/core/app/utils.ts index ecef68ee7..2ce8058ab 100644 --- a/projects/app/src/web/core/app/utils.ts +++ b/projects/app/src/web/core/app/utils.ts @@ -19,7 +19,7 @@ import { import { getNanoid } from '@fastgpt/global/common/string/tools'; import { type StoreEdgeItemType } from '@fastgpt/global/core/workflow/type/edge'; import { type EditorVariablePickerType } from '@fastgpt/web/components/common/Textarea/PromptEditor/type'; -import { ToolModule } from '@fastgpt/global/core/workflow/template/system/tools'; +import { AgentNode } from '@fastgpt/global/core/workflow/template/system/agent'; import { WorkflowStart, userFilesInput @@ -400,7 +400,7 @@ export function form2AppWorkflow( x: 500 + 500 * (i + 1), y: 545 }, - // 这里不需要固定版本,给一个不存在的版本,每次都会用最新版 + toolConfig: tool.toolConfig, pluginData: tool.pluginData, inputs: tool.inputs.map((input) => { // Special key value @@ -437,19 +437,19 @@ export function form2AppWorkflow( nodes: [ { nodeId: toolNodeId, - name: ToolModule.name, - intro: ToolModule.intro, - avatar: ToolModule.avatar, - flowNodeType: ToolModule.flowNodeType, + name: AgentNode.name, + intro: AgentNode.intro, + avatar: AgentNode.avatar, + flowNodeType: AgentNode.flowNodeType, showStatus: true, position: { x: 1062.1738942532802, y: -223.65033022650476 }, - version: ToolModule.version, + version: AgentNode.version, inputs: [ { - key: 'model', + key: NodeInputKeyEnum.aiModel, renderTypeList: [ FlowNodeInputTypeEnum.settingLLMModel, FlowNodeInputTypeEnum.reference @@ -526,7 +526,7 @@ export function form2AppWorkflow( value: formData.aiSettings.aiChatReasoning } ], - outputs: ToolModule.outputs + outputs: AgentNode.outputs }, // tool nodes ...(datasetTool ? datasetTool.nodes : []), diff --git a/projects/app/src/web/core/chat/utils.ts b/projects/app/src/web/core/chat/utils.ts index fdeed951d..581393a50 100644 --- a/projects/app/src/web/core/chat/utils.ts +++ b/projects/app/src/web/core/chat/utils.ts @@ -18,7 +18,7 @@ export function checkChatSupportSelectFileByModules(modules: StoreNodeItemType[] const chatModules = modules.filter( (item) => item.flowNodeType === FlowNodeTypeEnum.chatNode || - item.flowNodeType === FlowNodeTypeEnum.tools + item.flowNodeType === FlowNodeTypeEnum.agent ); const models: string[] = chatModules.map( (item) => item.inputs.find((item) => item.key === 'model')?.value || '' diff --git a/projects/app/src/web/core/workflow/adapt.ts b/projects/app/src/web/core/workflow/adapt.ts index 079768e3d..a9828757c 100644 --- a/projects/app/src/web/core/workflow/adapt.ts +++ b/projects/app/src/web/core/workflow/adapt.ts @@ -9,7 +9,6 @@ import { FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; -import { getHandleConfig } from '@fastgpt/global/core/workflow/template/utils'; import type { FlowNodeItemType, StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node'; import type { FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node'; import { VARIABLE_NODE_ID } from '@fastgpt/global/core/workflow/constants'; @@ -20,7 +19,6 @@ import type { FlowNodeInputItemType, FlowNodeOutputItemType } from '@fastgpt/global/core/workflow/type/io'; -import type { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants'; import { getWorkflowGlobalVariables } from './utils'; import type { TFunction } from 'next-i18next'; import type { AppChatConfigType } from '@fastgpt/global/core/app/type'; @@ -38,8 +36,8 @@ export const getGlobalVariableNode = ({ id: FlowNodeTypeEnum.globalVariable, templateType: FlowNodeTemplateTypeEnum.other, flowNodeType: FlowNodeTypeEnum.emptyNode, - sourceHandle: getHandleConfig(false, false, false, false), - targetHandle: getHandleConfig(false, false, false, false), + showSourceHandle: false, + showTargetHandle: false, avatar: 'core/workflow/template/variable', name: t('common:core.module.Variable'), intro: '', @@ -231,7 +229,6 @@ type V1WorkflowType = { // runTime field isEntry?: boolean; - pluginType?: `${PluginTypeEnum}`; parentId?: string; }; export const v1Workflow2V2 = ( @@ -267,7 +264,7 @@ export const v1Workflow2V2 = ( [FlowTypeEnum.pluginInput]: FlowNodeTypeEnum.pluginInput, [FlowTypeEnum.pluginOutput]: FlowNodeTypeEnum.pluginOutput, [FlowTypeEnum.queryExtension]: FlowNodeTypeEnum.queryExtension, - [FlowTypeEnum.tools]: FlowNodeTypeEnum.tools, + [FlowTypeEnum.tools]: FlowNodeTypeEnum.agent, [FlowTypeEnum.stopTool]: FlowNodeTypeEnum.stopTool, [FlowTypeEnum.lafModule]: FlowNodeTypeEnum.lafModule }; @@ -408,7 +405,6 @@ export const v1Workflow2V2 = ( intro: node.intro, showStatus: node.showStatus, pluginId, - pluginType: node.pluginType, parentId: node.parentId, version: '481', diff --git a/projects/app/src/web/core/workflow/type.d.ts b/projects/app/src/web/core/workflow/type.d.ts new file mode 100644 index 000000000..95ab3842e --- /dev/null +++ b/projects/app/src/web/core/workflow/type.d.ts @@ -0,0 +1,13 @@ +export type THelperLine = { + position: number; + nodes: { + left: number; + right: number; + top: number; + bottom: number; + width: number; + height: number; + centerX: number; + centerY: number; + }[]; +}; diff --git a/projects/app/src/web/core/workflow/utils.ts b/projects/app/src/web/core/workflow/utils.ts index 656a98321..e6a55c725 100644 --- a/projects/app/src/web/core/workflow/utils.ts +++ b/projects/app/src/web/core/workflow/utils.ts @@ -33,9 +33,9 @@ import { type IfElseListItemType } from '@fastgpt/global/core/workflow/template/ import { VariableConditionEnum } from '@fastgpt/global/core/workflow/template/system/ifElse/constant'; import { type AppChatConfigType } from '@fastgpt/global/core/app/type'; import { cloneDeep, isEqual } from 'lodash'; -import { getInputComponentProps } from '@fastgpt/global/core/workflow/node/io/utils'; import { workflowSystemVariables } from '../app/utils'; +/* ====== node ======= */ export const nodeTemplate2FlowNode = ({ template, position, @@ -170,6 +170,25 @@ export const storeNode2FlowNode = ({ zIndex }; }; +export const filterSensitiveNodesData = (nodes: StoreNodeItemType[]) => { + const cloneNodes = JSON.parse(JSON.stringify(nodes)) as StoreNodeItemType[]; + + cloneNodes.forEach((node) => { + // selected dataset + if (node.flowNodeType === FlowNodeTypeEnum.datasetSearchNode) { + node.inputs.forEach((input) => { + if (input.key === NodeInputKeyEnum.datasetSelectList) { + input.value = []; + } + }); + } + + return node; + }); + return cloneNodes; +}; + +/* ====== edge ======= */ export const storeEdge2RenderEdge = ({ edge }: { edge: StoreEdgeItemType }) => { const sourceHandle = edge.sourceHandle.replace(/-source-(top|bottom|left)$/, '-source-right'); const targetHandle = edge.targetHandle.replace(/-target-(top|bottom|right)$/, '-target-left'); @@ -183,53 +202,24 @@ export const storeEdge2RenderEdge = ({ edge }: { edge: StoreEdgeItemType }) => { }; }; -export const computedNodeInputReference = ({ - nodeId, - nodes, - edges, - chatConfig, - t -}: { - nodeId: string; - nodes: FlowNodeItemType[]; - edges: Edge[]; - chatConfig: AppChatConfigType; - t: TFunction; -}) => { - // get current node - const node = nodes.find((item) => item.nodeId === nodeId); - if (!node) { - return; - } - const parentId = node.parentNodeId; - let sourceNodes: FlowNodeItemType[] = []; - // 根据 edge 获取所有的 source 节点(source节点会继续向前递归获取) - const findSourceNode = (nodeId: string) => { - const targetEdges = edges.filter((item) => item.target === nodeId || item.target === parentId); - targetEdges.forEach((edge) => { - const sourceNode = nodes.find((item) => item.nodeId === edge.source); - if (!sourceNode) return; - - // 去重 - if (sourceNodes.some((item) => item.nodeId === sourceNode.nodeId)) { - return; - } - sourceNodes.push(sourceNode); - findSourceNode(sourceNode.nodeId); - }); +/* ====== IO ======= */ +export const getInputComponentProps = (input: FlowNodeInputItemType) => { + return { + referencePlaceholder: input.referencePlaceholder, + placeholder: input.placeholder, + maxLength: input.maxLength, + list: input.list, + markList: input.markList, + step: input.step, + max: input.max, + min: input.min, + defaultValue: input.defaultValue, + llmModelType: input.llmModelType, + customInputConfig: input.customInputConfig }; - findSourceNode(nodeId); - - sourceNodes.push( - getGlobalVariableNode({ - nodes, - t, - chatConfig - }) - ); - - return sourceNodes; }; + +/* ====== Reference ======= */ export const getRefData = ({ variable, nodeList, @@ -268,7 +258,6 @@ export const getRefData = ({ required: !!output.required }; }; - // 根据数据类型,过滤无效的节点输出 export const filterWorkflowNodeOutputsByType = ( outputs: FlowNodeOutputItemType[], @@ -337,8 +326,55 @@ export const filterWorkflowNodeOutputsByType = ( validTypeMap[valueType]?.includes(output.valueType) ); }; +export const computedNodeInputReference = ({ + nodeId, + nodes, + edges, + chatConfig, + t +}: { + nodeId: string; + nodes: FlowNodeItemType[]; + edges: Edge[]; + chatConfig: AppChatConfigType; + t: TFunction; +}) => { + // get current node + const node = nodes.find((item) => item.nodeId === nodeId); + if (!node) { + return; + } + const parentId = node.parentNodeId; + let sourceNodes: FlowNodeItemType[] = []; + // 根据 edge 获取所有的 source 节点(source节点会继续向前递归获取) + const findSourceNode = (nodeId: string) => { + const targetEdges = edges.filter((item) => item.target === nodeId || item.target === parentId); + targetEdges.forEach((edge) => { + const sourceNode = nodes.find((item) => item.nodeId === edge.source); + if (!sourceNode) return; -/* Connection rules */ + // 去重 + if (sourceNodes.some((item) => item.nodeId === sourceNode.nodeId)) { + return; + } + sourceNodes.push(sourceNode); + findSourceNode(sourceNode.nodeId); + }); + }; + findSourceNode(nodeId); + + sourceNodes.push( + getGlobalVariableNode({ + nodes, + t, + chatConfig + }) + ); + + return sourceNodes; +}; + +/* ====== Connection ======= */ export const checkWorkflowNodeAndConnection = ({ nodes, edges @@ -467,7 +503,7 @@ export const checkWorkflowNodeAndConnection = ({ const edgeFilted = edges.filter( (edge) => !( - data.flowNodeType === FlowNodeTypeEnum.tools && + data.flowNodeType === FlowNodeTypeEnum.agent && edge.sourceHandle === NodeOutputKeyEnum.selectedTools ) ); @@ -481,24 +517,7 @@ export const checkWorkflowNodeAndConnection = ({ } }; -export const filterSensitiveNodesData = (nodes: StoreNodeItemType[]) => { - const cloneNodes = JSON.parse(JSON.stringify(nodes)) as StoreNodeItemType[]; - - cloneNodes.forEach((node) => { - // selected dataset - if (node.flowNodeType === FlowNodeTypeEnum.datasetSearchNode) { - node.inputs.forEach((input) => { - if (input.key === NodeInputKeyEnum.datasetSelectList) { - input.value = []; - } - }); - } - - return node; - }); - return cloneNodes; -}; - +/* ====== Variables ======= */ /* get workflowStart output to global variables */ export const getWorkflowGlobalVariables = ({ nodes, @@ -518,47 +537,7 @@ export const getWorkflowGlobalVariables = ({ return [...globalVariables, ...workflowSystemVariables]; }; -export type CombinedItemType = Partial & Partial; - -/* Reset node to latest version */ -export const getLatestNodeTemplate = ( - node: FlowNodeItemType, - template: FlowNodeTemplateType -): FlowNodeItemType => { - const updatedNode: FlowNodeItemType = { - ...node, - ...template, - inputs: template.inputs.map((templateItem) => { - const nodeItem = node.inputs.find((item) => item.key === templateItem.key); - if (nodeItem) { - return { - ...templateItem, - value: nodeItem.value, - selectedTypeIndex: nodeItem.selectedTypeIndex, - valueType: nodeItem.valueType - }; - } - return { ...templateItem }; - }), - outputs: template.outputs.map((templateItem) => { - const nodeItem = node.outputs.find((item) => item.key === templateItem.key); - if (nodeItem) { - return { - ...templateItem, - id: nodeItem.id, - value: nodeItem.value, - valueType: nodeItem.valueType - }; - } - return { ...templateItem }; - }), - name: node.name, - intro: node.intro - }; - - return updatedNode; -}; - +/* ====== Snapshot ======= */ export const compareSnapshot = ( snapshot1: { nodes?: Node[]; diff --git a/projects/app/test/cases/web/workflow/utils.test.ts b/projects/app/test/cases/web/workflow/utils.test.ts index 4274363b6..5760b05c7 100644 --- a/projects/app/test/cases/web/workflow/utils.test.ts +++ b/projects/app/test/cases/web/workflow/utils.test.ts @@ -17,8 +17,7 @@ import { nodeTemplate2FlowNode, storeNode2FlowNode, filterWorkflowNodeOutputsByType, - checkWorkflowNodeAndConnection, - getLatestNodeTemplate + checkWorkflowNodeAndConnection } from '@/web/core/workflow/utils'; import type { FlowNodeOutputItemType } from '@fastgpt/global/core/workflow/type/io'; @@ -238,102 +237,3 @@ describe('checkWorkflowNodeAndConnection', () => { expect(result).toBeUndefined(); }); }); - -describe('getLatestNodeTemplate', () => { - it('should update node to latest template version', () => { - const node: FlowNodeItemType = { - id: 'node1', - nodeId: 'node1', - templateType: 'formInput', - flowNodeType: FlowNodeTypeEnum.formInput, - inputs: [ - { - key: 'input1', - value: 'test', - renderTypeList: [FlowNodeInputTypeEnum.input], - label: 'Input 1' - } - ], - outputs: [ - { - key: 'output1', - value: 'test', - type: FlowNodeOutputTypeEnum.static, - label: 'Output 1', - id: 'output1' - } - ], - name: 'Old Name', - intro: 'Old Intro' - }; - - const template: FlowNodeTemplateType = { - name: 'Template 1', - id: 'template1', - templateType: 'formInput', - flowNodeType: FlowNodeTypeEnum.formInput, - inputs: [ - { key: 'input1', renderTypeList: [FlowNodeInputTypeEnum.input], label: 'Input 1' }, - { key: 'input2', renderTypeList: [FlowNodeInputTypeEnum.input], label: 'Input 2' } - ], - outputs: [ - { id: 'output1', key: 'output1', type: FlowNodeOutputTypeEnum.static, label: 'Output 1' }, - { id: 'output2', key: 'output2', type: FlowNodeOutputTypeEnum.static, label: 'Output 2' } - ] - }; - - const result = getLatestNodeTemplate(node, template); - - expect(result.inputs).toHaveLength(2); - expect(result.outputs).toHaveLength(2); - expect(result.name).toBe('Old Name'); - }); - - it('should preserve existing values when updating template', () => { - const node: FlowNodeItemType = { - id: 'node1', - nodeId: 'node1', - templateType: 'formInput', - flowNodeType: FlowNodeTypeEnum.formInput, - inputs: [ - { - key: 'input1', - value: 'existingValue', - renderTypeList: [FlowNodeInputTypeEnum.input], - label: 'Input 1' - } - ], - outputs: [ - { - key: 'output1', - value: 'existingOutput', - type: FlowNodeOutputTypeEnum.static, - label: 'Output 1', - id: 'output1' - } - ], - name: 'Node Name', - intro: 'Node Intro' - }; - - const template: FlowNodeTemplateType = { - name: 'Template 1', - id: 'template1', - templateType: 'formInput', - flowNodeType: FlowNodeTypeEnum.formInput, - inputs: [ - { key: 'input1', renderTypeList: [FlowNodeInputTypeEnum.input], label: 'Input 1' }, - { key: 'input2', renderTypeList: [FlowNodeInputTypeEnum.input], label: 'Input 2' } - ], - outputs: [ - { id: 'output1', key: 'output1', type: FlowNodeOutputTypeEnum.static, label: 'Output 1' }, - { id: 'output2', key: 'output2', type: FlowNodeOutputTypeEnum.static, label: 'Output 2' } - ] - }; - - const result = getLatestNodeTemplate(node, template); - - expect(result.inputs[0].value).toBe('existingValue'); - expect(result.outputs[0].value).toBe('existingOutput'); - }); -}); diff --git a/test/cases/global/core/chat/utils.test.ts b/test/cases/global/core/chat/utils.test.ts index e0cbca21a..d4e51564a 100644 --- a/test/cases/global/core/chat/utils.test.ts +++ b/test/cases/global/core/chat/utils.test.ts @@ -116,7 +116,7 @@ describe('addStatisticalDataToHistoryItem', () => { }, { ...mockResponseData, - moduleType: FlowNodeTypeEnum.tools, + moduleType: FlowNodeTypeEnum.agent, runningTime: 1, toolDetail: [ { @@ -176,7 +176,7 @@ describe('addStatisticalDataToHistoryItem', () => { ], loopDetail: [ { - moduleType: FlowNodeTypeEnum.tools, + moduleType: FlowNodeTypeEnum.agent, runningTime: 0.3 } ]