From 8aa6b5376089afcaefa2e2142e8bd4224dfd1afb Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Tue, 26 Nov 2024 12:02:58 +0800 Subject: [PATCH] V4.8.14 dev (#3234) * feat: rewrite chat context (#3176) * feat: add app auto execute (#3115) * feat: add app auto execute * auto exec configtion * chatting animation * change icon * fix * fix * fix link * feat: add chat context to all chatbox * perf: loading ui --------- Co-authored-by: heheer * app auto exec (#3179) * add chat records loaded state (#3184) * perf: chat store reset storage (#3186) * perf: chat store reset storage * perf: auto exec code * chore: workflow ui (#3175) * chore: workflow ui * fix * change icon color config * change popover to mymenu * 4.8.14 test (#3189) * update doc * fix: token check * perf: icon button * update doc * feat: share page support configuration Whether to allow the original view (#3194) * update doc * perf: fix index (#3206) * perf: i18n * perf: Add service entry (#3226) * 4.8.14 test (#3228) * fix: ai log * fix: text splitter * fix: reference unselect & user form description & simple to advance (#3229) * fix: reference unselect & user form description & simple to advance * change abort position * perf * perf: code (#3232) * perf: code * update doc * fix: create btn permission (#3233) * update doc * fix: refresh chatbox listener * perf: check invalid reference * perf: check invalid reference * update doc * fix: ui props --------- Co-authored-by: heheer --- .vscode/settings.json | 4 +- .../zh-cn/docs/development/upgrading/4814.md | 24 +- packages/global/common/file/icon.ts | 4 +- packages/global/common/file/type.d.ts | 3 +- packages/global/common/string/textSplitter.ts | 5 +- packages/global/core/ai/type.d.ts | 1 + packages/global/core/app/constants.ts | 12 +- packages/global/core/app/type.d.ts | 6 + packages/global/core/chat/adapt.ts | 2 + packages/global/core/chat/type.d.ts | 1 + packages/global/core/chat/utils.ts | 2 +- packages/global/core/dataset/type.d.ts | 3 +- packages/global/core/workflow/constants.ts | 1 + packages/global/core/workflow/utils.ts | 36 +- .../service/common/file/gridfs/controller.ts | 6 +- packages/service/common/file/multer.ts | 4 +- packages/service/core/ai/config.ts | 16 +- packages/service/core/app/schema.ts | 3 +- packages/service/core/chat/chatItemSchema.ts | 4 + packages/service/core/chat/saveChat.ts | 22 +- .../core/dataset/collection/controller.ts | 2 +- .../service/core/dataset/collection/schema.ts | 2 +- .../core/dataset/training/controller.ts | 7 +- .../dispatch/agent/runTool/functionCall.ts | 14 +- .../dispatch/agent/runTool/promptCall.ts | 15 +- .../dispatch/agent/runTool/toolChoice.ts | 13 +- .../core/workflow/dispatch/chat/oneapi.ts | 165 ++++--- .../core/workflow/dispatch/tools/http468.ts | 3 +- .../service/core/workflow/dispatch/utils.ts | 29 +- packages/service/support/outLink/schema.ts | 3 +- .../service/support/permission/auth/file.ts | 8 +- .../service/support/permission/controller.ts | 7 +- .../support/permission/publish/authLink.ts | 8 +- packages/service/support/permission/type.d.ts | 1 + packages/service/type.d.ts | 3 - packages/web/common/system/utils.ts | 2 + .../web/components/common/Icon/button.tsx | 41 ++ .../web/components/common/Icon/constants.ts | 3 + .../components/common/Icon/icons/check.svg | 4 +- .../common/Icon/icons/checkCircle.svg | 3 + .../common/Icon/icons/common/file/move.svg | 7 +- .../icons/core/app/simpleMode/autoExec.svg | 7 + .../icons/core/workflow/edgeArrowBold.svg | 3 + .../web/components/common/Image/MyImage.tsx | 6 +- .../web/components/common/MyMenu/index.tsx | 181 +++++-- .../common/MySelect/MultipleRowSelect.tsx | 4 +- .../components/common/Tabs/FillRowTabs.tsx | 13 +- .../common/Textarea/JsonEditor/index.tsx | 6 +- .../common/Textarea/PromptEditor/Editor.tsx | 4 +- .../components/VariableLabel.tsx | 9 +- .../plugins/VariableLabelPlugin/index.tsx | 2 +- .../core/workflow/NodeInputSelect.tsx | 48 +- packages/web/hooks/useI18n.ts | 13 +- packages/web/hooks/useScrollPagination.tsx | 14 +- packages/web/hooks/useToast.ts | 8 +- packages/web/i18n/en/app.json | 11 +- packages/web/i18n/en/chat.json | 1 + packages/web/i18n/en/common.json | 10 +- packages/web/i18n/{zh => zh-CN}/app.json | 4 + packages/web/i18n/{zh => zh-CN}/chat.json | 1 + packages/web/i18n/{zh => zh-CN}/common.json | 4 +- packages/web/i18n/{zh => zh-CN}/dataset.json | 0 packages/web/i18n/{zh => zh-CN}/file.json | 0 packages/web/i18n/{zh => zh-CN}/login.json | 0 packages/web/i18n/{zh => zh-CN}/publish.json | 0 packages/web/i18n/{zh => zh-CN}/user.json | 0 packages/web/i18n/{zh => zh-CN}/workflow.json | 0 packages/web/i18n/{zh_TW => zh-TW}/app.json | 0 packages/web/i18n/{zh_TW => zh-TW}/chat.json | 0 .../web/i18n/{zh_TW => zh-TW}/common.json | 0 .../web/i18n/{zh_TW => zh-TW}/dataset.json | 0 packages/web/i18n/{zh_TW => zh-TW}/file.json | 0 packages/web/i18n/{zh_TW => zh-TW}/login.json | 0 .../web/i18n/{zh_TW => zh-TW}/publish.json | 0 packages/web/i18n/{zh_TW => zh-TW}/user.json | 0 .../web/i18n/{zh_TW => zh-TW}/workflow.json | 0 packages/web/styles/theme.ts | 48 +- packages/web/types/i18next.d.ts | 18 +- projects/app/next-i18next.config.js | 4 +- projects/app/next.config.js | 3 +- projects/app/package.json | 2 +- .../app/public/imgs/app/autoExec-icon.svg | 8 + projects/app/public/imgs/app/autoExec.svg | 91 ++++ projects/app/src/components/Layout/navbar.tsx | 12 +- .../app/src/components/Layout/navbarPhone.tsx | 8 +- .../src/components/Select/I18nLngSelector.tsx | 4 +- .../components/core/app/AutoExecConfig.tsx | 87 ++++ .../components/core/app/InputGuideConfig.tsx | 4 +- .../core/app/ScheduledTriggerConfig.tsx | 10 +- projects/app/src/components/core/app/Tip.tsx | 9 +- .../src/components/core/app/VariableEdit.tsx | 138 +++--- .../src/components/core/app/WhisperConfig.tsx | 11 +- .../ChatContainer/ChatBox/Input/ChatInput.tsx | 25 +- .../chat/ChatContainer/ChatBox/Provider.tsx | 157 +++---- .../ChatBox/components/ChatController.tsx | 66 ++- .../ChatBox/components/ChatItem.tsx | 2 +- .../ChatBox/components/ContextModal.tsx | 10 +- .../ChatBox/components/QuoteModal.tsx | 24 +- .../ChatBox/components/ResponseTags.tsx | 1 + .../ChatBox/components/TimeBox.tsx | 19 + .../ChatBox/components/VariableInput.tsx | 40 +- .../ChatBox/components/WelcomeBox.tsx | 4 +- .../ChatBox/hooks/useFileUpload.tsx | 20 +- .../core/chat/ChatContainer/ChatBox/index.tsx | 441 +++++++++--------- .../core/chat/ChatContainer/ChatBox/type.d.ts | 1 + .../PluginRunBox/components/RenderInput.tsx | 40 +- .../PluginRunBox/components/RenderOutput.tsx | 6 +- .../components/RenderResponseDetail.tsx | 10 +- .../components/renderPluginInput.tsx | 14 +- .../ChatContainer/PluginRunBox/context.tsx | 99 ++-- .../chat/ChatContainer/PluginRunBox/index.tsx | 24 +- .../chat/ChatContainer/PluginRunBox/type.d.ts | 16 +- .../ChatContainer/components/FilePreview.tsx | 11 +- .../core/chat/ChatContainer/useChat.ts | 113 ----- .../core/chat/components/AIResponseBox.tsx | 14 +- .../chat/components/WholeResponseModal.tsx | 25 +- .../src/components/core/dataset/QuoteItem.tsx | 7 +- .../components/core/dataset/RawSourceBox.tsx | 22 +- .../core/dataset/SearchParamsTip.tsx | 12 + projects/app/src/global/core/ai/api.d.ts | 1 + projects/app/src/global/core/app/api.d.ts | 1 - projects/app/src/global/core/chat/api.d.ts | 5 +- projects/app/src/global/core/chat/utils.ts | 10 +- projects/app/src/instrumentation.ts | 55 +++ .../pages/api/common/file/previewContent.ts | 4 +- .../app/src/pages/api/common/file/upload.ts | 58 ++- .../src/pages/api/common/file/uploadImage.ts | 7 +- .../api/core/ai/agent/createQuestionGuide.ts | 20 +- .../core/ai/agent/v2/createQuestionGuide.ts | 47 ++ .../pages/api/core/app/transitionWorkflow.ts | 4 +- .../src/pages/api/core/app/version/publish.ts | 27 +- .../app/src/pages/api/core/chat/chatTest.ts | 145 ++++-- .../src/pages/api/core/chat/clearHistories.ts | 58 +-- .../app/src/pages/api/core/chat/delHistory.ts | 4 +- .../api/core/chat/feedback/adminUpdate.ts | 5 +- .../api/core/chat/feedback/closeCustom.ts | 5 +- .../core/chat/feedback/updateUserFeedback.ts | 91 ++-- .../src/pages/api/core/chat/getHistories.ts | 10 +- .../api/core/chat/getPaginationRecords.ts | 28 +- .../app/src/pages/api/core/chat/getResData.ts | 42 +- .../pages/api/core/chat/inputGuide/query.ts | 4 +- .../src/pages/api/core/chat/item/delete.ts | 8 +- .../src/pages/api/core/chat/item/getSpeech.ts | 18 +- .../src/pages/api/core/chat/outLink/init.ts | 11 +- .../app/src/pages/api/core/chat/team/init.ts | 19 +- .../dataset/collection/create/localFile.ts | 2 +- .../pages/api/core/dataset/collection/read.ts | 128 ++++- .../api/core/dataset/file/getPreviewChunks.ts | 4 +- .../src/pages/api/support/outLink/update.ts | 4 +- .../src/pages/api/v1/audio/transcriptions.ts | 5 +- .../app/src/pages/api/v1/chat/completions.ts | 23 +- .../components/Logs/DetailLogsModal.tsx | 121 +++-- .../Publish/Link/SelectUsingWayModal.tsx | 3 +- .../detail/components/Publish/Link/index.tsx | 15 +- .../detail/components/SimpleApp/AppCard.tsx | 51 +- .../detail/components/SimpleApp/ChatTest.tsx | 48 +- .../app/detail/components/SimpleApp/Edit.tsx | 2 +- .../detail/components/SimpleApp/Header.tsx | 1 - .../components/SimpleApp/useSnapshots.tsx | 6 +- .../components/WorkflowComponents/AppCard.tsx | 5 - .../WorkflowComponents/Flow/ChatTest.tsx | 56 ++- .../Flow/NodeTemplatesModal.tsx | 14 +- .../Flow/components/ButtonEdge.tsx | 15 +- .../Flow/components/ContextMenu.tsx | 2 +- .../Flow/hooks/useDebug.tsx | 2 +- .../Flow/nodes/NodeCode.tsx | 6 +- .../Flow/nodes/NodeComment.tsx | 2 +- .../Flow/nodes/NodeExtract/index.tsx | 97 ++-- .../NodeFormInput/InputFormEditModal.tsx | 2 +- .../Flow/nodes/NodeFormInput/index.tsx | 70 +-- .../nodes/NodePluginIO/InputTypeConfig.tsx | 7 +- .../NodePluginIO/PluginOutputEditModal.tsx | 1 + .../Flow/nodes/NodePluginIO/VariableTable.tsx | 108 ++--- .../Flow/nodes/NodeSystemConfig.tsx | 21 + .../NodeToolParams/ToolParamsEditModal.tsx | 2 +- .../Flow/nodes/NodeToolParams/index.tsx | 127 +++-- .../Flow/nodes/NodeTools.tsx | 2 +- .../Flow/nodes/NodeVariableUpdate.tsx | 4 +- .../Flow/nodes/render/Handle/ToolHandle.tsx | 4 + .../Flow/nodes/render/NodeCard.tsx | 123 +++-- .../templates/DynamicInputs/index.tsx | 3 +- .../RenderInput/templates/SelectDataset.tsx | 11 +- .../Flow/nodes/render/RenderOutput/index.tsx | 8 +- .../Flow/nodes/render/ValueTypeLabel.tsx | 3 +- .../WorkflowComponents/constants.tsx | 2 +- .../app/detail/components/useChatTest.tsx | 133 +++--- projects/app/src/pages/app/detail/index.tsx | 11 +- .../src/pages/app/list/components/List.tsx | 17 +- projects/app/src/pages/app/list/index.tsx | 145 +++--- .../chat/components/ChatHistorySlider.tsx | 108 ++--- .../chat/components/CustomPluginRunBox.tsx | 8 +- .../src/pages/chat/components/SliderApps.tsx | 1 - projects/app/src/pages/chat/index.tsx | 202 +++----- projects/app/src/pages/chat/share.tsx | 296 +++++------- projects/app/src/pages/chat/team.tsx | 247 ++++------ .../Import/components/FileSelector.tsx | 6 + projects/app/src/pages/dataset/list/index.tsx | 9 +- projects/app/src/pages/login/fastlogin.tsx | 8 +- projects/app/src/pages/login/index.tsx | 13 +- projects/app/src/pages/login/provider.tsx | 8 +- projects/app/src/pages/login/sso.tsx | 6 +- .../app/src/service/common/system/index.ts | 2 +- projects/app/src/service/core/app/plugin.ts | 2 +- projects/app/src/service/middleware/entry.ts | 3 +- projects/app/src/service/mongo.ts | 38 +- .../service/support/permission/auth/chat.ts | 215 ++++++--- .../support/permission/auth/outLink.ts | 20 +- .../service/support/permission/auth/team.ts | 10 +- .../support/wallet/usage/controller.ts | 16 +- projects/app/src/web/common/api/request.ts | 3 +- .../app/src/web/common/file/controller.ts | 14 +- projects/app/src/web/common/utils/i18n.ts | 11 +- projects/app/src/web/core/app/utils.ts | 6 +- .../src/web/core/chat/context/chatContext.tsx | 189 +++++--- .../web/core/chat/context/chatItemContext.tsx | 125 +++++ .../core/chat/context/chatRecordContext.tsx | 121 +++++ .../src/web/core/chat/context/storeChat.ts | 39 -- .../src/web/core/chat/context/useChatStore.ts | 129 +++++ .../dataset/context/datasetPageContext.tsx | 2 +- .../dataset/hooks/readCollectionSource.ts | 16 +- projects/app/src/web/core/workflow/utils.ts | 64 ++- 221 files changed, 3831 insertions(+), 2737 deletions(-) create mode 100644 packages/web/components/common/Icon/button.tsx create mode 100644 packages/web/components/common/Icon/icons/checkCircle.svg create mode 100644 packages/web/components/common/Icon/icons/core/app/simpleMode/autoExec.svg create mode 100644 packages/web/components/common/Icon/icons/core/workflow/edgeArrowBold.svg rename packages/web/i18n/{zh => zh-CN}/app.json (96%) rename packages/web/i18n/{zh => zh-CN}/chat.json (98%) rename packages/web/i18n/{zh => zh-CN}/common.json (99%) rename packages/web/i18n/{zh => zh-CN}/dataset.json (100%) rename packages/web/i18n/{zh => zh-CN}/file.json (100%) rename packages/web/i18n/{zh => zh-CN}/login.json (100%) rename packages/web/i18n/{zh => zh-CN}/publish.json (100%) rename packages/web/i18n/{zh => zh-CN}/user.json (100%) rename packages/web/i18n/{zh => zh-CN}/workflow.json (100%) rename packages/web/i18n/{zh_TW => zh-TW}/app.json (100%) rename packages/web/i18n/{zh_TW => zh-TW}/chat.json (100%) rename packages/web/i18n/{zh_TW => zh-TW}/common.json (100%) rename packages/web/i18n/{zh_TW => zh-TW}/dataset.json (100%) rename packages/web/i18n/{zh_TW => zh-TW}/file.json (100%) rename packages/web/i18n/{zh_TW => zh-TW}/login.json (100%) rename packages/web/i18n/{zh_TW => zh-TW}/publish.json (100%) rename packages/web/i18n/{zh_TW => zh-TW}/user.json (100%) rename packages/web/i18n/{zh_TW => zh-TW}/workflow.json (100%) create mode 100644 projects/app/public/imgs/app/autoExec-icon.svg create mode 100644 projects/app/public/imgs/app/autoExec.svg create mode 100644 projects/app/src/components/core/app/AutoExecConfig.tsx create mode 100644 projects/app/src/components/core/chat/ChatContainer/ChatBox/components/TimeBox.tsx delete mode 100644 projects/app/src/components/core/chat/ChatContainer/useChat.ts create mode 100644 projects/app/src/instrumentation.ts create mode 100644 projects/app/src/pages/api/core/ai/agent/v2/createQuestionGuide.ts create mode 100644 projects/app/src/web/core/chat/context/chatItemContext.tsx create mode 100644 projects/app/src/web/core/chat/context/chatRecordContext.tsx delete mode 100644 projects/app/src/web/core/chat/context/storeChat.ts create mode 100644 projects/app/src/web/core/chat/context/useChatStore.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 2508d1ce8..c674d0733 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,8 +16,8 @@ "i18n-ally.keystyle": "flat", "i18n-ally.sortKeys": true, "i18n-ally.keepFulfilled": false, - "i18n-ally.sourceLanguage": "zh", // 根据此语言文件翻译其他语言文件的变量和内容 - "i18n-ally.displayLanguage": "zh", // 显示语言 + "i18n-ally.sourceLanguage": "zh-CN", // 根据此语言文件翻译其他语言文件的变量和内容 + "i18n-ally.displayLanguage": "zh-CN", // 显示语言 "i18n-ally.namespace": true, "i18n-ally.pathMatcher": "{locale}/{namespaces}.json", "i18n-ally.extract.targetPickingStrategy": "most-similar-by-key", diff --git a/docSite/content/zh-cn/docs/development/upgrading/4814.md b/docSite/content/zh-cn/docs/development/upgrading/4814.md index 98eb146b0..25082023a 100644 --- a/docSite/content/zh-cn/docs/development/upgrading/4814.md +++ b/docSite/content/zh-cn/docs/development/upgrading/4814.md @@ -7,13 +7,19 @@ toc: true weight: 810 --- -## 更新预告 +## 更新内容 -1. -2. 新增 - 工作流支持进入聊天框/点击开始对话后,自动触发一轮对话。 -3. 新增 - 重写 chatContext,对话测试也会有日志,并且刷新后不会丢失对话。 -4. 新增 - 分享链接支持配置是否允许查看原文。 -5. 优化 - 工作流 ui 细节。 -6. 优化 - 应用编辑记录采用 diff 存储,避免浏览器溢出。 -7. 修复 - 分块策略,四级标题会被丢失。 同时新增了五级标题的支持。 -8. 修复 - MongoDB 知识库集合唯一索引。 +1. 新增 - 工作流支持进入聊天框/点击开始对话后,自动触发一轮对话。 +2. 新增 - 重写 chatContext,对话测试也会有日志,并且刷新后不会丢失对话。 +3. 新增 - 分享链接支持配置是否允许查看原文。 +4. 新增 - 新的 doc2x 插件。 +5. 新增 - 繁体中文-台湾。 +6. 优化 - 工作流 ui 细节。 +7. 优化 - 应用编辑记录采用 diff 存储,避免浏览器溢出。 +8. 优化 - 代码入口,增加 register 入口,无需等待首次访问才执行。 +9. 优化 - 工作流检查,增加更多缺失值检查。 +10. 修复 - 分块策略,四级标题会被丢失。 同时新增了五级标题的支持。 +11. 修复 - MongoDB 知识库集合唯一索引。 +12. 修复 - 反选知识库引用后可能会报错。 +13. 修复 - 简易模式转工作流,不是使用最新编辑记录进行转移。 +14. 修复 - 表单输入的说明文字不显示。 diff --git a/packages/global/common/file/icon.ts b/packages/global/common/file/icon.ts index 5c56cd19b..40928c5c2 100644 --- a/packages/global/common/file/icon.ts +++ b/packages/global/common/file/icon.ts @@ -12,5 +12,7 @@ export const fileImgs = [ ]; export function getFileIcon(name = '', defaultImg = 'file/fill/file') { - return fileImgs.find((item) => new RegExp(item.suffix, 'gi').test(name))?.src || defaultImg; + return ( + fileImgs.find((item) => new RegExp(`\.${item.suffix}`, 'gi').test(name))?.src || defaultImg + ); } diff --git a/packages/global/common/file/type.d.ts b/packages/global/common/file/type.d.ts index dfe8b21c6..55f1747ca 100644 --- a/packages/global/common/file/type.d.ts +++ b/packages/global/common/file/type.d.ts @@ -3,6 +3,7 @@ import { BucketNameEnum } from './constants'; export type FileTokenQuery = { bucketName: `${BucketNameEnum}`; teamId: string; - tmbId: string; + uid: string; // tmbId/ share uid/ teamChat uid fileId: string; + customExpireMinutes?: number; }; diff --git a/packages/global/common/string/textSplitter.ts b/packages/global/common/string/textSplitter.ts index 7694e604a..940aece50 100644 --- a/packages/global/common/string/textSplitter.ts +++ b/packages/global/common/string/textSplitter.ts @@ -140,9 +140,10 @@ const commonSplit = (props: SplitProps): SplitResponse => { const customRegLen = customReg.length; const checkIsCustomStep = (step: number) => step < customRegLen; - const checkIsMarkdownSplit = (step: number) => step >= customRegLen && step <= markdownIndex; + const checkIsMarkdownSplit = (step: number) => + step >= customRegLen && step <= markdownIndex + customRegLen; +customReg.length; - const checkForbidOverlap = (step: number) => step <= forbidOverlapIndex + customReg.length; + const checkForbidOverlap = (step: number) => step <= forbidOverlapIndex + customRegLen; // if use markdown title split, Separate record title const getSplitTexts = ({ text, step }: { text: string; step: number }) => { diff --git a/packages/global/core/ai/type.d.ts b/packages/global/core/ai/type.d.ts index f87d4d928..a245af7ca 100644 --- a/packages/global/core/ai/type.d.ts +++ b/packages/global/core/ai/type.d.ts @@ -49,6 +49,7 @@ export type ChatCompletionMessageParam = ( | CustomChatCompletionAssistantMessageParam ) & { dataId?: string; + hideInUI?: boolean; }; export type SdkChatCompletionMessageParam = SdkChatCompletionMessageParam; diff --git a/packages/global/core/app/constants.ts b/packages/global/core/app/constants.ts index e6600f23c..d9bc42abb 100644 --- a/packages/global/core/app/constants.ts +++ b/packages/global/core/app/constants.ts @@ -1,4 +1,9 @@ -import { AppTTSConfigType, AppFileSelectConfigType, AppWhisperConfigType } from './type'; +import { + AppTTSConfigType, + AppFileSelectConfigType, + AppWhisperConfigType, + AppAutoExecuteConfigType +} from './type'; export enum AppTypeEnum { folder = 'folder', @@ -12,6 +17,11 @@ export const AppFolderTypeList = [AppTypeEnum.folder, AppTypeEnum.httpPlugin]; export const defaultTTSConfig: AppTTSConfigType = { type: 'web' }; +export const defaultAutoExecuteConfig: AppAutoExecuteConfigType = { + open: false, + defaultPrompt: '' +}; + export const defaultWhisperConfig: AppWhisperConfigType = { open: false, autoSend: false, diff --git a/packages/global/core/app/type.d.ts b/packages/global/core/app/type.d.ts index 8f6cf209a..916720591 100644 --- a/packages/global/core/app/type.d.ts +++ b/packages/global/core/app/type.d.ts @@ -96,6 +96,7 @@ export type AppSimpleEditFormType = { export type AppChatConfigType = { welcomeText?: string; variables?: VariableItemType[]; + autoExecute?: AppAutoExecuteConfigType; questionGuide?: boolean; ttsConfig?: AppTTSConfigType; whisperConfig?: AppWhisperConfigType; @@ -158,6 +159,11 @@ export type AppScheduledTriggerConfigType = { timezone: string; defaultPrompt: string; }; +// auto execute +export type AppAutoExecuteConfigType = { + open: boolean; + defaultPrompt: string; +}; // File export type AppFileSelectConfigType = { canSelectFile: boolean; diff --git a/packages/global/core/chat/adapt.ts b/packages/global/core/chat/adapt.ts index 02a85fe1c..0362efe16 100644 --- a/packages/global/core/chat/adapt.ts +++ b/packages/global/core/chat/adapt.ts @@ -76,6 +76,7 @@ export const chats2GPTMessages = ({ results.push({ dataId, + hideInUI: item.hideInUI, role: ChatCompletionRequestMessageRoleEnum.User, content: simpleUserContentPart(value) }); @@ -318,6 +319,7 @@ export const GPTMessages2Chats = ( return { dataId: item.dataId, obj, + hideInUI: item.hideInUI, value } as ChatItemType; }) diff --git a/packages/global/core/chat/type.d.ts b/packages/global/core/chat/type.d.ts index 3d16c2653..72be2e388 100644 --- a/packages/global/core/chat/type.d.ts +++ b/packages/global/core/chat/type.d.ts @@ -56,6 +56,7 @@ export type UserChatItemValueItemType = { export type UserChatItemType = { obj: ChatRoleEnum.Human; value: UserChatItemValueItemType[]; + hideInUI?: boolean; }; export type SystemChatItemValueItemType = { type: ChatItemValueTypeEnum.text; diff --git a/packages/global/core/chat/utils.ts b/packages/global/core/chat/utils.ts index e8900081c..4b7eba63c 100644 --- a/packages/global/core/chat/utils.ts +++ b/packages/global/core/chat/utils.ts @@ -101,7 +101,7 @@ export const filterPublicNodeResponseData = ({ for (let key in item) { if (key === 'toolDetail' || key === 'pluginDetail') { // @ts-ignore - obj[key] = filterPublicNodeResponseData({ flowResponses: item[key] }); + obj[key] = filterPublicNodeResponseData({ flowResponses: item[key], responseDetail }); } else if (filedList.includes(key)) { // @ts-ignore obj[key] = item[key]; diff --git a/packages/global/core/dataset/type.d.ts b/packages/global/core/dataset/type.d.ts index ada60a1e1..f215d9ef5 100644 --- a/packages/global/core/dataset/type.d.ts +++ b/packages/global/core/dataset/type.d.ts @@ -204,7 +204,8 @@ export type DatasetFileSchema = { contentType: string; metadata: { teamId: string; - tmbId: string; + tmbId?: string; + uid: string; encoding?: string; }; }; diff --git a/packages/global/core/workflow/constants.ts b/packages/global/core/workflow/constants.ts index 578a81b3b..d93c7ada3 100644 --- a/packages/global/core/workflow/constants.ts +++ b/packages/global/core/workflow/constants.ts @@ -106,6 +106,7 @@ export enum NodeInputKeyEnum { variables = 'variables', scheduleTrigger = 'scheduleTrigger', chatInputGuide = 'chatInputGuide', + autoExecute = 'autoExecute', // plugin config instruction = 'instruction', diff --git a/packages/global/core/workflow/utils.ts b/packages/global/core/workflow/utils.ts index d4a5a4a29..3e082c235 100644 --- a/packages/global/core/workflow/utils.ts +++ b/packages/global/core/workflow/utils.ts @@ -25,10 +25,12 @@ import type { AppWhisperConfigType, AppScheduledTriggerConfigType, ChatInputGuideConfigType, - AppChatConfigType + AppChatConfigType, + AppAutoExecuteConfigType } from '../app/type'; import { EditorVariablePickerType } from '../../../web/components/common/Textarea/PromptEditor/type'; import { + defaultAutoExecuteConfig, defaultChatInputGuideConfig, defaultTTSConfig, defaultWhisperConfig @@ -69,34 +71,37 @@ export const getGuideModule = (modules: StoreNodeItemType[]) => ); export const splitGuideModule = (guideModules?: StoreNodeItemType) => { const welcomeText: string = - guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.welcomeText)?.value || ''; + guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.welcomeText)?.value ?? ''; const variables: VariableItemType[] = - guideModules?.inputs.find((item) => item.key === NodeInputKeyEnum.variables)?.value || []; + guideModules?.inputs.find((item) => item.key === NodeInputKeyEnum.variables)?.value ?? []; const questionGuide: boolean = - !!guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.questionGuide)?.value || + !!guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.questionGuide)?.value ?? false; const ttsConfig: AppTTSConfigType = - guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.tts)?.value || + guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.tts)?.value ?? defaultTTSConfig; const whisperConfig: AppWhisperConfigType = - guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.whisper)?.value || + guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.whisper)?.value ?? defaultWhisperConfig; - const scheduledTriggerConfig: AppScheduledTriggerConfigType = guideModules?.inputs?.find( - (item) => item.key === NodeInputKeyEnum.scheduleTrigger - )?.value; + const scheduledTriggerConfig: AppScheduledTriggerConfigType = + guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.scheduleTrigger)?.value ?? + undefined; const chatInputGuide: ChatInputGuideConfigType = - guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.chatInputGuide)?.value || + guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.chatInputGuide)?.value ?? defaultChatInputGuideConfig; - // plugin const instruction: string = - guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.instruction)?.value || ''; + guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.instruction)?.value ?? ''; + + const autoExecute: AppAutoExecuteConfigType = + guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.autoExecute)?.value ?? + defaultAutoExecuteConfig; return { welcomeText, @@ -106,7 +111,8 @@ export const splitGuideModule = (guideModules?: StoreNodeItemType) => { whisperConfig, scheduledTriggerConfig, chatInputGuide, - instruction + instruction, + autoExecute }; }; @@ -132,7 +138,8 @@ export const getAppChatConfig = ({ whisperConfig, scheduledTriggerConfig, chatInputGuide, - instruction + instruction, + autoExecute } = splitGuideModule(systemConfigNode); const config: AppChatConfigType = { @@ -142,6 +149,7 @@ export const getAppChatConfig = ({ scheduledTriggerConfig, chatInputGuide, instruction, + autoExecute, ...chatConfig, variables: storeVariables ?? chatConfig?.variables ?? variables, welcomeText: storeWelcomeText ?? chatConfig?.welcomeText ?? welcomeText diff --git a/packages/service/common/file/gridfs/controller.ts b/packages/service/common/file/gridfs/controller.ts index 2d0d915f6..a5693e39b 100644 --- a/packages/service/common/file/gridfs/controller.ts +++ b/packages/service/common/file/gridfs/controller.ts @@ -32,7 +32,7 @@ export function getGridBucket(bucket: `${BucketNameEnum}`) { export async function uploadFile({ bucketName, teamId, - tmbId, + uid, path, filename, contentType, @@ -41,7 +41,7 @@ export async function uploadFile({ }: { bucketName: `${BucketNameEnum}`; teamId: string; - tmbId: string; + uid: string; // tmbId / outLinkUId path: string; filename: string; contentType?: string; @@ -58,7 +58,7 @@ export async function uploadFile({ // Add default metadata metadata.teamId = teamId; - metadata.tmbId = tmbId; + metadata.uid = uid; metadata.encoding = encoding; // create a gridfs bucket diff --git a/packages/service/common/file/multer.ts b/packages/service/common/file/multer.ts index 876060d5a..460d8ae79 100644 --- a/packages/service/common/file/multer.ts +++ b/packages/service/common/file/multer.ts @@ -4,7 +4,7 @@ import path from 'path'; import { BucketNameEnum, bucketNameMap } from '@fastgpt/global/common/file/constants'; import { getNanoid } from '@fastgpt/global/common/string/tools'; -type FileType = { +export type FileType = { fieldname: string; originalname: string; encoding: string; @@ -41,7 +41,7 @@ export const getUploadModel = ({ maxSize = 500 }: { maxSize?: number }) => { }) }).single('file'); - async doUpload>( + async doUpload( req: NextApiRequest, res: NextApiResponse, originBucketName?: `${BucketNameEnum}` diff --git a/packages/service/core/ai/config.ts b/packages/service/core/ai/config.ts index 3b05d0729..c30f5cc51 100644 --- a/packages/service/core/ai/config.ts +++ b/packages/service/core/ai/config.ts @@ -6,6 +6,7 @@ import { } from '@fastgpt/global/core/ai/type'; import { getErrText } from '@fastgpt/global/common/error/utils'; import { addLog } from '../../common/system/log'; +import { i18nT } from '../../../web/i18n/utils'; export const openaiBaseUrl = process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1'; @@ -62,6 +63,7 @@ export const createChatCompletion = async ({ }): Promise<{ response: InferResponseType; isStreamResponse: boolean; + getEmptyResponseTip: () => string; }> => { try { const formatTimeout = timeout ? timeout : body.stream ? 60000 : 600000; @@ -76,9 +78,21 @@ export const createChatCompletion = async ({ response !== null && ('iterator' in response || 'controller' in response); + const getEmptyResponseTip = () => { + addLog.warn(`LLM response empty`, { + baseUrl: userKey?.baseUrl, + requestBody: body + }); + if (userKey?.baseUrl) { + return `您的 OpenAI key 没有响应: ${JSON.stringify(body)}`; + } + return i18nT('chat:LLM_model_response_empty'); + }; + return { response: response as InferResponseType, - isStreamResponse + isStreamResponse, + getEmptyResponseTip }; } catch (error) { addLog.error(`LLM response error`, error); diff --git a/packages/service/core/app/schema.ts b/packages/service/core/app/schema.ts index 4b069cb8c..71bb2ad33 100644 --- a/packages/service/core/app/schema.ts +++ b/packages/service/core/app/schema.ts @@ -17,7 +17,8 @@ export const chatConfigType = { scheduledTriggerConfig: Object, chatInputGuide: Object, fileSelectConfig: Object, - instruction: String + instruction: String, + autoExecute: Object }; // schema diff --git a/packages/service/core/chat/chatItemSchema.ts b/packages/service/core/chat/chatItemSchema.ts index e549ef601..237ae49c9 100644 --- a/packages/service/core/chat/chatItemSchema.ts +++ b/packages/service/core/chat/chatItemSchema.ts @@ -46,6 +46,10 @@ const ChatItemSchema = new Schema({ type: Date, default: () => new Date() }, + hideInUI: { + type: Boolean, + default: false + }, obj: { // chat role type: String, diff --git a/packages/service/core/chat/saveChat.ts b/packages/service/core/chat/saveChat.ts index 1b78e1e70..4004a8a1c 100644 --- a/packages/service/core/chat/saveChat.ts +++ b/packages/service/core/chat/saveChat.ts @@ -1,15 +1,6 @@ -import type { - AIChatItemType, - ChatItemType, - UserChatItemType -} from '@fastgpt/global/core/chat/type.d'; -import axios from 'axios'; +import type { AIChatItemType, UserChatItemType } from '@fastgpt/global/core/chat/type.d'; import { MongoApp } from '../app/schema'; -import { - ChatItemValueTypeEnum, - ChatRoleEnum, - ChatSourceEnum -} from '@fastgpt/global/core/chat/constants'; +import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; import { MongoChatItem } from './chatItemSchema'; import { MongoChat } from './chatSchema'; import { addLog } from '../../common/system/log'; @@ -133,21 +124,15 @@ export async function saveChat({ export const updateInteractiveChat = async ({ chatId, appId, - teamId, - tmbId, userInteractiveVal, aiResponse, - newVariables, - newTitle + newVariables }: { chatId: string; appId: string; - teamId: string; - tmbId: string; userInteractiveVal: string; aiResponse: AIChatItemType & { dataId?: string }; newVariables?: Record; - newTitle: string; }) => { if (!chatId) return; @@ -232,7 +217,6 @@ export const updateInteractiveChat = async ({ { $set: { variables: newVariables, - title: newTitle, updateTime: new Date() } }, diff --git a/packages/service/core/dataset/collection/controller.ts b/packages/service/core/dataset/collection/controller.ts index a19a279a1..efd667464 100644 --- a/packages/service/core/dataset/collection/controller.ts +++ b/packages/service/core/dataset/collection/controller.ts @@ -67,7 +67,7 @@ export async function createOneCollection({ fileId, rawLink, - externalFileId, + ...(externalFileId ? { externalFileId } : {}), externalFileUrl, rawTextLength, diff --git a/packages/service/core/dataset/collection/schema.ts b/packages/service/core/dataset/collection/schema.ts index 5450b4c1b..00df3dc05 100644 --- a/packages/service/core/dataset/collection/schema.ts +++ b/packages/service/core/dataset/collection/schema.ts @@ -118,7 +118,7 @@ try { { unique: true, partialFilterExpression: { - externalFileId: { $exists: true, $ne: '' } + externalFileId: { $exists: true } } } ); diff --git a/packages/service/core/dataset/training/controller.ts b/packages/service/core/dataset/training/controller.ts index d09576bf4..fb01e709c 100644 --- a/packages/service/core/dataset/training/controller.ts +++ b/packages/service/core/dataset/training/controller.ts @@ -77,7 +77,7 @@ export async function pushDataListToTrainingQueue({ if (trainingMode === TrainingModeEnum.chunk) { return { - maxToken: vectorModelData.maxToken * 1.3, + maxToken: vectorModelData.maxToken * 1.5, model: vectorModelData.model, weight: vectorModelData.weight }; @@ -125,10 +125,7 @@ export async function pushDataListToTrainingQueue({ const text = item.q + item.a; - // count q token - const token = item.q.length; - - if (token > maxToken) { + if (text.length > maxToken) { filterResult.overToken.push(item); return; } diff --git a/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts b/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts index 6084fb994..daab1c0aa 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/functionCall.ts @@ -27,7 +27,6 @@ import { computedMaxToken, llmCompletionsBodyFormat } from '../../../../ai/utils import { toolValueTypeList } from '@fastgpt/global/core/workflow/constants'; import { WorkflowInteractiveResponseType } from '@fastgpt/global/core/workflow/template/system/interactive/type'; import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants'; -import { i18nT } from '../../../../../../web/i18n/utils'; type FunctionRunResponseType = { toolRunResponse: DispatchFlowResponse; @@ -216,7 +215,11 @@ export const runToolWithFunctionCall = async ( // console.log(JSON.stringify(requestMessages, null, 2)); /* Run llm */ - const { response: aiResponse, isStreamResponse } = await createChatCompletion({ + const { + response: aiResponse, + isStreamResponse, + getEmptyResponseTip + } = await createChatCompletion({ body: requestBody, userKey: user.openaiAccount, options: { @@ -256,6 +259,9 @@ export const runToolWithFunctionCall = async ( }; } })(); + if (!answer && functionCalls.length === 0) { + return Promise.reject(getEmptyResponseTip()); + } // Run the selected tool. const toolsRunResponse = ( @@ -549,9 +555,5 @@ async function streamResponse({ } } - if (!textAnswer && functionCalls.length === 0) { - return Promise.reject(i18nT('chat:LLM_model_response_empty')); - } - return { answer: textAnswer, functionCalls }; } diff --git a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts b/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts index 661117752..0dc11e056 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts @@ -29,7 +29,6 @@ import { WorkflowResponseType } from '../../type'; import { toolValueTypeList } from '@fastgpt/global/core/workflow/constants'; import { WorkflowInteractiveResponseType } from '@fastgpt/global/core/workflow/template/system/interactive/type'; import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants'; -import { i18nT } from '../../../../../../web/i18n/utils'; type FunctionCallCompletion = { id: string; @@ -225,7 +224,11 @@ export const runToolWithPromptCall = async ( // console.log(JSON.stringify(requestMessages, null, 2)); /* Run llm */ - const { response: aiResponse, isStreamResponse } = await createChatCompletion({ + const { + response: aiResponse, + isStreamResponse, + getEmptyResponseTip + } = await createChatCompletion({ body: requestBody, userKey: user.openaiAccount, options: { @@ -251,8 +254,11 @@ export const runToolWithPromptCall = async ( return result.choices?.[0]?.message?.content || ''; } })(); - const { answer: replaceAnswer, toolJson } = parseAnswer(answer); + if (!answer && !toolJson) { + return Promise.reject(getEmptyResponseTip()); + } + // No tools if (!toolJson) { if (replaceAnswer === ERROR_TEXT) { @@ -534,9 +540,6 @@ async function streamResponse({ } } - if (!textAnswer) { - return Promise.reject(i18nT('chat:LLM_model_response_empty')); - } return { answer: textAnswer.trim() }; } diff --git a/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts b/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts index fbea9acab..80bc641db 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts @@ -272,7 +272,11 @@ export const runToolWithToolChoice = async ( ); // console.log(JSON.stringify(requestBody, null, 2), '==requestBody'); /* Run llm */ - const { response: aiResponse, isStreamResponse } = await createChatCompletion({ + const { + response: aiResponse, + isStreamResponse, + getEmptyResponseTip + } = await createChatCompletion({ body: requestBody, userKey: user.openaiAccount, options: { @@ -336,6 +340,9 @@ export const runToolWithToolChoice = async ( }; } })(); + if (!answer && toolCalls.length === 0) { + return Promise.reject(getEmptyResponseTip()); + } // Run the selected tool by LLM. const toolsRunResponse = ( @@ -645,9 +652,5 @@ async function streamResponse({ } } - if (!textAnswer && toolCalls.length === 0) { - return Promise.reject(i18nT('chat:LLM_model_response_empty')); - } - return { answer: textAnswer, toolCalls }; } diff --git a/packages/service/core/workflow/dispatch/chat/oneapi.ts b/packages/service/core/workflow/dispatch/chat/oneapi.ts index c652246eb..59cfe7afb 100644 --- a/packages/service/core/workflow/dispatch/chat/oneapi.ts +++ b/packages/service/core/workflow/dispatch/chat/oneapi.ts @@ -33,15 +33,13 @@ import { getLLMModel, ModelTypeEnum } from '../../../ai/model'; import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type'; import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants'; -import { getHistories } from '../utils'; +import { checkQuoteQAValue, getHistories } from '../utils'; import { filterSearchResultsByMaxChars } from '../../utils'; import { getHistoryPreview } from '@fastgpt/global/core/chat/utils'; -import { addLog } from '../../../../common/system/log'; import { computedMaxToken, llmCompletionsBodyFormat } from '../../../ai/utils'; import { WorkflowResponseType } from '../type'; import { formatTime2YMDHM } from '@fastgpt/global/common/string/time'; import { AiChatQuoteRoleType } from '@fastgpt/global/core/workflow/template/system/aiChat/type'; -import { getErrText } from '@fastgpt/global/common/error/utils'; import { getFileContentFromLinks, getHistoryFileLinks } from '../tools/readFiles'; import { parseUrlToFileType } from '@fastgpt/global/common/file/tools'; import { i18nT } from '../../../../../web/i18n/utils'; @@ -93,6 +91,7 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise { - if (res && isStreamResponse) { - // sse response - const { answer } = await streamResponse({ - res, - stream: response, - workflowStreamResponse + const { answerText } = await (async () => { + if (res && isStreamResponse) { + // sse response + const { answer } = await streamResponse({ + res, + stream: response, + workflowStreamResponse + }); + + return { + answerText: answer + }; + } else { + const unStreamResponse = response as ChatCompletion; + const answer = unStreamResponse.choices?.[0]?.message?.content || ''; + + if (stream) { + // Some models do not support streaming + workflowStreamResponse?.({ + event: SseResponseEventEnum.fastAnswer, + data: textAdaptGptResponse({ + text: answer + }) }); - - if (!answer) { - return Promise.reject(i18nT('chat:LLM_model_response_empty')); - } - - return { - answerText: answer - }; - } else { - const unStreamResponse = response as ChatCompletion; - const answer = unStreamResponse.choices?.[0]?.message?.content || ''; - - if (stream) { - // Some models do not support streaming - workflowStreamResponse?.({ - event: SseResponseEventEnum.fastAnswer, - data: textAdaptGptResponse({ - text: answer - }) - }); - } - - return { - answerText: answer - }; } - })(); - const completeMessages = requestMessages.concat({ - role: ChatCompletionRequestMessageRoleEnum.Assistant, - content: answerText - }); - const chatCompleteMessages = GPTMessages2Chats(completeMessages); + return { + answerText: answer + }; + } + })(); - const tokens = await countMessagesTokens(chatCompleteMessages); - const { totalPoints, modelName } = formatModelChars2Points({ - model, + if (!answerText) { + return Promise.reject(getEmptyResponseTip()); + } + + const completeMessages = requestMessages.concat({ + role: ChatCompletionRequestMessageRoleEnum.Assistant, + content: answerText + }); + const chatCompleteMessages = GPTMessages2Chats(completeMessages); + + const tokens = await countMessagesTokens(chatCompleteMessages); + const { totalPoints, modelName } = formatModelChars2Points({ + model, + tokens, + modelType: ModelTypeEnum.llm + }); + + return { + answerText, + [DispatchNodeResponseKeyEnum.nodeResponse]: { + totalPoints: user.openaiAccount?.key ? 0 : totalPoints, + model: modelName, tokens, - modelType: ModelTypeEnum.llm - }); - - return { - answerText, - [DispatchNodeResponseKeyEnum.nodeResponse]: { + query: `${userChatInput}`, + maxToken: max_tokens, + historyPreview: getHistoryPreview( + chatCompleteMessages, + 10000, + modelConstantsData.vision && aiChatVision + ), + contextTotalLen: completeMessages.length + }, + [DispatchNodeResponseKeyEnum.nodeDispatchUsages]: [ + { + moduleName: name, totalPoints: user.openaiAccount?.key ? 0 : totalPoints, model: modelName, - tokens, - query: `${userChatInput}`, - maxToken: max_tokens, - historyPreview: getHistoryPreview( - chatCompleteMessages, - 10000, - modelConstantsData.vision && aiChatVision - ), - contextTotalLen: completeMessages.length - }, - [DispatchNodeResponseKeyEnum.nodeDispatchUsages]: [ - { - moduleName: name, - totalPoints: user.openaiAccount?.key ? 0 : totalPoints, - model: modelName, - tokens - } - ], - [DispatchNodeResponseKeyEnum.toolResponses]: answerText, - history: chatCompleteMessages - }; - } catch (error) { - if (user.openaiAccount?.baseUrl) { - return Promise.reject(`您的 OpenAI key 出错了: ${getErrText(error)}`); - } - - return Promise.reject(error); - } + tokens + } + ], + [DispatchNodeResponseKeyEnum.toolResponses]: answerText, + history: chatCompleteMessages + }; }; async function filterDatasetQuote({ diff --git a/packages/service/core/workflow/dispatch/tools/http468.ts b/packages/service/core/workflow/dispatch/tools/http468.ts index cbedf4ea8..307edd350 100644 --- a/packages/service/core/workflow/dispatch/tools/http468.ts +++ b/packages/service/core/workflow/dispatch/tools/http468.ts @@ -209,7 +209,6 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise { const systemPluginCb = global.systemPluginCb; - console.log(systemPluginCb, '-=', httpReqUrl); if (systemPluginCb[httpReqUrl]) { const pluginResult = await replaceSystemPluginResponse({ response: await systemPluginCb[httpReqUrl](requestBody), @@ -395,7 +394,7 @@ async function replaceSystemPluginResponse({ response[key] = `${ReadFileBaseUrl}/${filename}?token=${await createFileToken({ bucketName: 'chat', teamId, - tmbId, + uid: tmbId, fileId })}`; } catch (error) {} diff --git a/packages/service/core/workflow/dispatch/utils.ts b/packages/service/core/workflow/dispatch/utils.ts index 3ed92a6e9..3a183988b 100644 --- a/packages/service/core/workflow/dispatch/utils.ts +++ b/packages/service/core/workflow/dispatch/utils.ts @@ -13,6 +13,7 @@ import { responseWrite } from '../../../common/response'; import { NextApiResponse } from 'next'; import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants'; import { getNanoid } from '@fastgpt/global/common/string/tools'; +import { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type'; export const getWorkflowResponseWrite = ({ res, @@ -87,27 +88,6 @@ export const filterToolNodeIdByEdges = ({ .map((edge) => edge.target); }; -// export const checkTheModuleConnectedByTool = ( -// modules: StoreNodeItemType[], -// node: StoreNodeItemType -// ) => { -// let sign = false; -// const toolModules = modules.filter((item) => item.flowNodeType === FlowNodeTypeEnum.tools); - -// toolModules.forEach((item) => { -// const toolOutput = item.outputs.find( -// (output) => output.key === NodeOutputKeyEnum.selectedTools -// ); -// toolOutput?.targets.forEach((target) => { -// if (target.moduleId === node.moduleId) { -// sign = true; -// } -// }); -// }); - -// return sign; -// }; - export const getHistories = (history?: ChatItemType[] | number, histories: ChatItemType[] = []) => { if (!history) return []; @@ -149,6 +129,13 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => { return value; }; +export const checkQuoteQAValue = (quoteQA: SearchDataResponseItemType[] = []) => { + if (quoteQA.some((item) => !item.q || !item.datasetId)) { + return undefined; + } + return quoteQA; +}; + /* remove system variable */ export const removeSystemVariable = (variables: Record) => { const copyVariables = { ...variables }; diff --git a/packages/service/support/outLink/schema.ts b/packages/service/support/outLink/schema.ts index 51e470a94..4323a808c 100644 --- a/packages/service/support/outLink/schema.ts +++ b/packages/service/support/outLink/schema.ts @@ -48,7 +48,8 @@ const OutLinkSchema = new Schema({ default: false }, showNodeStatus: { - type: Boolean + type: Boolean, + default: true }, showRawSource: { type: Boolean diff --git a/packages/service/support/permission/auth/file.ts b/packages/service/support/permission/auth/file.ts index 8a54c509f..11d639e26 100644 --- a/packages/service/support/permission/auth/file.ts +++ b/packages/service/support/permission/auth/file.ts @@ -7,7 +7,7 @@ import { CommonErrEnum } from '@fastgpt/global/common/error/code/common'; import { OwnerPermissionVal, ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { Permission } from '@fastgpt/global/support/permission/controller'; -export async function authFile({ +export const authCollectionFile = async ({ fileId, per = OwnerPermissionVal, ...props @@ -17,7 +17,7 @@ export async function authFile({ AuthResponseType & { file: DatasetFileSchema; } -> { +> => { const authRes = await parseHeaderCert(props); const { teamId, tmbId } = authRes; @@ -33,7 +33,7 @@ export async function authFile({ const permission = new Permission({ per: ReadPermissionVal, - isOwner: file.metadata?.tmbId === tmbId + isOwner: file.metadata?.uid === tmbId || file.metadata?.tmbId === tmbId }); if (!permission.checkPer(per)) { @@ -45,4 +45,4 @@ export async function authFile({ permission, file }; -} +}; diff --git a/packages/service/support/permission/controller.ts b/packages/service/support/permission/controller.ts index 743759a5b..c68f07d1b 100644 --- a/packages/service/support/permission/controller.ts +++ b/packages/service/support/permission/controller.ts @@ -413,7 +413,8 @@ export const createFileToken = (data: FileTokenQuery) => { return Promise.reject('System unset FILE_TOKEN_KEY'); } - const expireMinutes = bucketNameMap[data.bucketName].previewExpireMinutes; + const expireMinutes = + data.customExpireMinutes ?? bucketNameMap[data.bucketName].previewExpireMinutes; const expiredTime = Math.floor(addMinutes(new Date(), expireMinutes).getTime() / 1000); const key = (process.env.FILE_TOKEN_KEY as string) ?? 'filetoken'; @@ -435,14 +436,14 @@ export const authFileToken = (token?: string) => const key = (process.env.FILE_TOKEN_KEY as string) ?? 'filetoken'; jwt.verify(token, key, function (err, decoded: any) { - if (err || !decoded.bucketName || !decoded?.teamId || !decoded?.tmbId || !decoded?.fileId) { + if (err || !decoded.bucketName || !decoded?.teamId || !decoded?.fileId) { reject(ERROR_ENUM.unAuthFile); return; } resolve({ bucketName: decoded.bucketName, teamId: decoded.teamId, - tmbId: decoded.tmbId, + uid: decoded.uid, fileId: decoded.fileId }); }); diff --git a/packages/service/support/permission/publish/authLink.ts b/packages/service/support/permission/publish/authLink.ts index 551437135..7e9c4f94d 100644 --- a/packages/service/support/permission/publish/authLink.ts +++ b/packages/service/support/permission/publish/authLink.ts @@ -62,14 +62,14 @@ export async function authOutLinkValid({ if (!shareId) { return Promise.reject(OutLinkErrEnum.linkUnInvalid); } - const shareChat = (await MongoOutLink.findOne({ shareId }).lean()) as OutLinkSchema; + const outLinkConfig = (await MongoOutLink.findOne({ shareId }).lean()) as OutLinkSchema; - if (!shareChat) { + if (!outLinkConfig) { return Promise.reject(OutLinkErrEnum.linkUnInvalid); } return { - appId: shareChat.appId, - shareChat + appId: outLinkConfig.appId, + outLinkConfig }; } diff --git a/packages/service/support/permission/type.d.ts b/packages/service/support/permission/type.d.ts index e6ce6c797..22b79d68e 100644 --- a/packages/service/support/permission/type.d.ts +++ b/packages/service/support/permission/type.d.ts @@ -2,6 +2,7 @@ import { Permission } from '@fastgpt/global/support/permission/controller'; import { ApiRequestProps } from '../../type/next'; import type { PermissionValueType } from '@fastgpt/global/support/permission/type'; import { RequireAtLeastOne } from '@fastgpt/global/common/type/utils'; +import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant'; export type ReqHeaderAuthType = { cookie?: string; diff --git a/packages/service/type.d.ts b/packages/service/type.d.ts index d8ffa5102..ad8e11399 100644 --- a/packages/service/type.d.ts +++ b/packages/service/type.d.ts @@ -23,9 +23,6 @@ declare global { var whisperModel: WhisperModelType; var reRankModels: ReRankModelItemType[]; - var systemLoadedGlobalVariables: boolean; - var systemLoadedGlobalConfig: boolean; - var workerPoll: Record; var appMarketTemplates: TemplateMarketItemType[]; } diff --git a/packages/web/common/system/utils.ts b/packages/web/common/system/utils.ts index 1015f699f..d51cf1aa1 100644 --- a/packages/web/common/system/utils.ts +++ b/packages/web/common/system/utils.ts @@ -10,6 +10,8 @@ export const hasHttps = () => { return window.location.protocol === 'https:'; }; +export const subRoute = process.env.NEXT_PUBLIC_BASE_URL; + export const getWebReqUrl = (url: string = '') => { if (!url) return '/'; const baseUrl = process.env.NEXT_PUBLIC_BASE_URL; diff --git a/packages/web/components/common/Icon/button.tsx b/packages/web/components/common/Icon/button.tsx new file mode 100644 index 000000000..38cd50a39 --- /dev/null +++ b/packages/web/components/common/Icon/button.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { Flex, FlexProps } from '@chakra-ui/react'; +import MyIcon from './index'; + +type Props = FlexProps & { + icon: string; + size?: string; + onClick?: () => void; + hoverColor?: string; +}; + +const MyIconButton = ({ + icon, + onClick, + hoverColor = 'primary.600', + size = '1rem', + ...props +}: Props) => { + return ( + + + + ); +}; + +export default MyIconButton; diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index da1bf101c..e6d3d82bb 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -5,6 +5,7 @@ export const iconPaths = { change: () => import('./icons/change.svg'), chatSend: () => import('./icons/chatSend.svg'), check: () => import('./icons/check.svg'), + checkCircle: () => import('./icons/checkCircle.svg'), closeSolid: () => import('./icons/closeSolid.svg'), collectionLight: () => import('./icons/collectionLight.svg'), collectionSolid: () => import('./icons/collectionSolid.svg'), @@ -101,6 +102,7 @@ export const iconPaths = { 'core/app/schedulePlan': () => import('./icons/core/app/schedulePlan.svg'), 'core/app/simpleBot': () => import('./icons/core/app/simpleBot.svg'), 'core/app/simpleMode/ai': () => import('./icons/core/app/simpleMode/ai.svg'), + 'core/app/simpleMode/autoExec': () => import('./icons/core/app/simpleMode/autoExec.svg'), 'core/app/simpleMode/chat': () => import('./icons/core/app/simpleMode/chat.svg'), 'core/app/simpleMode/dataset': () => import('./icons/core/app/simpleMode/dataset.svg'), 'core/app/simpleMode/file': () => import('./icons/core/app/simpleMode/file.svg'), @@ -183,6 +185,7 @@ export const iconPaths = { 'core/workflow/debugNext': () => import('./icons/core/workflow/debugNext.svg'), 'core/workflow/debugResult': () => import('./icons/core/workflow/debugResult.svg'), 'core/workflow/edgeArrow': () => import('./icons/core/workflow/edgeArrow.svg'), + 'core/workflow/edgeArrowBold': () => import('./icons/core/workflow/edgeArrowBold.svg'), 'core/workflow/grout': () => import('./icons/core/workflow/grout.svg'), 'core/workflow/inputType/array': () => import('./icons/core/workflow/inputType/array.svg'), 'core/workflow/inputType/customVariable': () => diff --git a/packages/web/components/common/Icon/icons/check.svg b/packages/web/components/common/Icon/icons/check.svg index 5332e6086..d43d66d29 100644 --- a/packages/web/components/common/Icon/icons/check.svg +++ b/packages/web/components/common/Icon/icons/check.svg @@ -1,3 +1,3 @@ - - + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/checkCircle.svg b/packages/web/components/common/Icon/icons/checkCircle.svg new file mode 100644 index 000000000..1c41452e0 --- /dev/null +++ b/packages/web/components/common/Icon/icons/checkCircle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/common/file/move.svg b/packages/web/components/common/Icon/icons/common/file/move.svg index 7e23ef30f..38465aaab 100644 --- a/packages/web/components/common/Icon/icons/common/file/move.svg +++ b/packages/web/components/common/Icon/icons/common/file/move.svg @@ -1 +1,6 @@ - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/app/simpleMode/autoExec.svg b/packages/web/components/common/Icon/icons/core/app/simpleMode/autoExec.svg new file mode 100644 index 000000000..287169b06 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/app/simpleMode/autoExec.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/workflow/edgeArrowBold.svg b/packages/web/components/common/Icon/icons/core/workflow/edgeArrowBold.svg new file mode 100644 index 000000000..bca309065 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/edgeArrowBold.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/web/components/common/Image/MyImage.tsx b/packages/web/components/common/Image/MyImage.tsx index b9f7a6a0e..9eaed1c1f 100644 --- a/packages/web/components/common/Image/MyImage.tsx +++ b/packages/web/components/common/Image/MyImage.tsx @@ -1,7 +1,7 @@ -import React from 'react'; +import React, { ForwardedRef, forwardRef } from 'react'; import { Image, ImageProps } from '@chakra-ui/react'; import { getWebReqUrl } from '../../../common/system/utils'; -const MyImage = (props: ImageProps) => { +const MyImage = (props: ImageProps, ref?: ForwardedRef) => { return ; }; -export default React.memo(MyImage); +export default forwardRef(MyImage); diff --git a/packages/web/components/common/MyMenu/index.tsx b/packages/web/components/common/MyMenu/index.tsx index c05128356..72a7db646 100644 --- a/packages/web/components/common/MyMenu/index.tsx +++ b/packages/web/components/common/MyMenu/index.tsx @@ -7,22 +7,26 @@ import { useOutsideClick, MenuButton, MenuItemProps, - PlacementWithLogical + PlacementWithLogical, + AvatarProps, + BoxProps, + DividerProps } from '@chakra-ui/react'; import MyDivider from '../MyDivider'; import type { IconNameType } from '../Icon/type'; import { useSystem } from '../../../hooks/useSystem'; import Avatar from '../Avatar'; -export type MenuItemType = 'primary' | 'danger'; +export type MenuItemType = 'primary' | 'danger' | 'gray' | 'grayBg'; + +export type MenuSizeType = 'sm' | 'md' | 'xs' | 'mini'; export type Props = { width?: number | string; offset?: [number, number]; Button: React.ReactNode; trigger?: 'hover' | 'click'; - iconSize?: string; - iconRadius?: string; + size?: MenuSizeType; placement?: PlacementWithLogical; menuList: { @@ -39,18 +43,9 @@ export type Props = { }[]; }; -const MyMenu = ({ - width = 'auto', - trigger = 'hover', - offset, - iconSize = '1rem', - Button, - menuList, - iconRadius, - placement = 'bottom-start' -}: Props) => { - const typeMapStyle: Record = { - primary: { +const typeMapStyle: Record = { + primary: { + styles: { _hover: { backgroundColor: 'primary.50', color: 'primary.600' @@ -64,7 +59,44 @@ const MyMenu = ({ color: 'primary.600' } }, - danger: { + iconColor: 'myGray.600' + }, + gray: { + styles: { + _hover: { + backgroundColor: 'myGray.05', + color: 'primary.600' + }, + _focus: { + backgroundColor: 'myGray.05', + color: 'primary.600' + }, + _active: { + backgroundColor: 'myGray.05', + color: 'primary.600' + } + }, + iconColor: 'myGray.400' + }, + grayBg: { + styles: { + _hover: { + backgroundColor: 'myGray.05', + color: 'primary.600' + }, + _focus: { + backgroundColor: 'myGray.05', + color: 'primary.600' + }, + _active: { + backgroundColor: 'myGray.05', + color: 'primary.600' + } + }, + iconColor: 'myGray.600' + }, + danger: { + styles: { color: 'red.600', _hover: { background: 'red.1' @@ -75,9 +107,97 @@ const MyMenu = ({ _active: { background: 'red.1' } + }, + iconColor: 'red.600' + } +}; +const sizeMapStyle: Record< + MenuSizeType, + { + iconStyle: AvatarProps; + labelStyle: BoxProps; + dividerStyle: DividerProps; + menuItemStyle: MenuItemProps; + } +> = { + mini: { + iconStyle: { + w: '14px' + }, + labelStyle: { + fontSize: 'mini' + }, + dividerStyle: { + my: 0.5 + }, + menuItemStyle: { + py: 1.5, + px: 2 } - }; + }, + xs: { + iconStyle: { + w: '14px' + }, + labelStyle: { + fontSize: 'sm' + }, + dividerStyle: { + my: 0.5 + }, + menuItemStyle: { + py: 1.5, + px: 2 + } + }, + sm: { + iconStyle: { + w: '1rem' + }, + labelStyle: { + fontSize: 'sm' + }, + dividerStyle: { + my: 1 + }, + menuItemStyle: { + py: 2, + px: 3, + _notLast: { + mb: 0.5 + } + } + }, + md: { + iconStyle: { + w: '2rem', + borderRadius: '6px' + }, + labelStyle: { + fontSize: 'sm' + }, + dividerStyle: { + my: 1 + }, + menuItemStyle: { + py: 2, + px: 3, + _notLast: { + mb: 0.5 + } + } + } +}; +const MyMenu = ({ + width = 'auto', + trigger = 'hover', + size = 'sm', + offset, + Button, + menuList, + placement = 'bottom-start' +}: Props) => { const { isPc } = useSystem(); const ref = useRef(null); const closeTimer = useRef(); @@ -165,7 +285,7 @@ const MyMenu = ({ return ( {item.label && {item.label}} - {i !== 0 && } + {i !== 0 && } {item.children.map((child, index) => ( {!!child.icon && ( )} {child.label} diff --git a/packages/web/components/common/MySelect/MultipleRowSelect.tsx b/packages/web/components/common/MySelect/MultipleRowSelect.tsx index c8d335b77..545938fb8 100644 --- a/packages/web/components/common/MySelect/MultipleRowSelect.tsx +++ b/packages/web/components/common/MySelect/MultipleRowSelect.tsx @@ -60,7 +60,9 @@ export const MultipleRowSelect = ({ const newValue = [...cloneValue]; if (item.value === selectedValue) { - newValue[index] = undefined; + for (let i = index; i < newValue.length; i++) { + newValue[i] = undefined; + } setCloneValue(newValue); onSelect(newValue); } else { diff --git a/packages/web/components/common/Tabs/FillRowTabs.tsx b/packages/web/components/common/Tabs/FillRowTabs.tsx index b788e4271..7388af742 100644 --- a/packages/web/components/common/Tabs/FillRowTabs.tsx +++ b/packages/web/components/common/Tabs/FillRowTabs.tsx @@ -18,12 +18,13 @@ const FillRowTabs = ({ list, value, onChange, py = '7px', px = '12px', ...props display={'inline-flex'} px={'3px'} py={'3px'} - borderRadius={'md'} + borderRadius={'sm'} borderWidth={'1px'} - borderColor={'borderColor.base'} + borderColor={'myGray.200'} bg={'myGray.50'} gap={'4px'} fontSize={'sm'} + fontWeight={'medium'} {...props} > {list.map((item) => ( @@ -33,7 +34,7 @@ const FillRowTabs = ({ list, value, onChange, py = '7px', px = '12px', ...props alignItems={'center'} justifyContent={'center'} cursor={'pointer'} - borderRadius={'md'} + borderRadius={'xs'} px={px} py={py} userSelect={'none'} @@ -45,10 +46,14 @@ const FillRowTabs = ({ list, value, onChange, py = '7px', px = '12px', ...props color: 'primary.600' } : { + color: 'myGray.500', + _hover: { + color: 'primary.600' + }, onClick: () => onChange(item.value) })} > - {item.icon && } + {item.icon && } {item.label} ))} diff --git a/packages/web/components/common/Textarea/JsonEditor/index.tsx b/packages/web/components/common/Textarea/JsonEditor/index.tsx index feea41284..8a8e3f298 100644 --- a/packages/web/components/common/Textarea/JsonEditor/index.tsx +++ b/packages/web/components/common/Textarea/JsonEditor/index.tsx @@ -224,8 +224,8 @@ const JSONEditor = ({ {resize && ( {placeholder} diff --git a/packages/web/components/common/Textarea/PromptEditor/Editor.tsx b/packages/web/components/common/Textarea/PromptEditor/Editor.tsx index ce85e7d65..a76cc136e 100644 --- a/packages/web/components/common/Textarea/PromptEditor/Editor.tsx +++ b/packages/web/components/common/Textarea/PromptEditor/Editor.tsx @@ -105,8 +105,8 @@ export default function Editor({ left={0} right={0} bottom={0} - py={2} - px={3} + py={3} + px={3.5} pointerEvents={'none'} overflow={'hidden'} > diff --git a/packages/web/components/common/Textarea/PromptEditor/plugins/VariableLabelPlugin/components/VariableLabel.tsx b/packages/web/components/common/Textarea/PromptEditor/plugins/VariableLabelPlugin/components/VariableLabel.tsx index 2190c65e0..d8afc2749 100644 --- a/packages/web/components/common/Textarea/PromptEditor/plugins/VariableLabelPlugin/components/VariableLabel.tsx +++ b/packages/web/components/common/Textarea/PromptEditor/plugins/VariableLabelPlugin/components/VariableLabel.tsx @@ -1,5 +1,5 @@ import { ChevronRightIcon } from '@chakra-ui/icons'; -import { Box } from '@chakra-ui/react'; +import { Box, Flex } from '@chakra-ui/react'; import { useTranslation } from 'next-i18next'; import Avatar from '../../../../../../../components/common/Avatar'; @@ -28,7 +28,7 @@ export default function VariableLabel({ color={parentLabel !== 'undefined' ? 'myGray.900' : 'red.600'} > {parentLabel !== 'undefined' ? ( - + {parentLabel} - + {childLabel} - + ) : ( <> {t('common:invalid_variable')} diff --git a/packages/web/components/common/Textarea/PromptEditor/plugins/VariableLabelPlugin/index.tsx b/packages/web/components/common/Textarea/PromptEditor/plugins/VariableLabelPlugin/index.tsx index c54a8093c..4c14b8430 100644 --- a/packages/web/components/common/Textarea/PromptEditor/plugins/VariableLabelPlugin/index.tsx +++ b/packages/web/components/common/Textarea/PromptEditor/plugins/VariableLabelPlugin/index.tsx @@ -6,7 +6,7 @@ import { TextNode } from 'lexical'; import { getHashtagRegexString } from './utils'; import { mergeRegister } from '@lexical/utils'; import { registerLexicalTextEntity } from '../../utils'; -import { useTranslation } from 'react-i18next'; +import { useTranslation } from 'next-i18next'; const REGEX = new RegExp(getHashtagRegexString(), 'i'); diff --git a/packages/web/components/core/workflow/NodeInputSelect.tsx b/packages/web/components/core/workflow/NodeInputSelect.tsx index ca170e8f5..3834dab2a 100644 --- a/packages/web/components/core/workflow/NodeInputSelect.tsx +++ b/packages/web/components/core/workflow/NodeInputSelect.tsx @@ -1,13 +1,12 @@ import React, { useMemo, useRef } from 'react'; -import MyMenu from '../../common/MyMenu'; +import MyMenu, { MenuItemType } from '../../common/MyMenu'; import { FlowNodeInputMap, FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; -import { Box, Button, useTheme } from '@chakra-ui/react'; +import { Button, useTheme } from '@chakra-ui/react'; import MyIcon from '../../common/Icon'; import { useTranslation } from 'next-i18next'; -import { useConfirm } from '../../../hooks/useConfirm'; const NodeInputSelect = ({ renderTypeList, @@ -19,9 +18,6 @@ const NodeInputSelect = ({ onChange: (e: string) => void; }) => { const { t } = useTranslation(); - const { openConfirm, ConfirmModal } = useConfirm({ - title: t('common:core.workflow.Change input type tip') - }); const renderType = renderTypeList[renderTypeIndex]; const theme = useTheme(); @@ -136,7 +132,22 @@ const NodeInputSelect = ({ ); const filterMenuList = useMemo( - () => renderList.filter((item) => renderTypeList.includes(item.renderType)), + () => + renderList + .filter((item) => renderTypeList.includes(item.renderType)) + .map((item) => ({ + ...item, + type: 'gray' as MenuItemType, + menuItemStyles: { + fontWeight: 'medium', + minH: 7, + h: 7, + px: 1, + py: 0, + mb: 0, + borderRadius: 'xs' + } + })), [renderTypeList, renderList] ); const renderTypeData = useMemo( @@ -148,24 +159,37 @@ const NodeInputSelect = ({ } - rightIcon={} + rightIcon={ + + } variant={'grayBase'} border={theme.borders.base} borderColor={'myGray.200'} borderRadius={'sm'} - px={'10px'} - py={'6px'} + px={'8px'} fontSize={'mini'} color={'myGray.600'} - h={'28px'} bg={'myGray.100'} + minH={'28px'} + h={'28px'} > - {renderTypeData.title} + {renderTypeData.title} } menuList={[{ children: filterMenuList }]} diff --git a/packages/web/hooks/useI18n.ts b/packages/web/hooks/useI18n.ts index b0d6b619c..09d83027c 100644 --- a/packages/web/hooks/useI18n.ts +++ b/packages/web/hooks/useI18n.ts @@ -1,5 +1,6 @@ import Cookies, { CookieAttributes } from 'js-cookie'; import { useTranslation } from 'next-i18next'; +import { LangEnum } from '../../../projects/app/src/web/common/utils/i18n'; const setCookie = (key: string, value: string, options?: CookieAttributes) => { Cookies.set(key, value, options); @@ -13,11 +14,13 @@ const LANG_KEY = 'NEXT_LOCALE'; export const useI18nLng = () => { const { i18n } = useTranslation(); const languageMap: Record = { - zh: 'zh', - 'zh-CN': 'zh', - 'zh-Hans': 'zh', - en: 'en', - 'en-US': 'en' + zh: LangEnum.zh_CN, + 'zh-CN': LangEnum.zh_CN, + 'zh-Hans': LangEnum.zh_CN, + 'zh-HK': LangEnum.zh_CN, + 'zh-TW': LangEnum.zh_TW, + en: LangEnum.en, + 'en-US': LangEnum.en }; const onChangeLng = (lng: string) => { diff --git a/packages/web/hooks/useScrollPagination.tsx b/packages/web/hooks/useScrollPagination.tsx index 46bc20640..83a5ad11b 100644 --- a/packages/web/hooks/useScrollPagination.tsx +++ b/packages/web/hooks/useScrollPagination.tsx @@ -188,7 +188,8 @@ export function useScrollPagination< pageSize = 10, params = {}, - EmptyTip + EmptyTip, + showErrorToast = true }: { refreshDeps?: any[]; scrollLoadType?: 'top' | 'bottom'; @@ -196,6 +197,7 @@ export function useScrollPagination< pageSize?: number; params?: Record; EmptyTip?: React.JSX.Element; + showErrorToast?: boolean; } ) { const { t } = useTranslation(); @@ -249,10 +251,12 @@ export function useScrollPagination< setData((prevData) => (offset === 0 ? res.list : [...prevData, ...res.list])); } } catch (error: any) { - toast({ - title: getErrText(error, t('common:core.chat.error.data_error')), - status: 'error' - }); + if (showErrorToast) { + toast({ + title: getErrText(error, t('common:core.chat.error.data_error')), + status: 'error' + }); + } console.log(error); } diff --git a/packages/web/hooks/useToast.ts b/packages/web/hooks/useToast.ts index 4cf088983..63a797938 100644 --- a/packages/web/hooks/useToast.ts +++ b/packages/web/hooks/useToast.ts @@ -1,8 +1,10 @@ import { useToast as uToast, UseToastOptions } from '@chakra-ui/react'; import { CSSProperties, useCallback } from 'react'; +import { useTranslation } from 'next-i18next'; export const useToast = (props?: UseToastOptions & { containerStyle?: CSSProperties }) => { const { containerStyle, ...toastProps } = props || {}; + const { t } = useTranslation(); const toast = uToast({ position: 'top', @@ -17,7 +19,11 @@ export const useToast = (props?: UseToastOptions & { containerStyle?: CSSPropert const myToast = useCallback( (options?: UseToastOptions) => { if (options?.title || options?.description) { - toast(options); + toast({ + ...(options.title && { title: t(options.title as any) }), + ...(options.description && { description: t(options.description as any) }), + ...options + }); } }, [props] diff --git a/packages/web/i18n/en/app.json b/packages/web/i18n/en/app.json index b8bdb7b98..713eedccb 100644 --- a/packages/web/i18n/en/app.json +++ b/packages/web/i18n/en/app.json @@ -1,5 +1,5 @@ { - "Role_setting": "Role setting", + "Role_setting": "Permission", "Run": "Execute", "Team Tags Set": "Team tags", "Team_Tags": "Team tags", @@ -14,6 +14,8 @@ "app.version_past": "Previously Published", "app.version_publish_tips": "This version will be saved to the team cloud, synchronized with the entire team, and update the app version on all release channels.", "app_detail": "Application Details", + "auto_execute": "Automatic execution", + "auto_execute_default_prompt_placeholder": "Default questions sent when executing automatically", "chat_debug": "Chat Preview", "chat_logs": "Conversation Logs", "chat_logs_tips": "Logs will record the online, shared, and API (requires chatId) conversation records of this app.", @@ -36,10 +38,10 @@ "document_quote_tip": "Usually used to accept user-uploaded document content (requires document parsing), and can also be used to reference other string data.", "document_upload": "Document Upload", "edit_app": "Edit Application", - "edit_info": "Edit Information", + "edit_info": "Edit", "execute_time": "Execution Time", "export_config_successful": "Configuration copied, some sensitive information automatically filtered. Please check for any remaining sensitive data.", - "export_configs": "Export Configurations", + "export_configs": "Export", "feedback_count": "User Feedback", "file_quote_link": "Files", "file_recover": "File will overwrite current content", @@ -50,7 +52,7 @@ "go_to_run": "Go to Execution", "image_upload": "Image Upload", "image_upload_tip": "How to activate model image recognition capabilities", - "import_configs": "Import Configurations", + "import_configs": "Import", "import_configs_failed": "Import configuration failed, please ensure the configuration is correct!", "import_configs_success": "Import Successful", "initial_form": "initial state", @@ -77,6 +79,7 @@ "move.hint": "After moving, the selected application/folder will inherit the permission settings of the new folder, and the original permission settings will become invalid.", "move_app": "Move Application", "not_json_file": "Please select a JSON file", + "open_auto_execute": "Enable automatic execution", "open_vision_function_tip": "Models with icon switches have image recognition capabilities. \nAfter being turned on, the model will parse the pictures in the file link and automatically parse the pictures in the user's question (user question ≤ 500 words).", "or_drag_JSON": "or drag in JSON file", "paste_config": "Paste Configuration", diff --git a/packages/web/i18n/en/chat.json b/packages/web/i18n/en/chat.json index 2f48e8371..5d5345485 100644 --- a/packages/web/i18n/en/chat.json +++ b/packages/web/i18n/en/chat.json @@ -4,6 +4,7 @@ "LLM_model_response_empty": "The model flow response is empty, please check whether the model flow output is normal.", "chat_history": "Conversation History", "chat_input_guide_lexicon_is_empty": "Lexicon not configured yet", + "chat_test_app": "Debug-{{name}}", "citations": "{{num}} References", "click_contextual_preview": "Click to see contextual preview", "config_input_guide": "Set Up Input Guide", diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index 481c17aae..c594859a4 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -268,9 +268,11 @@ "core.app.Api request": "API Request", "core.app.Api request desc": "Integrate into existing systems through API, or WeChat Work, Feishu, etc.", "core.app.App intro": "App Introduction", + "core.app.Auto execute": "Auto execute", "core.app.Chat Variable": "Chat Variable", "core.app.Config schedule plan": "Configure Scheduled Execution", "core.app.Config whisper": "Configure Voice Input", + "core.app.Config_auto_execute": "Click to configure automatic execution rules", "core.app.Interval timer config": "Scheduled Execution Configuration", "core.app.Interval timer run": "Scheduled Execution", "core.app.Interval timer tip": "Can Execute App on Schedule", @@ -428,7 +430,7 @@ "core.chat.logs.online": "Online Use", "core.chat.logs.share": "External Link Call", "core.chat.logs.team": "Team Space Chat", - "core.chat.logs.test": "Test", + "core.chat.logs.test": "Online debugging", "core.chat.logs.wecom": "WeChat Work", "core.chat.markdown.Edit Question": "Edit Question", "core.chat.markdown.Quick Question": "Click to Ask Immediately", @@ -732,11 +734,11 @@ "core.module.template.AI function": "AI Capability", "core.module.template.AI response switch tip": "If you want the current node not to output content, you can turn off this switch. The content output by AI will not be displayed to the user, and you can manually use 'AI Response Content' for special processing.", "core.module.template.AI support tool tip": "Models that support function calls can better use tool calls.", - "core.module.template.Basic Node": "Basic Function", + "core.module.template.Basic Node": "Basic", "core.module.template.Query extension": "Question Optimization", - "core.module.template.System Plugin": "System Plugin", + "core.module.template.System Plugin": "System", "core.module.template.System input module": "System Input", - "core.module.template.Team app": "Team App", + "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", diff --git a/packages/web/i18n/zh/app.json b/packages/web/i18n/zh-CN/app.json similarity index 96% rename from packages/web/i18n/zh/app.json rename to packages/web/i18n/zh-CN/app.json index a9d178419..ce3341b94 100644 --- a/packages/web/i18n/zh/app.json +++ b/packages/web/i18n/zh-CN/app.json @@ -14,6 +14,9 @@ "app.version_past": "发布过", "app.version_publish_tips": "该版本将被保存至团队云端,同步给整个团队,同时更新所有发布渠道的应用版本", "app_detail": "应用详情", + "auto_execute": "自动执行", + "auto_execute_default_prompt_placeholder": "自动执行时,发送的默认问题", + "auto_execute_tip": "开启后,用户进入对话界面将自动触发工作流。执行顺序:1、对话开场白;2、全局变量;3、自动执行。", "chat_debug": "调试预览", "chat_logs": "对话日志", "chat_logs_tips": "日志会记录该应用的在线、分享和 API(需填写 chatId)对话记录", @@ -77,6 +80,7 @@ "move.hint": "移动后,所选应用/文件夹将继承新文件夹的权限设置,原先的权限设置失效。", "move_app": "移动应用", "not_json_file": "请选择JSON文件", + "open_auto_execute": "启用自动执行", "open_vision_function_tip": "有图示开关的模型即拥有图片识别能力。若开启,模型会解析文件链接里的图片,并自动解析用户问题中的图片(用户问题≤500字时生效)。", "or_drag_JSON": "或拖入JSON文件", "paste_config": "粘贴配置", diff --git a/packages/web/i18n/zh/chat.json b/packages/web/i18n/zh-CN/chat.json similarity index 98% rename from packages/web/i18n/zh/chat.json rename to packages/web/i18n/zh-CN/chat.json index a82ce845f..bf3d21e0e 100644 --- a/packages/web/i18n/zh/chat.json +++ b/packages/web/i18n/zh-CN/chat.json @@ -4,6 +4,7 @@ "LLM_model_response_empty": "模型流响应为空,请检查模型流输出是否正常", "chat_history": "聊天记录", "chat_input_guide_lexicon_is_empty": "还没有配置词库", + "chat_test_app": "调试-{{name}}", "citations": "{{num}}条引用", "click_contextual_preview": "点击查看上下文预览", "config_input_guide": "配置输入引导", diff --git a/packages/web/i18n/zh/common.json b/packages/web/i18n/zh-CN/common.json similarity index 99% rename from packages/web/i18n/zh/common.json rename to packages/web/i18n/zh-CN/common.json index 98f933f88..47900073e 100644 --- a/packages/web/i18n/zh/common.json +++ b/packages/web/i18n/zh-CN/common.json @@ -267,9 +267,11 @@ "core.app.Api request": "API 访问", "core.app.Api request desc": "通过 API 接入到已有系统中,或企微、飞书等", "core.app.App intro": "应用介绍", + "core.app.Auto execute": "自动执行", "core.app.Chat Variable": "对话框变量", "core.app.Config schedule plan": "配置定时执行", "core.app.Config whisper": "配置语音输入", + "core.app.Config_auto_execute": "点击配置自动执行规则", "core.app.Interval timer config": "定时执行配置", "core.app.Interval timer run": "定时执行", "core.app.Interval timer tip": "可定时执行应用", @@ -427,7 +429,7 @@ "core.chat.logs.online": "在线使用", "core.chat.logs.share": "外部链接调用", "core.chat.logs.team": "团队空间对话", - "core.chat.logs.test": "测试", + "core.chat.logs.test": "在线调试", "core.chat.logs.wecom": "企业微信", "core.chat.markdown.Edit Question": "编辑问题", "core.chat.markdown.Quick Question": "点我立即提问", diff --git a/packages/web/i18n/zh/dataset.json b/packages/web/i18n/zh-CN/dataset.json similarity index 100% rename from packages/web/i18n/zh/dataset.json rename to packages/web/i18n/zh-CN/dataset.json diff --git a/packages/web/i18n/zh/file.json b/packages/web/i18n/zh-CN/file.json similarity index 100% rename from packages/web/i18n/zh/file.json rename to packages/web/i18n/zh-CN/file.json diff --git a/packages/web/i18n/zh/login.json b/packages/web/i18n/zh-CN/login.json similarity index 100% rename from packages/web/i18n/zh/login.json rename to packages/web/i18n/zh-CN/login.json diff --git a/packages/web/i18n/zh/publish.json b/packages/web/i18n/zh-CN/publish.json similarity index 100% rename from packages/web/i18n/zh/publish.json rename to packages/web/i18n/zh-CN/publish.json diff --git a/packages/web/i18n/zh/user.json b/packages/web/i18n/zh-CN/user.json similarity index 100% rename from packages/web/i18n/zh/user.json rename to packages/web/i18n/zh-CN/user.json diff --git a/packages/web/i18n/zh/workflow.json b/packages/web/i18n/zh-CN/workflow.json similarity index 100% rename from packages/web/i18n/zh/workflow.json rename to packages/web/i18n/zh-CN/workflow.json diff --git a/packages/web/i18n/zh_TW/app.json b/packages/web/i18n/zh-TW/app.json similarity index 100% rename from packages/web/i18n/zh_TW/app.json rename to packages/web/i18n/zh-TW/app.json diff --git a/packages/web/i18n/zh_TW/chat.json b/packages/web/i18n/zh-TW/chat.json similarity index 100% rename from packages/web/i18n/zh_TW/chat.json rename to packages/web/i18n/zh-TW/chat.json diff --git a/packages/web/i18n/zh_TW/common.json b/packages/web/i18n/zh-TW/common.json similarity index 100% rename from packages/web/i18n/zh_TW/common.json rename to packages/web/i18n/zh-TW/common.json diff --git a/packages/web/i18n/zh_TW/dataset.json b/packages/web/i18n/zh-TW/dataset.json similarity index 100% rename from packages/web/i18n/zh_TW/dataset.json rename to packages/web/i18n/zh-TW/dataset.json diff --git a/packages/web/i18n/zh_TW/file.json b/packages/web/i18n/zh-TW/file.json similarity index 100% rename from packages/web/i18n/zh_TW/file.json rename to packages/web/i18n/zh-TW/file.json diff --git a/packages/web/i18n/zh_TW/login.json b/packages/web/i18n/zh-TW/login.json similarity index 100% rename from packages/web/i18n/zh_TW/login.json rename to packages/web/i18n/zh-TW/login.json diff --git a/packages/web/i18n/zh_TW/publish.json b/packages/web/i18n/zh-TW/publish.json similarity index 100% rename from packages/web/i18n/zh_TW/publish.json rename to packages/web/i18n/zh-TW/publish.json diff --git a/packages/web/i18n/zh_TW/user.json b/packages/web/i18n/zh-TW/user.json similarity index 100% rename from packages/web/i18n/zh_TW/user.json rename to packages/web/i18n/zh-TW/user.json diff --git a/packages/web/i18n/zh_TW/workflow.json b/packages/web/i18n/zh-TW/workflow.json similarity index 100% rename from packages/web/i18n/zh_TW/workflow.json rename to packages/web/i18n/zh-TW/workflow.json diff --git a/packages/web/styles/theme.ts b/packages/web/styles/theme.ts index 0e6258c02..c8bf06d7b 100644 --- a/packages/web/styles/theme.ts +++ b/packages/web/styles/theme.ts @@ -221,7 +221,6 @@ const Button = defineStyleConfig({ boxShadow: '0px 0px 1px 0px rgba(19, 51, 107, 0.08), 0px 1px 2px 0px rgba(19, 51, 107, 0.05)', _hover: { color: 'red.600', - background: 'red.1', borderColor: 'red.300' }, _active: { @@ -251,6 +250,16 @@ const Button = defineStyleConfig({ color: 'red.600' } }, + grayGhost: { + color: 'myGray.500', + fontWeight: '500', + p: 0, + bg: 'transparent', + transition: 'background 0.1s', + _hover: { + bg: 'myGray.05' + } + }, transparentBase: { color: 'myGray.800', fontWeight: '500', @@ -570,6 +579,43 @@ const Table = tableMultiStyle({ } }) }, + variants: { + workflow: { + table: { + bg: 'white' + }, + thead: { + tr: { + th: { + p: '0', + px: 4, + bg: 'myGray.50', + borderRadius: 'none !important', + borderBottom: 'none', + height: '32px', + fontSize: 'mini', + fontWeight: 'medium' + } + } + }, + tbody: { + tr: { + td: { + p: '0', + px: 4, + fontSize: 'xs', + borderBottom: 'base', + height: '40px' + }, + '&:last-child': { + td: { + borderBottom: 'none' + } + } + } + } + } + }, defaultProps: { size: 'md' } diff --git a/packages/web/types/i18next.d.ts b/packages/web/types/i18next.d.ts index 20a2fcfb3..145804a53 100644 --- a/packages/web/types/i18next.d.ts +++ b/packages/web/types/i18next.d.ts @@ -1,13 +1,13 @@ import 'i18next'; -import common from '../i18n/zh/common.json'; -import dataset from '../i18n/zh/dataset.json'; -import app from '../i18n/zh/app.json'; -import file from '../i18n/zh/file.json'; -import publish from '../i18n/zh/publish.json'; -import workflow from '../i18n/zh/workflow.json'; -import user from '../i18n/zh/user.json'; -import chat from '../i18n/zh/chat.json'; -import login from '../i18n/zh/login.json'; +import common from '../i18n/zh-CN/common.json'; +import dataset from '../i18n/zh-CN/dataset.json'; +import app from '../i18n/zh-CN/app.json'; +import file from '../i18n/zh-CN/file.json'; +import publish from '../i18n/zh-CN/publish.json'; +import workflow from '../i18n/zh-CN/workflow.json'; +import user from '../i18n/zh-CN/user.json'; +import chat from '../i18n/zh-CN/chat.json'; +import login from '../i18n/zh-CN/login.json'; export interface I18nNamespaces { common: typeof common; diff --git a/projects/app/next-i18next.config.js b/projects/app/next-i18next.config.js index dce1cf6e5..d16520ce4 100644 --- a/projects/app/next-i18next.config.js +++ b/projects/app/next-i18next.config.js @@ -5,8 +5,8 @@ module.exports = { i18n: { - defaultLocale: 'zh', - locales: ['en', 'zh', 'zh_TW'], + defaultLocale: 'zh-CN', + locales: ['en', 'zh-CN', 'zh-TW'], localeDetection: false }, localePath: diff --git a/projects/app/next.config.js b/projects/app/next.config.js index 73a53cd4e..deeb20d93 100644 --- a/projects/app/next.config.js +++ b/projects/app/next.config.js @@ -85,7 +85,8 @@ const nextConfig = { experimental: { // 优化 Server Components 的构建和运行,避免不必要的客户端打包。 serverComponentsExternalPackages: ['mongoose', 'pg', '@node-rs/jieba', 'duck-duck-scrape'], - outputFileTracingRoot: path.join(__dirname, '../../') + outputFileTracingRoot: path.join(__dirname, '../../'), + instrumentationHook: true } }; diff --git a/projects/app/package.json b/projects/app/package.json index 5534e5408..5d378119a 100644 --- a/projects/app/package.json +++ b/projects/app/package.json @@ -1,6 +1,6 @@ { "name": "app", - "version": "4.8.13", + "version": "4.8.14", "private": false, "scripts": { "dev": "next dev", diff --git a/projects/app/public/imgs/app/autoExec-icon.svg b/projects/app/public/imgs/app/autoExec-icon.svg new file mode 100644 index 000000000..ab7fdfbe9 --- /dev/null +++ b/projects/app/public/imgs/app/autoExec-icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/projects/app/public/imgs/app/autoExec.svg b/projects/app/public/imgs/app/autoExec.svg new file mode 100644 index 000000000..9e9230f11 --- /dev/null +++ b/projects/app/public/imgs/app/autoExec.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/app/src/components/Layout/navbar.tsx b/projects/app/src/components/Layout/navbar.tsx index f2785673f..86c355895 100644 --- a/projects/app/src/components/Layout/navbar.tsx +++ b/projects/app/src/components/Layout/navbar.tsx @@ -2,7 +2,7 @@ import React, { useMemo } from 'react'; import { Box, BoxProps, Flex, Link, LinkProps } from '@chakra-ui/react'; import { useRouter } from 'next/router'; import { useUserStore } from '@/web/support/user/useUserStore'; -import { useChatStore } from '@/web/core/chat/context/storeChat'; +import { useChatStore } from '@/web/core/chat/context/useChatStore'; import { HUMAN_ICON } from '@fastgpt/global/common/system/constants'; import NextLink from 'next/link'; import Badge from '../Badge'; @@ -23,14 +23,14 @@ const Navbar = ({ unread }: { unread: number }) => { const router = useRouter(); const { userInfo } = useUserStore(); const { gitStar, feConfigs } = useSystemStore(); - const { lastChatAppId, lastChatId } = useChatStore(); + const { lastChatAppId } = useChatStore(); const navbarList = useMemo( () => [ { label: t('common:navbar.Chat'), icon: 'core/chat/chatLight', activeIcon: 'core/chat/chatFill', - link: `/chat?appId=${lastChatAppId}&chatId=${lastChatId}`, + link: `/chat?appId=${lastChatAppId}`, activeLink: ['/chat'] }, { @@ -55,7 +55,7 @@ const Navbar = ({ unread }: { unread: number }) => { activeLink: ['/account'] } ], - [lastChatAppId, lastChatId, t] + [lastChatAppId, t] ); const itemStyles: BoxProps & LinkProps = { @@ -84,6 +84,7 @@ const Navbar = ({ unread }: { unread: number }) => { h={'100%'} w={'100%'} userSelect={'none'} + pb={2} > {/* logo */} { href={`/account?currentTab=inform`} mb={0} color={'myGray.500'} + height={'48px'} > @@ -171,6 +173,7 @@ const Navbar = ({ unread }: { unread: number }) => { target="_blank" mb={0} color={'myGray.500'} + height={'48px'} > @@ -186,6 +189,7 @@ const Navbar = ({ unread }: { unread: number }) => { {...hoverStyle} mt={0} color={'myGray.500'} + height={'48px'} > diff --git a/projects/app/src/components/Layout/navbarPhone.tsx b/projects/app/src/components/Layout/navbarPhone.tsx index 06fc542e1..19214b2a3 100644 --- a/projects/app/src/components/Layout/navbarPhone.tsx +++ b/projects/app/src/components/Layout/navbarPhone.tsx @@ -1,7 +1,7 @@ import React, { useMemo } from 'react'; import { useRouter } from 'next/router'; import { Flex, Box } from '@chakra-ui/react'; -import { useChatStore } from '@/web/core/chat/context/storeChat'; +import { useChatStore } from '@/web/core/chat/context/useChatStore'; import { useTranslation } from 'next-i18next'; import Badge from '../Badge'; import MyIcon from '@fastgpt/web/components/common/Icon'; @@ -9,14 +9,14 @@ import MyIcon from '@fastgpt/web/components/common/Icon'; const NavbarPhone = ({ unread }: { unread: number }) => { const router = useRouter(); const { t } = useTranslation(); - const { lastChatAppId, lastChatId } = useChatStore(); + const { lastChatAppId } = useChatStore(); const navbarList = useMemo( () => [ { label: t('common:navbar.Chat'), icon: 'core/chat/chatLight', activeIcon: 'core/chat/chatFill', - link: `/chat?appId=${lastChatAppId}&chatId=${lastChatId}`, + link: `/chat?appId=${lastChatAppId}`, activeLink: ['/chat'], unread: 0 }, @@ -45,7 +45,7 @@ const NavbarPhone = ({ unread }: { unread: number }) => { unread } ], - [t, lastChatAppId, lastChatId, unread] + [t, lastChatAppId, unread] ); return ( diff --git a/projects/app/src/components/Select/I18nLngSelector.tsx b/projects/app/src/components/Select/I18nLngSelector.tsx index 18e5f17cc..7a74c0e15 100644 --- a/projects/app/src/components/Select/I18nLngSelector.tsx +++ b/projects/app/src/components/Select/I18nLngSelector.tsx @@ -1,5 +1,5 @@ import { langMap } from '@/web/common/utils/i18n'; -import { Avatar, Box, Flex } from '@chakra-ui/react'; +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'; @@ -14,7 +14,7 @@ const I18nLngSelector = () => { return Object.entries(langMap).map(([key, lang]) => ({ label: ( - + {lang.label} ), diff --git a/projects/app/src/components/core/app/AutoExecConfig.tsx b/projects/app/src/components/core/app/AutoExecConfig.tsx new file mode 100644 index 000000000..cfa2a7df0 --- /dev/null +++ b/projects/app/src/components/core/app/AutoExecConfig.tsx @@ -0,0 +1,87 @@ +import { Box, Button, Flex, ModalBody, Switch, Textarea, useDisclosure } from '@chakra-ui/react'; +import { defaultAutoExecuteConfig } from '@fastgpt/global/core/app/constants'; +import { AppAutoExecuteConfigType } from '@fastgpt/global/core/app/type'; +import MyIcon from '@fastgpt/web/components/common/Icon'; +import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; +import { useTranslation } from 'react-i18next'; +import ChatFunctionTip from './Tip'; +import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; +import MyModal from '@fastgpt/web/components/common/MyModal'; + +const AutoExecConfig = ({ + value = defaultAutoExecuteConfig, + onChange +}: { + value?: AppAutoExecuteConfigType; + onChange: (e: AppAutoExecuteConfigType) => void; +}) => { + const { t } = useTranslation(); + const { isOpen, onOpen, onClose } = useDisclosure(); + const isOpenAutoExec = value.open; + const defaultPrompt = value.defaultPrompt; + + const formLabel = isOpenAutoExec + ? t('common:core.app.whisper.Open') + : t('common:core.app.whisper.Close'); + + return ( + + + {t('app:auto_execute')} + + + + + + + + + {t('app:open_auto_execute')} + { + onChange({ + ...value, + open: e.target.checked + }); + }} + /> + + {isOpenAutoExec && ( + + {t('common:core.app.schedule.Default prompt')} +