@lobehub/chat 1.11.9 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yml +2 -1
- package/.github/workflows/test.yml +2 -1
- package/CHANGELOG.md +25 -0
- package/Dockerfile.database +2 -0
- package/docs/self-hosting/advanced/knowledge-base.zh-CN.mdx +65 -0
- package/locales/ar/chat.json +13 -3
- package/locales/ar/components.json +2 -0
- package/locales/bg-BG/chat.json +13 -3
- package/locales/bg-BG/components.json +2 -0
- package/locales/de-DE/chat.json +13 -3
- package/locales/de-DE/components.json +2 -0
- package/locales/en-US/chat.json +13 -3
- package/locales/en-US/components.json +2 -0
- package/locales/es-ES/chat.json +13 -3
- package/locales/es-ES/components.json +2 -0
- package/locales/fr-FR/chat.json +13 -3
- package/locales/fr-FR/components.json +2 -0
- package/locales/it-IT/chat.json +13 -3
- package/locales/it-IT/components.json +2 -0
- package/locales/ja-JP/chat.json +13 -3
- package/locales/ja-JP/components.json +2 -0
- package/locales/ko-KR/chat.json +13 -3
- package/locales/ko-KR/components.json +2 -0
- package/locales/nl-NL/chat.json +13 -3
- package/locales/nl-NL/components.json +2 -0
- package/locales/pl-PL/chat.json +13 -3
- package/locales/pl-PL/components.json +2 -0
- package/locales/pt-BR/chat.json +13 -3
- package/locales/pt-BR/components.json +2 -0
- package/locales/ru-RU/chat.json +13 -3
- package/locales/ru-RU/components.json +2 -0
- package/locales/tr-TR/chat.json +13 -3
- package/locales/tr-TR/components.json +2 -0
- package/locales/vi-VN/chat.json +13 -3
- package/locales/vi-VN/components.json +2 -0
- package/locales/zh-CN/chat.json +13 -3
- package/locales/zh-CN/components.json +2 -0
- package/locales/zh-TW/chat.json +13 -3
- package/locales/zh-TW/components.json +2 -0
- package/package.json +3 -2
- package/scripts/migrateServerDB/docker.cjs +6 -0
- package/scripts/migrateServerDB/errorHint.js +17 -0
- package/scripts/migrateServerDB/index.ts +6 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/Content.tsx +37 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/index.tsx +87 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/style.ts +4 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/utils.ts +28 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileList.tsx +41 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/index.tsx +40 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/SendMore.tsx +1 -1
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/index.tsx +7 -22
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/TextArea.tsx +1 -1
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/index.tsx +2 -4
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/File.tsx +72 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/Image.tsx +74 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/index.tsx +39 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/style.ts +1 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/index.tsx +33 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/InputArea/Container.tsx +41 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/InputArea/index.tsx +154 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Send.tsx +34 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/index.tsx +24 -11
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/components/UploadDetail/UploadStatus.tsx +71 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/components/UploadDetail/index.tsx +49 -0
- package/src/app/(main)/chat/(workspace)/@portal/FilePreview/index.tsx +26 -0
- package/src/app/(main)/chat/(workspace)/@portal/Home/Files/FileList/Item.tsx +53 -0
- package/src/app/(main)/chat/(workspace)/@portal/Home/Files/FileList/index.tsx +50 -0
- package/src/app/(main)/chat/(workspace)/@portal/Home/Files/index.tsx +21 -0
- package/src/app/(main)/chat/(workspace)/@portal/Home/index.tsx +2 -0
- package/src/app/(main)/chat/(workspace)/@portal/router.tsx +4 -0
- package/src/app/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/KnowledgeTag.tsx +41 -0
- package/src/app/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/Tags.tsx +7 -2
- package/src/app/(main)/chat/(workspace)/_layout/Desktop/HotKeys.tsx +1 -1
- package/src/app/(main)/files/(content)/@menu/default.tsx +27 -0
- package/src/app/(main)/files/(content)/@menu/features/FileMenu/index.tsx +97 -0
- package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/EmptyStatus.tsx +53 -0
- package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/Item/Content.tsx +175 -0
- package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/Item/index.tsx +69 -0
- package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/KnowledgeBaseList.tsx +30 -0
- package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/SkeletonList.tsx +57 -0
- package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/index.tsx +54 -0
- package/src/app/(main)/files/(content)/@modal/(.)[id]/FileDetail.tsx +16 -0
- package/src/app/(main)/files/(content)/@modal/(.)[id]/FilePreview.tsx +15 -0
- package/src/app/(main)/files/(content)/@modal/(.)[id]/FullscreenModal.tsx +85 -0
- package/src/app/(main)/files/(content)/@modal/(.)[id]/page.tsx +19 -0
- package/src/app/(main)/files/(content)/@modal/default.tsx +3 -0
- package/src/app/(main)/files/(content)/NotSupportClient.tsx +152 -0
- package/src/app/(main)/files/(content)/_layout/Desktop/index.tsx +28 -0
- package/src/app/(main)/files/(content)/_layout/Mobile.tsx +47 -0
- package/src/app/(main)/files/(content)/_layout/type.ts +7 -0
- package/src/app/(main)/files/(content)/layout.tsx +18 -0
- package/src/app/(main)/files/(content)/page.tsx +14 -0
- package/src/app/(main)/files/[id]/Header.tsx +63 -0
- package/src/app/(main)/files/[id]/page.tsx +44 -0
- package/src/app/(main)/files/features/FileDetail.tsx +93 -0
- package/src/app/(main)/files/hooks/useFileCategory.ts +9 -0
- package/src/app/(main)/files/layout.tsx +12 -0
- package/src/app/(main)/files/loading.tsx +21 -0
- package/src/app/(main)/repos/[id]/@menu/Head/index.tsx +33 -0
- package/src/app/(main)/repos/[id]/@menu/Menu/index.tsx +56 -0
- package/src/app/(main)/repos/[id]/@menu/default.tsx +25 -0
- package/src/app/(main)/repos/[id]/_layout/Desktop/index.tsx +25 -0
- package/src/app/(main)/repos/[id]/_layout/Mobile.tsx +47 -0
- package/src/app/(main)/repos/[id]/_layout/type.ts +6 -0
- package/src/app/(main)/repos/[id]/hooks/useKnowledgeItem.ts +7 -0
- package/src/app/(main)/repos/[id]/layout.tsx +13 -0
- package/src/app/(main)/repos/[id]/page.tsx +18 -0
- package/src/app/(main)/repos/layout.tsx +13 -0
- package/src/app/(main)/repos/page.tsx +5 -0
- package/src/app/trpc/async/[trpc]/route.ts +28 -0
- package/src/chains/abstractChunk.ts +19 -0
- package/src/chains/answerWithContext.ts +34 -0
- package/src/chains/rewriteQuery.ts +22 -0
- package/src/components/DragUpload/index.tsx +6 -99
- package/src/components/DragUpload/useDragUpload.tsx +146 -0
- package/src/components/FeatureList/index.tsx +64 -0
- package/src/components/FileParsingStatus/index.tsx +230 -0
- package/src/components/ImageItem/index.tsx +10 -2
- package/src/components/KnowledgeIcon/index.tsx +28 -0
- package/src/config/app.ts +6 -1
- package/src/config/featureFlags/schema.ts +1 -1
- package/src/const/file.ts +1 -0
- package/src/const/url.ts +1 -0
- package/src/database/client/models/file.ts +8 -2
- package/src/database/server/migrations/0005_pgvector.sql +2 -0
- package/src/database/server/migrations/0006_add_knowledge_base.sql +307 -0
- package/src/database/server/migrations/meta/0005_snapshot.json +2119 -0
- package/src/database/server/migrations/meta/0006_snapshot.json +3006 -0
- package/src/database/server/migrations/meta/_journal.json +14 -0
- package/src/database/server/models/__tests__/_test_template.ts +155 -0
- package/src/database/server/models/__tests__/agent.test.ts +226 -0
- package/src/database/server/models/__tests__/asyncTask.test.ts +176 -0
- package/src/database/server/models/__tests__/chunk.test.ts +336 -0
- package/src/database/server/models/__tests__/file.test.ts +317 -29
- package/src/database/server/models/__tests__/fixtures/embedding.ts +568 -0
- package/src/database/server/models/__tests__/knowledgeBase.test.ts +132 -0
- package/src/database/server/models/__tests__/message.test.ts +7 -4
- package/src/database/server/models/_template.ts +10 -1
- package/src/database/server/models/agent.ts +165 -0
- package/src/database/server/models/asyncTask.ts +96 -0
- package/src/database/server/models/chunk.ts +203 -0
- package/src/database/server/models/embedding.ts +47 -0
- package/src/database/server/models/file.ts +231 -12
- package/src/database/server/models/knowledgeBase.ts +94 -0
- package/src/database/server/models/message.ts +156 -30
- package/src/database/server/models/user.ts +12 -1
- package/src/database/server/schemas/lobechat/agent.ts +93 -0
- package/src/database/server/schemas/lobechat/discover.ts +1 -1
- package/src/database/server/schemas/lobechat/file.ts +118 -1
- package/src/database/server/schemas/lobechat/index.ts +5 -1
- package/src/database/server/schemas/lobechat/message.ts +169 -0
- package/src/database/server/schemas/lobechat/rag.ts +51 -0
- package/src/database/server/schemas/lobechat/relations.ts +68 -48
- package/src/database/server/schemas/lobechat/session.ts +77 -0
- package/src/database/server/schemas/lobechat/topic.ts +32 -0
- package/src/database/server/schemas/lobechat/user.ts +40 -25
- package/src/database/server/utils/idGenerator.ts +1 -0
- package/src/features/ChatInput/ActionBar/Clear.tsx +1 -1
- package/src/features/ChatInput/ActionBar/Knowledge/Dropdown.tsx +160 -0
- package/src/features/ChatInput/ActionBar/Knowledge/ListItem.tsx +52 -0
- package/src/features/ChatInput/ActionBar/Knowledge/index.tsx +54 -0
- package/src/features/ChatInput/ActionBar/Tools/index.tsx +1 -1
- package/src/features/ChatInput/ActionBar/Upload/ClientMode.tsx +52 -0
- package/src/features/ChatInput/ActionBar/Upload/ServerMode.tsx +104 -0
- package/src/features/ChatInput/ActionBar/Upload/index.tsx +8 -0
- package/src/features/ChatInput/ActionBar/config.ts +14 -5
- package/src/features/ChatInput/useSend.ts +16 -7
- package/src/features/Conversation/Messages/Assistant/FileChunks/Item/index.tsx +51 -0
- package/src/features/Conversation/Messages/Assistant/FileChunks/Item/style.ts +38 -0
- package/src/features/Conversation/Messages/Assistant/FileChunks/index.tsx +76 -0
- package/src/features/Conversation/Messages/Assistant/index.tsx +13 -4
- package/src/features/Conversation/Messages/Default.tsx +4 -0
- package/src/features/Conversation/Messages/User/BelowMessage.tsx +78 -0
- package/src/features/Conversation/Messages/User/FileListViewer/Item.tsx +53 -0
- package/src/features/Conversation/Messages/User/FileListViewer/index.tsx +21 -0
- package/src/{components/FileList/FileListViewer.tsx → features/Conversation/Messages/User/ImageFileListViewer.tsx} +10 -2
- package/src/features/Conversation/Messages/{User.tsx → User/index.tsx} +11 -2
- package/src/features/Conversation/Messages/index.ts +8 -3
- package/src/features/Conversation/components/ChatItem/index.tsx +33 -10
- package/src/features/Conversation/components/InboxWelcome/QuestionSuggest.tsx +1 -1
- package/src/features/Conversation/types/index.tsx +1 -0
- package/src/features/FileManager/ChunkDrawer/ChunkList/ChunkItem.tsx +61 -0
- package/src/features/FileManager/ChunkDrawer/ChunkList/index.tsx +42 -0
- package/src/features/FileManager/ChunkDrawer/Content.tsx +38 -0
- package/src/features/FileManager/ChunkDrawer/Loading/index.tsx +16 -0
- package/src/features/FileManager/ChunkDrawer/SimilaritySearchList/Item.tsx +62 -0
- package/src/features/FileManager/ChunkDrawer/SimilaritySearchList/index.tsx +31 -0
- package/src/features/FileManager/ChunkDrawer/index.tsx +48 -0
- package/src/features/FileManager/FileList/EmptyStatus.tsx +153 -0
- package/src/features/FileManager/FileList/FileListItem/ChunkTag.tsx +35 -0
- package/src/features/FileManager/FileList/FileListItem/DropdownMenu.tsx +150 -0
- package/src/features/FileManager/FileList/FileListItem/index.tsx +211 -0
- package/src/features/FileManager/FileList/FileSkeleton.tsx +25 -0
- package/src/features/FileManager/FileList/ToolBar/Config.tsx +28 -0
- package/src/features/FileManager/FileList/ToolBar/MultiSelectActions.tsx +152 -0
- package/src/features/FileManager/FileList/ToolBar/index.tsx +114 -0
- package/src/features/FileManager/FileList/index.tsx +143 -0
- package/src/features/FileManager/FileList/useCheckTaskStatus.ts +27 -0
- package/src/features/FileManager/Header/FilesSearchBar.tsx +41 -0
- package/src/features/FileManager/Header/UploadFileButton.tsx +79 -0
- package/src/features/FileManager/Header/index.tsx +39 -0
- package/src/features/FileManager/UploadDock/Item.tsx +124 -0
- package/src/features/FileManager/UploadDock/index.tsx +183 -0
- package/src/features/FileManager/index.tsx +38 -0
- package/src/features/FileSidePanel/index.tsx +79 -0
- package/src/features/FileViewer/NotSupport/index.tsx +54 -0
- package/src/features/FileViewer/PDFViewer/HighlightLayer.tsx +81 -0
- package/src/features/FileViewer/PDFViewer/index.tsx +93 -0
- package/src/features/FileViewer/PDFViewer/style.ts +20 -0
- package/src/features/FileViewer/PDFViewer/useResizeObserver.ts +33 -0
- package/src/features/FileViewer/TXTViewer/index.tsx +41 -0
- package/src/features/FileViewer/index.tsx +45 -0
- package/src/features/KnowledgeBaseModal/AddFilesToKnowledgeBase/SelectForm.tsx +115 -0
- package/src/features/KnowledgeBaseModal/AddFilesToKnowledgeBase/index.tsx +43 -0
- package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/Action.tsx +103 -0
- package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/EditCustomPlugin.tsx +55 -0
- package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/PluginTag.tsx +58 -0
- package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/index.tsx +70 -0
- package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/List.tsx +49 -0
- package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Loading.tsx +13 -0
- package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/index.tsx +39 -0
- package/src/features/KnowledgeBaseModal/CreateNew/CreateForm.tsx +73 -0
- package/src/features/KnowledgeBaseModal/CreateNew/index.tsx +35 -0
- package/src/features/KnowledgeBaseModal/index.ts +3 -0
- package/src/libs/langchain/loaders/pdf/index.ts +2 -2
- package/src/libs/trpc/async/asyncAuth.ts +24 -0
- package/src/libs/trpc/async/index.ts +10 -0
- package/src/libs/trpc/async/init.ts +11 -0
- package/src/libs/trpc/client/async.ts +14 -0
- package/src/libs/trpc/client/index.ts +1 -0
- package/src/libs/trpc/client/lambda.ts +9 -0
- package/src/libs/trpc/middleware/keyVaults.ts +18 -0
- package/src/libs/unstructured/__tests__/index.test.ts +0 -10
- package/src/libs/unstructured/index.ts +6 -11
- package/src/locales/default/chat.ts +47 -3
- package/src/locales/default/common.ts +1 -0
- package/src/locales/default/components.ts +2 -0
- package/src/locales/default/error.ts +6 -1
- package/src/locales/default/file.ts +92 -0
- package/src/locales/default/index.ts +4 -0
- package/src/locales/default/knowledgeBase.ts +31 -0
- package/src/locales/default/portal.ts +1 -0
- package/src/middleware.ts +3 -0
- package/src/server/asyncContext.ts +40 -0
- package/src/server/modules/ContentChunk/index.ts +135 -0
- package/src/server/modules/S3/index.ts +30 -5
- package/src/server/routers/async/caller.ts +27 -0
- package/src/server/routers/async/file.ts +247 -0
- package/src/server/routers/async/index.ts +12 -0
- package/src/server/routers/lambda/_template.ts +77 -0
- package/src/server/routers/lambda/agent.ts +159 -0
- package/src/server/routers/lambda/chunk.ts +189 -0
- package/src/server/routers/lambda/file.ts +129 -5
- package/src/server/routers/lambda/index.ts +6 -0
- package/src/server/routers/lambda/knowledgeBase.ts +79 -0
- package/src/server/routers/lambda/message.ts +6 -0
- package/src/server/routers/lambda/session.ts +0 -25
- package/src/server/routers/lambda/user.ts +5 -1
- package/src/server/services/chunk/index.ts +74 -0
- package/src/server/utils/files.ts +9 -0
- package/src/services/__tests__/chat.test.ts +18 -20
- package/src/services/__tests__/{upload.test.ts → upload_legacy.test.ts} +1 -1
- package/src/services/agent.ts +45 -0
- package/src/services/chat.ts +17 -15
- package/src/services/file/client.test.ts +1 -50
- package/src/services/file/client.ts +12 -25
- package/src/services/file/server.ts +25 -3
- package/src/services/file/type.ts +7 -4
- package/src/services/knowledgeBase.ts +34 -0
- package/src/services/message/client.test.ts +1 -1
- package/src/services/message/client.ts +29 -3
- package/src/services/message/index.ts +0 -2
- package/src/services/message/server.ts +9 -3
- package/src/services/message/type.ts +1 -13
- package/src/services/rag.ts +29 -0
- package/src/services/session/server.ts +1 -1
- package/src/services/upload.ts +89 -84
- package/src/services/upload_legacy.ts +104 -0
- package/src/services/user/client.ts +7 -2
- package/src/services/user/server.ts +6 -2
- package/src/services/user/type.ts +3 -2
- package/src/store/agent/slices/chat/action.ts +90 -18
- package/src/store/agent/slices/chat/initialState.ts +1 -0
- package/src/store/agent/slices/chat/selectors.ts +58 -0
- package/src/store/chat/slices/builtinTool/action.test.ts +2 -2
- package/src/store/chat/slices/builtinTool/action.ts +2 -2
- package/src/store/chat/slices/message/action.test.ts +2 -1
- package/src/store/chat/slices/message/action.ts +102 -26
- package/src/store/chat/slices/message/actions/rag.ts +148 -0
- package/src/store/chat/slices/message/initialState.ts +7 -0
- package/src/store/chat/slices/message/reducer.ts +6 -2
- package/src/store/chat/slices/message/selectors.ts +38 -3
- package/src/store/chat/slices/plugin/action.ts +8 -2
- package/src/store/chat/slices/portal/action.ts +8 -0
- package/src/store/chat/slices/portal/initialState.ts +3 -0
- package/src/store/chat/slices/portal/selectors.ts +8 -2
- package/src/store/file/initialState.ts +5 -1
- package/src/store/file/reducers/uploadFileList.ts +133 -0
- package/src/store/file/selectors.ts +3 -0
- package/src/store/file/slices/chat/action.test.ts +90 -90
- package/src/store/file/slices/chat/action.ts +164 -109
- package/src/store/file/slices/chat/initialState.ts +7 -2
- package/src/store/file/slices/chat/selectors.test.ts +84 -61
- package/src/store/file/slices/chat/selectors.ts +22 -32
- package/src/store/file/slices/chunk/action.ts +36 -0
- package/src/store/file/slices/chunk/index.ts +3 -0
- package/src/store/file/slices/chunk/initialState.ts +15 -0
- package/src/store/file/slices/chunk/selectors.ts +10 -0
- package/src/store/file/slices/fileManager/action.ts +187 -0
- package/src/store/file/slices/fileManager/index.ts +3 -0
- package/src/store/file/slices/fileManager/initialState.ts +18 -0
- package/src/store/file/slices/fileManager/selectors.ts +58 -0
- package/src/store/file/slices/tts/action.test.ts +1 -1
- package/src/store/file/slices/tts/action.ts +2 -2
- package/src/store/file/slices/upload/action.ts +164 -0
- package/src/store/file/store.ts +12 -1
- package/src/store/knowledgeBase/index.ts +2 -0
- package/src/store/knowledgeBase/initialState.ts +7 -0
- package/src/store/knowledgeBase/selectors.ts +1 -0
- package/src/store/knowledgeBase/slices/content/action.ts +27 -0
- package/src/store/knowledgeBase/slices/content/index.ts +1 -0
- package/src/store/knowledgeBase/slices/crud/action.ts +78 -0
- package/src/store/knowledgeBase/slices/crud/index.ts +3 -0
- package/src/store/knowledgeBase/slices/crud/initialState.ts +12 -0
- package/src/store/knowledgeBase/slices/crud/selectors.ts +7 -0
- package/src/store/knowledgeBase/store.ts +30 -0
- package/src/store/serverConfig/selectors.test.ts +1 -1
- package/src/store/user/slices/preference/selectors.ts +8 -0
- package/src/store/user/slices/settings/selectors/systemAgent.ts +2 -0
- package/src/tools/dalle/Render/Item/ImageFileItem.tsx +3 -23
- package/src/types/agent/index.ts +9 -0
- package/src/types/asyncTask.ts +31 -0
- package/src/types/chunk/document.ts +9 -0
- package/src/types/chunk/index.ts +52 -0
- package/src/types/files/index.ts +35 -0
- package/src/types/files/list.ts +44 -0
- package/src/types/files/upload.ts +91 -0
- package/src/types/knowledgeBase/index.ts +45 -0
- package/src/types/message/index.ts +54 -5
- package/src/types/rag.ts +16 -0
- package/src/utils/filter.test.ts +2 -0
- package/src/utils/server/auth.ts +23 -0
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/LocalFiles.tsx +0 -46
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files.tsx +0 -19
- package/src/components/FileList/EditableFileList.tsx +0 -47
- package/src/components/FileList/index.ts +0 -2
- package/src/components/FileList/type.tsx +0 -7
- package/src/database/server/schemas/lobechat/chat.ts +0 -331
- package/src/features/ChatInput/ActionBar/FileUpload.tsx +0 -69
- package/src/features/ChatInput/useChatInput.ts +0 -45
- package/src/features/FileList/EditableFileList.tsx +0 -31
- package/src/features/FileList/FileListPreviewer.tsx +0 -17
- package/src/features/FileList/index.tsx +0 -2
- package/src/types/files.ts +0 -42
|
@@ -14,6 +14,7 @@ import { agentSelectors } from '@/store/agent/selectors';
|
|
|
14
14
|
import { chatSelectors } from '@/store/chat/selectors';
|
|
15
15
|
import { messageMapKey } from '@/store/chat/slices/message/utils';
|
|
16
16
|
import { sessionMetaSelectors } from '@/store/session/selectors';
|
|
17
|
+
import { UploadFileItem } from '@/types/files/upload';
|
|
17
18
|
import { ChatMessage } from '@/types/message';
|
|
18
19
|
|
|
19
20
|
import { useChatStore } from '../../store';
|
|
@@ -426,7 +427,7 @@ describe('chatMessage actions', () => {
|
|
|
426
427
|
it('should create message and call internal_coreProcessMessage if message or files are provided', async () => {
|
|
427
428
|
const { result } = renderHook(() => useChatStore());
|
|
428
429
|
const message = 'Test message';
|
|
429
|
-
const files = [{ id: 'file-id'
|
|
430
|
+
const files = [{ id: 'file-id' } as UploadFileItem];
|
|
430
431
|
|
|
431
432
|
// Mock messageService.create to resolve with a message id
|
|
432
433
|
(messageService.createMessage as Mock).mockResolvedValue('new-message-id');
|
|
@@ -7,11 +7,13 @@ import { template } from 'lodash-es';
|
|
|
7
7
|
import { SWRResponse, mutate } from 'swr';
|
|
8
8
|
import { StateCreator } from 'zustand/vanilla';
|
|
9
9
|
|
|
10
|
+
import { chainAnswerWithContext } from '@/chains/answerWithContext';
|
|
10
11
|
import { LOADING_FLAT, MESSAGE_CANCEL_FLAT } from '@/const/message';
|
|
11
12
|
import { TraceEventType, TraceNameMap } from '@/const/trace';
|
|
13
|
+
import { isServerMode } from '@/const/version';
|
|
12
14
|
import { useClientDataSWR } from '@/libs/swr';
|
|
13
15
|
import { chatService } from '@/services/chat';
|
|
14
|
-
import {
|
|
16
|
+
import { messageService } from '@/services/message';
|
|
15
17
|
import { topicService } from '@/services/topic';
|
|
16
18
|
import { traceService } from '@/services/trace';
|
|
17
19
|
import { useAgentStore } from '@/store/agent';
|
|
@@ -20,7 +22,14 @@ import { chatHelpers } from '@/store/chat/helpers';
|
|
|
20
22
|
import { messageMapKey } from '@/store/chat/slices/message/utils';
|
|
21
23
|
import { ChatStore } from '@/store/chat/store';
|
|
22
24
|
import { useSessionStore } from '@/store/session';
|
|
23
|
-
import {
|
|
25
|
+
import { UploadFileItem } from '@/types/files/upload';
|
|
26
|
+
import {
|
|
27
|
+
ChatMessage,
|
|
28
|
+
ChatMessageError,
|
|
29
|
+
CreateMessageParams,
|
|
30
|
+
MessageToolCall,
|
|
31
|
+
} from '@/types/message';
|
|
32
|
+
import { MessageSemanticSearchChunk } from '@/types/rag';
|
|
24
33
|
import { TraceEventPayloads } from '@/types/trace';
|
|
25
34
|
import { setNamespace } from '@/utils/storeDebug';
|
|
26
35
|
import { nanoid } from '@/utils/uuid';
|
|
@@ -28,6 +37,7 @@ import { nanoid } from '@/utils/uuid';
|
|
|
28
37
|
import type { ChatStoreState } from '../../initialState';
|
|
29
38
|
import { chatSelectors, topicSelectors } from '../../selectors';
|
|
30
39
|
import { preventLeavingFn, toggleBooleanList } from '../../utils';
|
|
40
|
+
import { ChatRAGAction, chatRag } from './actions/rag';
|
|
31
41
|
import { MessageDispatch, messagesReducer } from './reducer';
|
|
32
42
|
|
|
33
43
|
const n = setNamespace('m');
|
|
@@ -36,7 +46,7 @@ const SWR_USE_FETCH_MESSAGES = 'SWR_USE_FETCH_MESSAGES';
|
|
|
36
46
|
|
|
37
47
|
export interface SendMessageParams {
|
|
38
48
|
message: string;
|
|
39
|
-
files?:
|
|
49
|
+
files?: UploadFileItem[];
|
|
40
50
|
onlyAddUserMessage?: boolean;
|
|
41
51
|
/**
|
|
42
52
|
*
|
|
@@ -48,9 +58,13 @@ export interface SendMessageParams {
|
|
|
48
58
|
interface ProcessMessageParams {
|
|
49
59
|
traceId?: string;
|
|
50
60
|
isWelcomeQuestion?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* the RAG query content, should be embedding and used in the semantic search
|
|
63
|
+
*/
|
|
64
|
+
ragQuery?: string;
|
|
51
65
|
}
|
|
52
66
|
|
|
53
|
-
export interface ChatMessageAction {
|
|
67
|
+
export interface ChatMessageAction extends ChatRAGAction {
|
|
54
68
|
// create
|
|
55
69
|
sendMessage: (params: SendMessageParams) => Promise<void>;
|
|
56
70
|
addAIMessage: () => Promise<void>;
|
|
@@ -174,13 +188,16 @@ export interface ChatMessageAction {
|
|
|
174
188
|
|
|
175
189
|
const getAgentConfig = () => agentSelectors.currentAgentConfig(useAgentStore.getState());
|
|
176
190
|
const getAgentChatConfig = () => agentSelectors.currentAgentChatConfig(useAgentStore.getState());
|
|
191
|
+
const getAgentKnowledge = () => agentSelectors.currentEnabledKnowledge(useAgentStore.getState());
|
|
177
192
|
|
|
178
193
|
export const chatMessage: StateCreator<
|
|
179
194
|
ChatStore,
|
|
180
195
|
[['zustand/devtools', never]],
|
|
181
196
|
[],
|
|
182
197
|
ChatMessageAction
|
|
183
|
-
> = (set, get) => ({
|
|
198
|
+
> = (set, get, ...rest) => ({
|
|
199
|
+
...chatRag(set, get, ...rest),
|
|
200
|
+
|
|
184
201
|
deleteMessage: async (id) => {
|
|
185
202
|
const message = chatSelectors.getMessageById(id)(get());
|
|
186
203
|
if (!message) return;
|
|
@@ -261,10 +278,11 @@ export const chatMessage: StateCreator<
|
|
|
261
278
|
|
|
262
279
|
const fileIdList = files?.map((f) => f.id);
|
|
263
280
|
|
|
264
|
-
const
|
|
281
|
+
const hasFile = !!fileIdList && fileIdList.length > 0;
|
|
265
282
|
|
|
266
283
|
// if message is empty or no files, then stop
|
|
267
|
-
if (!message &&
|
|
284
|
+
if (!message && !hasFile) return;
|
|
285
|
+
|
|
268
286
|
set({ isCreatingMessage: true }, false, 'creatingMessage/start');
|
|
269
287
|
|
|
270
288
|
const newMessage: CreateMessageParams = {
|
|
@@ -347,26 +365,43 @@ export const chatMessage: StateCreator<
|
|
|
347
365
|
|
|
348
366
|
// Get the current messages to generate AI response
|
|
349
367
|
const messages = chatSelectors.currentChats(get());
|
|
350
|
-
|
|
368
|
+
const userFiles = chatSelectors.currentUserFiles(get()).map((f) => f.id);
|
|
369
|
+
|
|
370
|
+
await internal_coreProcessMessage(messages, id, {
|
|
371
|
+
isWelcomeQuestion,
|
|
372
|
+
ragQuery: get().internal_shouldUseRAG() ? message : undefined,
|
|
373
|
+
});
|
|
351
374
|
|
|
352
375
|
set({ isCreatingMessage: false }, false, 'creatingMessage/stop');
|
|
353
376
|
|
|
354
|
-
|
|
355
|
-
|
|
377
|
+
const summaryTitle = async () => {
|
|
378
|
+
// if autoCreateTopic is false, then stop
|
|
379
|
+
if (!agentConfig.enableAutoCreateTopic) return;
|
|
356
380
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
381
|
+
// check activeTopic and then auto update topic title
|
|
382
|
+
if (newTopicId) {
|
|
383
|
+
const chats = chatSelectors.currentChats(get());
|
|
384
|
+
await get().summaryTopicTitle(newTopicId, chats);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
363
387
|
|
|
364
|
-
|
|
388
|
+
const topic = topicSelectors.currentActiveTopic(get());
|
|
365
389
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
390
|
+
if (topic && !topic.title) {
|
|
391
|
+
const chats = chatSelectors.currentChats(get());
|
|
392
|
+
await get().summaryTopicTitle(topic.id, chats);
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
// if there is relative files, then add files to agent
|
|
397
|
+
// only available in server mode
|
|
398
|
+
const addFilesToAgent = async () => {
|
|
399
|
+
if (userFiles.length === 0 || !isServerMode) return;
|
|
400
|
+
|
|
401
|
+
await useAgentStore.getState().addFilesToAgent(userFiles, false);
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
await Promise.all([summaryTitle(), addFilesToAgent()]);
|
|
370
405
|
},
|
|
371
406
|
addAIMessage: async () => {
|
|
372
407
|
const { internal_createMessage, updateInputMessage, activeTopicId, activeId, inputMessage } =
|
|
@@ -446,12 +481,48 @@ export const chatMessage: StateCreator<
|
|
|
446
481
|
},
|
|
447
482
|
|
|
448
483
|
// the internal process method of the AI message
|
|
449
|
-
internal_coreProcessMessage: async (
|
|
484
|
+
internal_coreProcessMessage: async (originalMessages, userMessageId, params) => {
|
|
450
485
|
const { internal_fetchAIChatMessage, triggerToolCalls, refreshMessages, activeTopicId } = get();
|
|
451
486
|
|
|
487
|
+
// create a new array to avoid the original messages array change
|
|
488
|
+
const messages = [...originalMessages];
|
|
489
|
+
|
|
452
490
|
const { model, provider } = getAgentConfig();
|
|
453
491
|
|
|
454
|
-
|
|
492
|
+
let fileChunks: MessageSemanticSearchChunk[] | undefined;
|
|
493
|
+
let ragQueryId;
|
|
494
|
+
// go into RAG flow if there is ragQuery flag
|
|
495
|
+
if (params?.ragQuery) {
|
|
496
|
+
// 1. get the relative chunks from semantic search
|
|
497
|
+
const { chunks, queryId } = await get().internal_retrieveChunks(
|
|
498
|
+
userMessageId,
|
|
499
|
+
params?.ragQuery,
|
|
500
|
+
// should skip the last content
|
|
501
|
+
messages.map((m) => m.content).slice(0, messages.length - 1),
|
|
502
|
+
);
|
|
503
|
+
|
|
504
|
+
ragQueryId = queryId;
|
|
505
|
+
|
|
506
|
+
console.log('召回 chunks', chunks);
|
|
507
|
+
|
|
508
|
+
// 2. build the retrieve context messages
|
|
509
|
+
const retrieveContext = chainAnswerWithContext({
|
|
510
|
+
context: chunks.map((c) => c.text as string),
|
|
511
|
+
question: params?.ragQuery,
|
|
512
|
+
knowledge: getAgentKnowledge().map((knowledge) => knowledge.name),
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
// 3. add the retrieve context messages to the messages history
|
|
516
|
+
if (retrieveContext.messages && retrieveContext.messages?.length > 0) {
|
|
517
|
+
// remove the last message due to the query is in the retrieveContext
|
|
518
|
+
messages.pop();
|
|
519
|
+
retrieveContext.messages?.forEach((m) => messages.push(m as ChatMessage));
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
fileChunks = chunks.map((c) => ({ id: c.id, similarity: c.similarity }));
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// 2. Add an empty message to place the AI response
|
|
455
526
|
const assistantMessage: CreateMessageParams = {
|
|
456
527
|
role: 'assistant',
|
|
457
528
|
content: LOADING_FLAT,
|
|
@@ -461,14 +532,16 @@ export const chatMessage: StateCreator<
|
|
|
461
532
|
parentId: userMessageId,
|
|
462
533
|
sessionId: get().activeId,
|
|
463
534
|
topicId: activeTopicId, // if there is activeTopicId,then add it to topicId
|
|
535
|
+
fileChunks,
|
|
536
|
+
ragQueryId,
|
|
464
537
|
};
|
|
465
538
|
|
|
466
539
|
const assistantId = await get().internal_createMessage(assistantMessage);
|
|
467
540
|
|
|
468
|
-
//
|
|
541
|
+
// 3. fetch the AI response
|
|
469
542
|
const { isFunctionCall } = await internal_fetchAIChatMessage(messages, assistantId, params);
|
|
470
543
|
|
|
471
|
-
//
|
|
544
|
+
// 4. if it's the function call message, trigger the function method
|
|
472
545
|
if (isFunctionCall) {
|
|
473
546
|
await refreshMessages();
|
|
474
547
|
await triggerToolCalls(assistantId);
|
|
@@ -661,7 +734,10 @@ export const chatMessage: StateCreator<
|
|
|
661
734
|
|
|
662
735
|
if (!latestMsg) return;
|
|
663
736
|
|
|
664
|
-
await internal_coreProcessMessage(contextMessages, latestMsg.id, {
|
|
737
|
+
await internal_coreProcessMessage(contextMessages, latestMsg.id, {
|
|
738
|
+
traceId,
|
|
739
|
+
ragQuery: get().internal_shouldUseRAG() ? currentMessage.content : undefined,
|
|
740
|
+
});
|
|
665
741
|
},
|
|
666
742
|
|
|
667
743
|
internal_updateMessageError: async (id, error) => {
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { StateCreator } from 'zustand/vanilla';
|
|
2
|
+
|
|
3
|
+
import { chainRewriteQuery } from '@/chains/rewriteQuery';
|
|
4
|
+
import { chatService } from '@/services/chat';
|
|
5
|
+
import { ragService } from '@/services/rag';
|
|
6
|
+
import { useAgentStore } from '@/store/agent';
|
|
7
|
+
import { agentSelectors } from '@/store/agent/selectors';
|
|
8
|
+
import { ChatStore } from '@/store/chat';
|
|
9
|
+
import { chatSelectors } from '@/store/chat/selectors';
|
|
10
|
+
import { toggleBooleanList } from '@/store/chat/utils';
|
|
11
|
+
import { useUserStore } from '@/store/user';
|
|
12
|
+
import { systemAgentSelectors } from '@/store/user/selectors';
|
|
13
|
+
import { ChatSemanticSearchChunk } from '@/types/chunk';
|
|
14
|
+
import { merge } from '@/utils/merge';
|
|
15
|
+
|
|
16
|
+
export interface ChatRAGAction {
|
|
17
|
+
deleteUserMessageRagQuery: (id: string) => Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Retrieve chunks from semantic search
|
|
20
|
+
*/
|
|
21
|
+
internal_retrieveChunks: (
|
|
22
|
+
id: string,
|
|
23
|
+
userQuery: string,
|
|
24
|
+
messages: string[],
|
|
25
|
+
) => Promise<{ chunks: ChatSemanticSearchChunk[]; queryId: string }>;
|
|
26
|
+
/**
|
|
27
|
+
* Rewrite user content to better RAG query
|
|
28
|
+
*/
|
|
29
|
+
internal_rewriteQuery: (id: string, content: string, messages: string[]) => Promise<string>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Check if we should use RAG
|
|
33
|
+
*/
|
|
34
|
+
internal_shouldUseRAG: () => boolean;
|
|
35
|
+
internal_toggleMessageRAGLoading: (loading: boolean, id: string) => void;
|
|
36
|
+
rewriteQuery: (id: string) => Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const knowledgeIds = () => agentSelectors.currentKnowledgeIds(useAgentStore.getState());
|
|
40
|
+
const hasEnabledKnowledge = () => agentSelectors.hasEnabledKnowledge(useAgentStore.getState());
|
|
41
|
+
|
|
42
|
+
export const chatRag: StateCreator<ChatStore, [['zustand/devtools', never]], [], ChatRAGAction> = (
|
|
43
|
+
set,
|
|
44
|
+
get,
|
|
45
|
+
) => ({
|
|
46
|
+
deleteUserMessageRagQuery: async (id) => {
|
|
47
|
+
const message = chatSelectors.getMessageById(id)(get());
|
|
48
|
+
|
|
49
|
+
if (!message || !message.ragQueryId) return;
|
|
50
|
+
|
|
51
|
+
// optimistic update the message's ragQuery
|
|
52
|
+
get().internal_dispatchMessage({
|
|
53
|
+
id,
|
|
54
|
+
type: 'updateMessage',
|
|
55
|
+
value: { ragQuery: null },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
await ragService.deleteMessageRagQuery(message.ragQueryId);
|
|
59
|
+
await get().refreshMessages();
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
internal_retrieveChunks: async (id, userQuery, messages) => {
|
|
63
|
+
get().internal_toggleMessageRAGLoading(true, id);
|
|
64
|
+
|
|
65
|
+
const message = chatSelectors.getMessageById(id)(get());
|
|
66
|
+
|
|
67
|
+
// 1. get the rewrite query
|
|
68
|
+
let rewriteQuery = message?.ragQuery || userQuery;
|
|
69
|
+
|
|
70
|
+
// if there is no ragQuery and there is a chat history
|
|
71
|
+
// we need to rewrite the user message to get better results
|
|
72
|
+
if (!message?.ragQuery && messages.length > 0) {
|
|
73
|
+
rewriteQuery = await get().internal_rewriteQuery(id, userQuery, messages);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 2. retrieve chunks from semantic search
|
|
77
|
+
const files = chatSelectors.currentUserFiles(get()).map((f) => f.id);
|
|
78
|
+
const { chunks, queryId } = await ragService.semanticSearchForChat({
|
|
79
|
+
fileIds: knowledgeIds().fileIds.concat(files),
|
|
80
|
+
knowledgeIds: knowledgeIds().knowledgeBaseIds,
|
|
81
|
+
messageId: id,
|
|
82
|
+
rewriteQuery,
|
|
83
|
+
userQuery,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
get().internal_toggleMessageRAGLoading(false, id);
|
|
87
|
+
|
|
88
|
+
return { chunks, queryId };
|
|
89
|
+
},
|
|
90
|
+
internal_rewriteQuery: async (id, content, messages) => {
|
|
91
|
+
let rewriteQuery = content;
|
|
92
|
+
|
|
93
|
+
const queryRewriteConfig = systemAgentSelectors.queryRewrite(useUserStore.getState());
|
|
94
|
+
const rewriteQueryParams = merge(queryRewriteConfig, chainRewriteQuery(content, messages));
|
|
95
|
+
|
|
96
|
+
let ragQuery = '';
|
|
97
|
+
await chatService.fetchPresetTaskResult({
|
|
98
|
+
onFinish: async (text) => {
|
|
99
|
+
rewriteQuery = text;
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
onMessageHandle: (chunk) => {
|
|
103
|
+
if (chunk.type !== 'text') return;
|
|
104
|
+
ragQuery += chunk.text;
|
|
105
|
+
|
|
106
|
+
get().internal_dispatchMessage({
|
|
107
|
+
id,
|
|
108
|
+
type: 'updateMessage',
|
|
109
|
+
value: { ragQuery },
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
params: rewriteQueryParams,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return rewriteQuery;
|
|
116
|
+
},
|
|
117
|
+
internal_shouldUseRAG: () => {
|
|
118
|
+
const userFiles = chatSelectors.currentUserFiles(get()).map((f) => f.id);
|
|
119
|
+
// if there is relative files or enabled knowledge, try with ragQuery
|
|
120
|
+
return hasEnabledKnowledge() || userFiles.length > 0;
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
internal_toggleMessageRAGLoading: (loading, id) => {
|
|
124
|
+
set(
|
|
125
|
+
{
|
|
126
|
+
messageRAGLoadingIds: toggleBooleanList(get().messageRAGLoadingIds, id, loading),
|
|
127
|
+
},
|
|
128
|
+
false,
|
|
129
|
+
'internal_toggleMessageLoading',
|
|
130
|
+
);
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
rewriteQuery: async (id) => {
|
|
134
|
+
const message = chatSelectors.getMessageById(id)(get());
|
|
135
|
+
if (!message) return;
|
|
136
|
+
|
|
137
|
+
// delete the current ragQuery
|
|
138
|
+
await get().deleteUserMessageRagQuery(id);
|
|
139
|
+
|
|
140
|
+
const chats = chatSelectors.currentChatsWithHistoryConfig(get());
|
|
141
|
+
|
|
142
|
+
await get().internal_rewriteQuery(
|
|
143
|
+
id,
|
|
144
|
+
message.content,
|
|
145
|
+
chats.map((m) => m.content),
|
|
146
|
+
);
|
|
147
|
+
},
|
|
148
|
+
});
|
|
@@ -11,6 +11,7 @@ export interface ChatMessageState {
|
|
|
11
11
|
* is the AI message is generating
|
|
12
12
|
*/
|
|
13
13
|
chatLoadingIds: string[];
|
|
14
|
+
inputFiles: File[];
|
|
14
15
|
inputMessage: string;
|
|
15
16
|
isCreatingMessage: boolean;
|
|
16
17
|
/**
|
|
@@ -21,6 +22,10 @@ export interface ChatMessageState {
|
|
|
21
22
|
* is the message is creating or updating in the service
|
|
22
23
|
*/
|
|
23
24
|
messageLoadingIds: string[];
|
|
25
|
+
/**
|
|
26
|
+
* is the message is in RAG flow
|
|
27
|
+
*/
|
|
28
|
+
messageRAGLoadingIds: string[];
|
|
24
29
|
/**
|
|
25
30
|
* whether messages have fetched
|
|
26
31
|
*/
|
|
@@ -36,10 +41,12 @@ export interface ChatMessageState {
|
|
|
36
41
|
export const initialMessageState: ChatMessageState = {
|
|
37
42
|
activeId: 'inbox',
|
|
38
43
|
chatLoadingIds: [],
|
|
44
|
+
inputFiles: [],
|
|
39
45
|
inputMessage: '',
|
|
40
46
|
isCreatingMessage: false,
|
|
41
47
|
messageEditingIds: [],
|
|
42
48
|
messageLoadingIds: [],
|
|
49
|
+
messageRAGLoadingIds: [],
|
|
43
50
|
messagesInit: false,
|
|
44
51
|
messagesMap: {},
|
|
45
52
|
pluginApiLoadingIds: [],
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import isEqual from 'fast-deep-equal';
|
|
2
2
|
import { produce } from 'immer';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
ChatMessage,
|
|
6
|
+
ChatPluginPayload,
|
|
7
|
+
ChatToolPayload,
|
|
8
|
+
CreateMessageParams,
|
|
9
|
+
} from '@/types/message';
|
|
6
10
|
import { merge } from '@/utils/merge';
|
|
7
11
|
|
|
8
12
|
interface UpdateMessages {
|
|
@@ -11,7 +11,7 @@ import { useSessionStore } from '@/store/session';
|
|
|
11
11
|
import { sessionMetaSelectors } from '@/store/session/selectors';
|
|
12
12
|
import { useUserStore } from '@/store/user';
|
|
13
13
|
import { userProfileSelectors } from '@/store/user/selectors';
|
|
14
|
-
import { ChatMessage } from '@/types/message';
|
|
14
|
+
import { ChatFileItem, ChatMessage } from '@/types/message';
|
|
15
15
|
import { MetaData } from '@/types/meta';
|
|
16
16
|
import { merge } from '@/utils/merge';
|
|
17
17
|
|
|
@@ -53,6 +53,21 @@ const currentToolMessages = (s: ChatStore) => {
|
|
|
53
53
|
return messages.filter((m) => m.role === 'tool');
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
+
const currentUserMessages = (s: ChatStore) => {
|
|
57
|
+
const messages = currentChats(s);
|
|
58
|
+
|
|
59
|
+
return messages.filter((m) => m.role === 'user');
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const currentUserFiles = (s: ChatStore) => {
|
|
63
|
+
const userMessages = currentUserMessages(s);
|
|
64
|
+
|
|
65
|
+
return userMessages
|
|
66
|
+
.filter((m) => m.fileList && m.fileList?.length > 0)
|
|
67
|
+
.flatMap((m) => m.fileList)
|
|
68
|
+
.filter(Boolean) as ChatFileItem[];
|
|
69
|
+
};
|
|
70
|
+
|
|
56
71
|
const initTime = Date.now();
|
|
57
72
|
|
|
58
73
|
const showInboxWelcome = (s: ChatStore): boolean => {
|
|
@@ -140,10 +155,9 @@ const isCurrentChatLoaded = (s: ChatStore) => !!s.messagesMap[currentChatKey(s)]
|
|
|
140
155
|
|
|
141
156
|
const isMessageEditing = (id: string) => (s: ChatStore) => s.messageEditingIds.includes(id);
|
|
142
157
|
const isMessageLoading = (id: string) => (s: ChatStore) => s.messageLoadingIds.includes(id);
|
|
143
|
-
const isHasMessageLoading = (s: ChatStore) => s.messageLoadingIds.length > 0;
|
|
144
|
-
const isCreatingMessage = (s: ChatStore) => s.isCreatingMessage;
|
|
145
158
|
|
|
146
159
|
const isMessageGenerating = (id: string) => (s: ChatStore) => s.chatLoadingIds.includes(id);
|
|
160
|
+
const isMessageInRAGFlow = (id: string) => (s: ChatStore) => s.messageRAGLoadingIds.includes(id);
|
|
147
161
|
const isPluginApiInvoking = (id: string) => (s: ChatStore) => s.pluginApiLoadingIds.includes(id);
|
|
148
162
|
|
|
149
163
|
const isToolCallStreaming = (id: string, index: number) => (s: ChatStore) => {
|
|
@@ -153,7 +167,25 @@ const isToolCallStreaming = (id: string, index: number) => (s: ChatStore) => {
|
|
|
153
167
|
|
|
154
168
|
return isLoading[index];
|
|
155
169
|
};
|
|
170
|
+
|
|
156
171
|
const isAIGenerating = (s: ChatStore) => s.chatLoadingIds.length > 0;
|
|
172
|
+
const isInRAGFlow = (s: ChatStore) => s.messageRAGLoadingIds.length > 0;
|
|
173
|
+
const isCreatingMessage = (s: ChatStore) => s.isCreatingMessage;
|
|
174
|
+
const isHasMessageLoading = (s: ChatStore) => s.messageLoadingIds.length > 0;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* this function is used to determine whether the send button should be disabled
|
|
178
|
+
* @param s
|
|
179
|
+
*/
|
|
180
|
+
const isSendButtonDisabledByMessage = (s: ChatStore) =>
|
|
181
|
+
// 1. when there is message loading
|
|
182
|
+
isHasMessageLoading(s) ||
|
|
183
|
+
// 2. when is creating the topic
|
|
184
|
+
s.creatingTopic ||
|
|
185
|
+
// 3. when is creating the message
|
|
186
|
+
isCreatingMessage(s) ||
|
|
187
|
+
// 4. when the message is in RAG flow
|
|
188
|
+
isInRAGFlow(s);
|
|
157
189
|
|
|
158
190
|
export const chatSelectors = {
|
|
159
191
|
chatsMessageString,
|
|
@@ -164,6 +196,7 @@ export const chatSelectors = {
|
|
|
164
196
|
currentChatsWithGuideMessage,
|
|
165
197
|
currentChatsWithHistoryConfig,
|
|
166
198
|
currentToolMessages,
|
|
199
|
+
currentUserFiles,
|
|
167
200
|
getMessageById,
|
|
168
201
|
getMessageByToolCallId,
|
|
169
202
|
getTraceIdByMessageId,
|
|
@@ -173,8 +206,10 @@ export const chatSelectors = {
|
|
|
173
206
|
isHasMessageLoading,
|
|
174
207
|
isMessageEditing,
|
|
175
208
|
isMessageGenerating,
|
|
209
|
+
isMessageInRAGFlow,
|
|
176
210
|
isMessageLoading,
|
|
177
211
|
isPluginApiInvoking,
|
|
212
|
+
isSendButtonDisabledByMessage,
|
|
178
213
|
isToolCallStreaming,
|
|
179
214
|
latestMessage,
|
|
180
215
|
showInboxWelcome,
|
|
@@ -8,13 +8,19 @@ import { StateCreator } from 'zustand/vanilla';
|
|
|
8
8
|
import { LOADING_FLAT } from '@/const/message';
|
|
9
9
|
import { PLUGIN_SCHEMA_API_MD5_PREFIX, PLUGIN_SCHEMA_SEPARATOR } from '@/const/plugin';
|
|
10
10
|
import { chatService } from '@/services/chat';
|
|
11
|
-
import {
|
|
11
|
+
import { messageService } from '@/services/message';
|
|
12
12
|
import { ChatStore } from '@/store/chat/store';
|
|
13
13
|
import { useToolStore } from '@/store/tool';
|
|
14
14
|
import { pluginSelectors } from '@/store/tool/selectors';
|
|
15
15
|
import { builtinTools } from '@/tools';
|
|
16
16
|
import { ChatErrorType } from '@/types/fetch';
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
ChatMessage,
|
|
19
|
+
ChatMessageError,
|
|
20
|
+
ChatToolPayload,
|
|
21
|
+
CreateMessageParams,
|
|
22
|
+
MessageToolCall,
|
|
23
|
+
} from '@/types/message';
|
|
18
24
|
import { merge } from '@/utils/merge';
|
|
19
25
|
import { safeParseJSON } from '@/utils/safeParseJSON';
|
|
20
26
|
import { setNamespace } from '@/utils/storeDebug';
|
|
@@ -4,6 +4,7 @@ import { ChatStore } from '@/store/chat/store';
|
|
|
4
4
|
|
|
5
5
|
export interface ChatPortalAction {
|
|
6
6
|
closeToolUI: () => void;
|
|
7
|
+
openFilePreview: (fileId: string) => void;
|
|
7
8
|
openToolUI: (messageId: string, identifier: string) => void;
|
|
8
9
|
togglePortal: (open?: boolean) => void;
|
|
9
10
|
}
|
|
@@ -17,6 +18,13 @@ export const chatPortalSlice: StateCreator<
|
|
|
17
18
|
closeToolUI: () => {
|
|
18
19
|
set({ portalToolMessage: undefined }, false, 'openToolUI');
|
|
19
20
|
},
|
|
21
|
+
openFilePreview: (fileId) => {
|
|
22
|
+
if (!get().showPortal) {
|
|
23
|
+
get().togglePortal(true);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
set({ portalFile: { fileId } }, false, 'openFilePreview');
|
|
27
|
+
},
|
|
20
28
|
openToolUI: (id, identifier) => {
|
|
21
29
|
if (!get().showPortal) {
|
|
22
30
|
get().togglePortal(true);
|
|
@@ -6,10 +6,16 @@ const showPortal = (s: ChatStoreState) => s.showPortal;
|
|
|
6
6
|
const isArtifactMessageUIOpen = (id: string) => (s: ChatStoreState) =>
|
|
7
7
|
artifactMessageId(s) === id && showPortal(s);
|
|
8
8
|
|
|
9
|
+
const showArtifactUI = (s: ChatStoreState) => !!s.portalToolMessage;
|
|
10
|
+
const showFilePreview = (s: ChatStoreState) => !!s.portalFile;
|
|
11
|
+
const previewFileId = (s: ChatStoreState) => s.portalFile?.fileId;
|
|
12
|
+
|
|
9
13
|
export const chatPortalSelectors = {
|
|
10
14
|
artifactMessageId,
|
|
11
15
|
isArtifactMessageUIOpen,
|
|
12
|
-
|
|
16
|
+
previewFileId,
|
|
17
|
+
showArtifactUI,
|
|
18
|
+
showFilePreview,
|
|
13
19
|
showPortal,
|
|
14
|
-
toolUIIdentifier: (
|
|
20
|
+
toolUIIdentifier: (s: ChatStoreState) => s.portalToolMessage?.identifier,
|
|
15
21
|
};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { ImageFileState, initialImageFileState } from './slices/chat';
|
|
2
|
+
import { FileChunkState, initialFileChunkState } from './slices/chunk';
|
|
3
|
+
import { FileManagerState, initialFileManagerState } from './slices/fileManager';
|
|
2
4
|
|
|
3
|
-
export type FilesStoreState = ImageFileState;
|
|
5
|
+
export type FilesStoreState = ImageFileState & FileManagerState & FileChunkState;
|
|
4
6
|
|
|
5
7
|
export const initialState: FilesStoreState = {
|
|
6
8
|
...initialImageFileState,
|
|
9
|
+
...initialFileManagerState,
|
|
10
|
+
...initialFileChunkState,
|
|
7
11
|
};
|