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 | 50 +- .../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 | 83 ++-- .../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 | 104 +++-- .../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 | 200 +++----- projects/app/src/pages/chat/share.tsx | 296 +++++------- projects/app/src/pages/chat/team.tsx | 249 ++++------ .../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 | 203 +++++--- .../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 | 191 ++++---- .../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, 3816 insertions(+), 2722 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 2508d1ce8201..c674d0733827 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 98eb146b04f3..25082023a9d3 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 5c56cd19bc99..40928c5c2132 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 dfe8b21c6dfe..55f1747ca137 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 7694e604a3cd..940aece50568 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 f87d4d92888a..a245af7ca990 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 e6600f23c972..d9bc42abb496 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 8f6cf209a73b..916720591843 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 02a85fe1cbdc..0362efe166ea 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 3d16c2653467..72be2e38869a 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 e8900081ce71..4b7eba63c3e3 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 ada60a1e16b5..f215d9ef55d6 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 578a81b3ba3b..d93c7ada3a4f 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 d4a5a4a29ee0..3e082c2357b7 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 2d0d915f677c..a5693e39b403 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 876060d5a57e..460d8ae79123 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 3b05d0729012..c30f5cc511df 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 4b069cb8caaf..71bb2ad33e61 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 e549ef601b95..237ae49c9c6e 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 1b78e1e702fb..4004a8a1cc0c 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 a19a279a1f6f..efd667464188 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 5450b4c1bc9e..00df3dc05dbf 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 d09576bf4b60..fb01e709c717 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 6084fb9940ca..daab1c0aa866 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 6611177529fe..0dc11e056ee0 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 fbea9acab103..80bc641db353 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 c652246ebfc1..59cfe7afbdda 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, - tokens, - modelType: ModelTypeEnum.llm - }); + if (!answerText) { + return Promise.reject(getEmptyResponseTip()); + } - return { - answerText, - [DispatchNodeResponseKeyEnum.nodeResponse]: { + 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, + 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 cbedf4ea81b5..307edd3505f3 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 3ed92a6e9d57..3a183988b89f 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 51e470a94041..4323a808c7a1 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 8a54c509f9ef..11d639e2650c 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 743759a5b931..c68f07d1bef0 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 551437135c35..7e9c4f94d115 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 e6ce6c7973e9..22b79d68e7de 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 d8ffa5102ffc..ad8e113998fc 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 1015f699f3df..d51cf1aa167a 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 000000000000..38cd50a39174 --- /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 da1bf101cc52..e6d3d82bbc47 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 5332e60860e5..d43d66d291cf 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 000000000000..1c41452e0b94 --- /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 7e23ef30fa84..38465aaabff3 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 000000000000..287169b06163 --- /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 000000000000..bca309065992 --- /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 b9f7a6a0e39f..9eaed1c1f98b 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 c051283562aa..72a7db646234 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 c8d335b77941..545938fb8c4d 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 b788e4271294..7388af742820 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 feea41284080..8a8e3f298317 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 ce85e7d651c9..a76cc136e006 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 2190c65e03fe..d8afc2749699 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 c54a8093cfc1..4c14b8430b7e 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 ca170e8f527b..3834dab2a019 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 b0d6b619cd8d..09d83027c54f 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 46bc20640345..83a5ad11b350 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 4cf088983201..63a797938ea3 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 b8bdb7b98e14..713eedccbe59 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 2f48e83711ff..5d5345485a13 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 481c17aae42b..c594859a43b0 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 a9d178419149..ce3341b945f0 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 a82ce845f2cb..bf3d21e0e373 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 98f933f88aae..47900073e3b0 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 0e6258c02697..c8bf06d7b091 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 20a2fcfb3b9a..145804a530f4 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 dce1cf6e5d9c..d16520ce46f5 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 73a53cd4e59d..deeb20d9390d 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 5534e540889f..5d378119a5d6 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 000000000000..ab7fdfbe9814 --- /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 000000000000..9e9230f11d1f --- /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 f2785673fd6c..86c35589507e 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 06fc542e1d03..19214b2a374d 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 18e5f17ccfe0..7a74c0e15884 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 000000000000..cfa2a7df002e --- /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')} +