@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.
Files changed (354) hide show
  1. package/.github/workflows/release.yml +2 -1
  2. package/.github/workflows/test.yml +2 -1
  3. package/CHANGELOG.md +25 -0
  4. package/Dockerfile.database +2 -0
  5. package/docs/self-hosting/advanced/knowledge-base.zh-CN.mdx +65 -0
  6. package/locales/ar/chat.json +13 -3
  7. package/locales/ar/components.json +2 -0
  8. package/locales/bg-BG/chat.json +13 -3
  9. package/locales/bg-BG/components.json +2 -0
  10. package/locales/de-DE/chat.json +13 -3
  11. package/locales/de-DE/components.json +2 -0
  12. package/locales/en-US/chat.json +13 -3
  13. package/locales/en-US/components.json +2 -0
  14. package/locales/es-ES/chat.json +13 -3
  15. package/locales/es-ES/components.json +2 -0
  16. package/locales/fr-FR/chat.json +13 -3
  17. package/locales/fr-FR/components.json +2 -0
  18. package/locales/it-IT/chat.json +13 -3
  19. package/locales/it-IT/components.json +2 -0
  20. package/locales/ja-JP/chat.json +13 -3
  21. package/locales/ja-JP/components.json +2 -0
  22. package/locales/ko-KR/chat.json +13 -3
  23. package/locales/ko-KR/components.json +2 -0
  24. package/locales/nl-NL/chat.json +13 -3
  25. package/locales/nl-NL/components.json +2 -0
  26. package/locales/pl-PL/chat.json +13 -3
  27. package/locales/pl-PL/components.json +2 -0
  28. package/locales/pt-BR/chat.json +13 -3
  29. package/locales/pt-BR/components.json +2 -0
  30. package/locales/ru-RU/chat.json +13 -3
  31. package/locales/ru-RU/components.json +2 -0
  32. package/locales/tr-TR/chat.json +13 -3
  33. package/locales/tr-TR/components.json +2 -0
  34. package/locales/vi-VN/chat.json +13 -3
  35. package/locales/vi-VN/components.json +2 -0
  36. package/locales/zh-CN/chat.json +13 -3
  37. package/locales/zh-CN/components.json +2 -0
  38. package/locales/zh-TW/chat.json +13 -3
  39. package/locales/zh-TW/components.json +2 -0
  40. package/package.json +3 -2
  41. package/scripts/migrateServerDB/docker.cjs +6 -0
  42. package/scripts/migrateServerDB/errorHint.js +17 -0
  43. package/scripts/migrateServerDB/index.ts +6 -0
  44. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/Content.tsx +37 -0
  45. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/index.tsx +87 -0
  46. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/style.ts +4 -0
  47. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/utils.ts +28 -0
  48. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileList.tsx +41 -0
  49. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/index.tsx +40 -0
  50. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/SendMore.tsx +1 -1
  51. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/index.tsx +7 -22
  52. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/TextArea.tsx +1 -1
  53. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/index.tsx +2 -4
  54. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/File.tsx +72 -0
  55. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/Image.tsx +74 -0
  56. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/index.tsx +39 -0
  57. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/style.ts +1 -0
  58. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/index.tsx +33 -0
  59. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/InputArea/Container.tsx +41 -0
  60. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/InputArea/index.tsx +154 -0
  61. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Send.tsx +34 -0
  62. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/index.tsx +24 -11
  63. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/components/UploadDetail/UploadStatus.tsx +71 -0
  64. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/components/UploadDetail/index.tsx +49 -0
  65. package/src/app/(main)/chat/(workspace)/@portal/FilePreview/index.tsx +26 -0
  66. package/src/app/(main)/chat/(workspace)/@portal/Home/Files/FileList/Item.tsx +53 -0
  67. package/src/app/(main)/chat/(workspace)/@portal/Home/Files/FileList/index.tsx +50 -0
  68. package/src/app/(main)/chat/(workspace)/@portal/Home/Files/index.tsx +21 -0
  69. package/src/app/(main)/chat/(workspace)/@portal/Home/index.tsx +2 -0
  70. package/src/app/(main)/chat/(workspace)/@portal/router.tsx +4 -0
  71. package/src/app/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/KnowledgeTag.tsx +41 -0
  72. package/src/app/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/Tags.tsx +7 -2
  73. package/src/app/(main)/chat/(workspace)/_layout/Desktop/HotKeys.tsx +1 -1
  74. package/src/app/(main)/files/(content)/@menu/default.tsx +27 -0
  75. package/src/app/(main)/files/(content)/@menu/features/FileMenu/index.tsx +97 -0
  76. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/EmptyStatus.tsx +53 -0
  77. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/Item/Content.tsx +175 -0
  78. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/Item/index.tsx +69 -0
  79. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/KnowledgeBaseList.tsx +30 -0
  80. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/SkeletonList.tsx +57 -0
  81. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/index.tsx +54 -0
  82. package/src/app/(main)/files/(content)/@modal/(.)[id]/FileDetail.tsx +16 -0
  83. package/src/app/(main)/files/(content)/@modal/(.)[id]/FilePreview.tsx +15 -0
  84. package/src/app/(main)/files/(content)/@modal/(.)[id]/FullscreenModal.tsx +85 -0
  85. package/src/app/(main)/files/(content)/@modal/(.)[id]/page.tsx +19 -0
  86. package/src/app/(main)/files/(content)/@modal/default.tsx +3 -0
  87. package/src/app/(main)/files/(content)/NotSupportClient.tsx +152 -0
  88. package/src/app/(main)/files/(content)/_layout/Desktop/index.tsx +28 -0
  89. package/src/app/(main)/files/(content)/_layout/Mobile.tsx +47 -0
  90. package/src/app/(main)/files/(content)/_layout/type.ts +7 -0
  91. package/src/app/(main)/files/(content)/layout.tsx +18 -0
  92. package/src/app/(main)/files/(content)/page.tsx +14 -0
  93. package/src/app/(main)/files/[id]/Header.tsx +63 -0
  94. package/src/app/(main)/files/[id]/page.tsx +44 -0
  95. package/src/app/(main)/files/features/FileDetail.tsx +93 -0
  96. package/src/app/(main)/files/hooks/useFileCategory.ts +9 -0
  97. package/src/app/(main)/files/layout.tsx +12 -0
  98. package/src/app/(main)/files/loading.tsx +21 -0
  99. package/src/app/(main)/repos/[id]/@menu/Head/index.tsx +33 -0
  100. package/src/app/(main)/repos/[id]/@menu/Menu/index.tsx +56 -0
  101. package/src/app/(main)/repos/[id]/@menu/default.tsx +25 -0
  102. package/src/app/(main)/repos/[id]/_layout/Desktop/index.tsx +25 -0
  103. package/src/app/(main)/repos/[id]/_layout/Mobile.tsx +47 -0
  104. package/src/app/(main)/repos/[id]/_layout/type.ts +6 -0
  105. package/src/app/(main)/repos/[id]/hooks/useKnowledgeItem.ts +7 -0
  106. package/src/app/(main)/repos/[id]/layout.tsx +13 -0
  107. package/src/app/(main)/repos/[id]/page.tsx +18 -0
  108. package/src/app/(main)/repos/layout.tsx +13 -0
  109. package/src/app/(main)/repos/page.tsx +5 -0
  110. package/src/app/trpc/async/[trpc]/route.ts +28 -0
  111. package/src/chains/abstractChunk.ts +19 -0
  112. package/src/chains/answerWithContext.ts +34 -0
  113. package/src/chains/rewriteQuery.ts +22 -0
  114. package/src/components/DragUpload/index.tsx +6 -99
  115. package/src/components/DragUpload/useDragUpload.tsx +146 -0
  116. package/src/components/FeatureList/index.tsx +64 -0
  117. package/src/components/FileParsingStatus/index.tsx +230 -0
  118. package/src/components/ImageItem/index.tsx +10 -2
  119. package/src/components/KnowledgeIcon/index.tsx +28 -0
  120. package/src/config/app.ts +6 -1
  121. package/src/config/featureFlags/schema.ts +1 -1
  122. package/src/const/file.ts +1 -0
  123. package/src/const/url.ts +1 -0
  124. package/src/database/client/models/file.ts +8 -2
  125. package/src/database/server/migrations/0005_pgvector.sql +2 -0
  126. package/src/database/server/migrations/0006_add_knowledge_base.sql +307 -0
  127. package/src/database/server/migrations/meta/0005_snapshot.json +2119 -0
  128. package/src/database/server/migrations/meta/0006_snapshot.json +3006 -0
  129. package/src/database/server/migrations/meta/_journal.json +14 -0
  130. package/src/database/server/models/__tests__/_test_template.ts +155 -0
  131. package/src/database/server/models/__tests__/agent.test.ts +226 -0
  132. package/src/database/server/models/__tests__/asyncTask.test.ts +176 -0
  133. package/src/database/server/models/__tests__/chunk.test.ts +336 -0
  134. package/src/database/server/models/__tests__/file.test.ts +317 -29
  135. package/src/database/server/models/__tests__/fixtures/embedding.ts +568 -0
  136. package/src/database/server/models/__tests__/knowledgeBase.test.ts +132 -0
  137. package/src/database/server/models/__tests__/message.test.ts +7 -4
  138. package/src/database/server/models/_template.ts +10 -1
  139. package/src/database/server/models/agent.ts +165 -0
  140. package/src/database/server/models/asyncTask.ts +96 -0
  141. package/src/database/server/models/chunk.ts +203 -0
  142. package/src/database/server/models/embedding.ts +47 -0
  143. package/src/database/server/models/file.ts +231 -12
  144. package/src/database/server/models/knowledgeBase.ts +94 -0
  145. package/src/database/server/models/message.ts +156 -30
  146. package/src/database/server/models/user.ts +12 -1
  147. package/src/database/server/schemas/lobechat/agent.ts +93 -0
  148. package/src/database/server/schemas/lobechat/discover.ts +1 -1
  149. package/src/database/server/schemas/lobechat/file.ts +118 -1
  150. package/src/database/server/schemas/lobechat/index.ts +5 -1
  151. package/src/database/server/schemas/lobechat/message.ts +169 -0
  152. package/src/database/server/schemas/lobechat/rag.ts +51 -0
  153. package/src/database/server/schemas/lobechat/relations.ts +68 -48
  154. package/src/database/server/schemas/lobechat/session.ts +77 -0
  155. package/src/database/server/schemas/lobechat/topic.ts +32 -0
  156. package/src/database/server/schemas/lobechat/user.ts +40 -25
  157. package/src/database/server/utils/idGenerator.ts +1 -0
  158. package/src/features/ChatInput/ActionBar/Clear.tsx +1 -1
  159. package/src/features/ChatInput/ActionBar/Knowledge/Dropdown.tsx +160 -0
  160. package/src/features/ChatInput/ActionBar/Knowledge/ListItem.tsx +52 -0
  161. package/src/features/ChatInput/ActionBar/Knowledge/index.tsx +54 -0
  162. package/src/features/ChatInput/ActionBar/Tools/index.tsx +1 -1
  163. package/src/features/ChatInput/ActionBar/Upload/ClientMode.tsx +52 -0
  164. package/src/features/ChatInput/ActionBar/Upload/ServerMode.tsx +104 -0
  165. package/src/features/ChatInput/ActionBar/Upload/index.tsx +8 -0
  166. package/src/features/ChatInput/ActionBar/config.ts +14 -5
  167. package/src/features/ChatInput/useSend.ts +16 -7
  168. package/src/features/Conversation/Messages/Assistant/FileChunks/Item/index.tsx +51 -0
  169. package/src/features/Conversation/Messages/Assistant/FileChunks/Item/style.ts +38 -0
  170. package/src/features/Conversation/Messages/Assistant/FileChunks/index.tsx +76 -0
  171. package/src/features/Conversation/Messages/Assistant/index.tsx +13 -4
  172. package/src/features/Conversation/Messages/Default.tsx +4 -0
  173. package/src/features/Conversation/Messages/User/BelowMessage.tsx +78 -0
  174. package/src/features/Conversation/Messages/User/FileListViewer/Item.tsx +53 -0
  175. package/src/features/Conversation/Messages/User/FileListViewer/index.tsx +21 -0
  176. package/src/{components/FileList/FileListViewer.tsx → features/Conversation/Messages/User/ImageFileListViewer.tsx} +10 -2
  177. package/src/features/Conversation/Messages/{User.tsx → User/index.tsx} +11 -2
  178. package/src/features/Conversation/Messages/index.ts +8 -3
  179. package/src/features/Conversation/components/ChatItem/index.tsx +33 -10
  180. package/src/features/Conversation/components/InboxWelcome/QuestionSuggest.tsx +1 -1
  181. package/src/features/Conversation/types/index.tsx +1 -0
  182. package/src/features/FileManager/ChunkDrawer/ChunkList/ChunkItem.tsx +61 -0
  183. package/src/features/FileManager/ChunkDrawer/ChunkList/index.tsx +42 -0
  184. package/src/features/FileManager/ChunkDrawer/Content.tsx +38 -0
  185. package/src/features/FileManager/ChunkDrawer/Loading/index.tsx +16 -0
  186. package/src/features/FileManager/ChunkDrawer/SimilaritySearchList/Item.tsx +62 -0
  187. package/src/features/FileManager/ChunkDrawer/SimilaritySearchList/index.tsx +31 -0
  188. package/src/features/FileManager/ChunkDrawer/index.tsx +48 -0
  189. package/src/features/FileManager/FileList/EmptyStatus.tsx +153 -0
  190. package/src/features/FileManager/FileList/FileListItem/ChunkTag.tsx +35 -0
  191. package/src/features/FileManager/FileList/FileListItem/DropdownMenu.tsx +150 -0
  192. package/src/features/FileManager/FileList/FileListItem/index.tsx +211 -0
  193. package/src/features/FileManager/FileList/FileSkeleton.tsx +25 -0
  194. package/src/features/FileManager/FileList/ToolBar/Config.tsx +28 -0
  195. package/src/features/FileManager/FileList/ToolBar/MultiSelectActions.tsx +152 -0
  196. package/src/features/FileManager/FileList/ToolBar/index.tsx +114 -0
  197. package/src/features/FileManager/FileList/index.tsx +143 -0
  198. package/src/features/FileManager/FileList/useCheckTaskStatus.ts +27 -0
  199. package/src/features/FileManager/Header/FilesSearchBar.tsx +41 -0
  200. package/src/features/FileManager/Header/UploadFileButton.tsx +79 -0
  201. package/src/features/FileManager/Header/index.tsx +39 -0
  202. package/src/features/FileManager/UploadDock/Item.tsx +124 -0
  203. package/src/features/FileManager/UploadDock/index.tsx +183 -0
  204. package/src/features/FileManager/index.tsx +38 -0
  205. package/src/features/FileSidePanel/index.tsx +79 -0
  206. package/src/features/FileViewer/NotSupport/index.tsx +54 -0
  207. package/src/features/FileViewer/PDFViewer/HighlightLayer.tsx +81 -0
  208. package/src/features/FileViewer/PDFViewer/index.tsx +93 -0
  209. package/src/features/FileViewer/PDFViewer/style.ts +20 -0
  210. package/src/features/FileViewer/PDFViewer/useResizeObserver.ts +33 -0
  211. package/src/features/FileViewer/TXTViewer/index.tsx +41 -0
  212. package/src/features/FileViewer/index.tsx +45 -0
  213. package/src/features/KnowledgeBaseModal/AddFilesToKnowledgeBase/SelectForm.tsx +115 -0
  214. package/src/features/KnowledgeBaseModal/AddFilesToKnowledgeBase/index.tsx +43 -0
  215. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/Action.tsx +103 -0
  216. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/EditCustomPlugin.tsx +55 -0
  217. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/PluginTag.tsx +58 -0
  218. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/index.tsx +70 -0
  219. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/List.tsx +49 -0
  220. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Loading.tsx +13 -0
  221. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/index.tsx +39 -0
  222. package/src/features/KnowledgeBaseModal/CreateNew/CreateForm.tsx +73 -0
  223. package/src/features/KnowledgeBaseModal/CreateNew/index.tsx +35 -0
  224. package/src/features/KnowledgeBaseModal/index.ts +3 -0
  225. package/src/libs/langchain/loaders/pdf/index.ts +2 -2
  226. package/src/libs/trpc/async/asyncAuth.ts +24 -0
  227. package/src/libs/trpc/async/index.ts +10 -0
  228. package/src/libs/trpc/async/init.ts +11 -0
  229. package/src/libs/trpc/client/async.ts +14 -0
  230. package/src/libs/trpc/client/index.ts +1 -0
  231. package/src/libs/trpc/client/lambda.ts +9 -0
  232. package/src/libs/trpc/middleware/keyVaults.ts +18 -0
  233. package/src/libs/unstructured/__tests__/index.test.ts +0 -10
  234. package/src/libs/unstructured/index.ts +6 -11
  235. package/src/locales/default/chat.ts +47 -3
  236. package/src/locales/default/common.ts +1 -0
  237. package/src/locales/default/components.ts +2 -0
  238. package/src/locales/default/error.ts +6 -1
  239. package/src/locales/default/file.ts +92 -0
  240. package/src/locales/default/index.ts +4 -0
  241. package/src/locales/default/knowledgeBase.ts +31 -0
  242. package/src/locales/default/portal.ts +1 -0
  243. package/src/middleware.ts +3 -0
  244. package/src/server/asyncContext.ts +40 -0
  245. package/src/server/modules/ContentChunk/index.ts +135 -0
  246. package/src/server/modules/S3/index.ts +30 -5
  247. package/src/server/routers/async/caller.ts +27 -0
  248. package/src/server/routers/async/file.ts +247 -0
  249. package/src/server/routers/async/index.ts +12 -0
  250. package/src/server/routers/lambda/_template.ts +77 -0
  251. package/src/server/routers/lambda/agent.ts +159 -0
  252. package/src/server/routers/lambda/chunk.ts +189 -0
  253. package/src/server/routers/lambda/file.ts +129 -5
  254. package/src/server/routers/lambda/index.ts +6 -0
  255. package/src/server/routers/lambda/knowledgeBase.ts +79 -0
  256. package/src/server/routers/lambda/message.ts +6 -0
  257. package/src/server/routers/lambda/session.ts +0 -25
  258. package/src/server/routers/lambda/user.ts +5 -1
  259. package/src/server/services/chunk/index.ts +74 -0
  260. package/src/server/utils/files.ts +9 -0
  261. package/src/services/__tests__/chat.test.ts +18 -20
  262. package/src/services/__tests__/{upload.test.ts → upload_legacy.test.ts} +1 -1
  263. package/src/services/agent.ts +45 -0
  264. package/src/services/chat.ts +17 -15
  265. package/src/services/file/client.test.ts +1 -50
  266. package/src/services/file/client.ts +12 -25
  267. package/src/services/file/server.ts +25 -3
  268. package/src/services/file/type.ts +7 -4
  269. package/src/services/knowledgeBase.ts +34 -0
  270. package/src/services/message/client.test.ts +1 -1
  271. package/src/services/message/client.ts +29 -3
  272. package/src/services/message/index.ts +0 -2
  273. package/src/services/message/server.ts +9 -3
  274. package/src/services/message/type.ts +1 -13
  275. package/src/services/rag.ts +29 -0
  276. package/src/services/session/server.ts +1 -1
  277. package/src/services/upload.ts +89 -84
  278. package/src/services/upload_legacy.ts +104 -0
  279. package/src/services/user/client.ts +7 -2
  280. package/src/services/user/server.ts +6 -2
  281. package/src/services/user/type.ts +3 -2
  282. package/src/store/agent/slices/chat/action.ts +90 -18
  283. package/src/store/agent/slices/chat/initialState.ts +1 -0
  284. package/src/store/agent/slices/chat/selectors.ts +58 -0
  285. package/src/store/chat/slices/builtinTool/action.test.ts +2 -2
  286. package/src/store/chat/slices/builtinTool/action.ts +2 -2
  287. package/src/store/chat/slices/message/action.test.ts +2 -1
  288. package/src/store/chat/slices/message/action.ts +102 -26
  289. package/src/store/chat/slices/message/actions/rag.ts +148 -0
  290. package/src/store/chat/slices/message/initialState.ts +7 -0
  291. package/src/store/chat/slices/message/reducer.ts +6 -2
  292. package/src/store/chat/slices/message/selectors.ts +38 -3
  293. package/src/store/chat/slices/plugin/action.ts +8 -2
  294. package/src/store/chat/slices/portal/action.ts +8 -0
  295. package/src/store/chat/slices/portal/initialState.ts +3 -0
  296. package/src/store/chat/slices/portal/selectors.ts +8 -2
  297. package/src/store/file/initialState.ts +5 -1
  298. package/src/store/file/reducers/uploadFileList.ts +133 -0
  299. package/src/store/file/selectors.ts +3 -0
  300. package/src/store/file/slices/chat/action.test.ts +90 -90
  301. package/src/store/file/slices/chat/action.ts +164 -109
  302. package/src/store/file/slices/chat/initialState.ts +7 -2
  303. package/src/store/file/slices/chat/selectors.test.ts +84 -61
  304. package/src/store/file/slices/chat/selectors.ts +22 -32
  305. package/src/store/file/slices/chunk/action.ts +36 -0
  306. package/src/store/file/slices/chunk/index.ts +3 -0
  307. package/src/store/file/slices/chunk/initialState.ts +15 -0
  308. package/src/store/file/slices/chunk/selectors.ts +10 -0
  309. package/src/store/file/slices/fileManager/action.ts +187 -0
  310. package/src/store/file/slices/fileManager/index.ts +3 -0
  311. package/src/store/file/slices/fileManager/initialState.ts +18 -0
  312. package/src/store/file/slices/fileManager/selectors.ts +58 -0
  313. package/src/store/file/slices/tts/action.test.ts +1 -1
  314. package/src/store/file/slices/tts/action.ts +2 -2
  315. package/src/store/file/slices/upload/action.ts +164 -0
  316. package/src/store/file/store.ts +12 -1
  317. package/src/store/knowledgeBase/index.ts +2 -0
  318. package/src/store/knowledgeBase/initialState.ts +7 -0
  319. package/src/store/knowledgeBase/selectors.ts +1 -0
  320. package/src/store/knowledgeBase/slices/content/action.ts +27 -0
  321. package/src/store/knowledgeBase/slices/content/index.ts +1 -0
  322. package/src/store/knowledgeBase/slices/crud/action.ts +78 -0
  323. package/src/store/knowledgeBase/slices/crud/index.ts +3 -0
  324. package/src/store/knowledgeBase/slices/crud/initialState.ts +12 -0
  325. package/src/store/knowledgeBase/slices/crud/selectors.ts +7 -0
  326. package/src/store/knowledgeBase/store.ts +30 -0
  327. package/src/store/serverConfig/selectors.test.ts +1 -1
  328. package/src/store/user/slices/preference/selectors.ts +8 -0
  329. package/src/store/user/slices/settings/selectors/systemAgent.ts +2 -0
  330. package/src/tools/dalle/Render/Item/ImageFileItem.tsx +3 -23
  331. package/src/types/agent/index.ts +9 -0
  332. package/src/types/asyncTask.ts +31 -0
  333. package/src/types/chunk/document.ts +9 -0
  334. package/src/types/chunk/index.ts +52 -0
  335. package/src/types/files/index.ts +35 -0
  336. package/src/types/files/list.ts +44 -0
  337. package/src/types/files/upload.ts +91 -0
  338. package/src/types/knowledgeBase/index.ts +45 -0
  339. package/src/types/message/index.ts +54 -5
  340. package/src/types/rag.ts +16 -0
  341. package/src/utils/filter.test.ts +2 -0
  342. package/src/utils/server/auth.ts +23 -0
  343. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/LocalFiles.tsx +0 -46
  344. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files.tsx +0 -19
  345. package/src/components/FileList/EditableFileList.tsx +0 -47
  346. package/src/components/FileList/index.ts +0 -2
  347. package/src/components/FileList/type.tsx +0 -7
  348. package/src/database/server/schemas/lobechat/chat.ts +0 -331
  349. package/src/features/ChatInput/ActionBar/FileUpload.tsx +0 -69
  350. package/src/features/ChatInput/useChatInput.ts +0 -45
  351. package/src/features/FileList/EditableFileList.tsx +0 -31
  352. package/src/features/FileList/FileListPreviewer.tsx +0 -17
  353. package/src/features/FileList/index.tsx +0 -2
  354. 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', url: 'file-url' }];
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 { CreateMessageParams, messageService } from '@/services/message';
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 { ChatMessage, ChatMessageError, MessageToolCall } from '@/types/message';
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?: { id: string; url: string }[];
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 isNoFile = !fileIdList || fileIdList.length === 0;
281
+ const hasFile = !!fileIdList && fileIdList.length > 0;
265
282
 
266
283
  // if message is empty or no files, then stop
267
- if (!message && isNoFile) return;
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
- await internal_coreProcessMessage(messages, id, { isWelcomeQuestion });
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
- // if autoCreateTopic is false, then stop
355
- if (!agentConfig.enableAutoCreateTopic) return;
377
+ const summaryTitle = async () => {
378
+ // if autoCreateTopic is false, then stop
379
+ if (!agentConfig.enableAutoCreateTopic) return;
356
380
 
357
- // check activeTopic and then auto update topic title
358
- if (newTopicId) {
359
- const chats = chatSelectors.currentChats(get());
360
- await get().summaryTopicTitle(newTopicId, chats);
361
- return;
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
- const topic = topicSelectors.currentActiveTopic(get());
388
+ const topic = topicSelectors.currentActiveTopic(get());
365
389
 
366
- if (topic && !topic.title) {
367
- const chats = chatSelectors.currentChats(get());
368
- await get().summaryTopicTitle(topic.id, chats);
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 (messages, userMessageId, params) => {
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
- // 1. Add an empty message to place the AI response
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
- // 2. fetch the AI response
541
+ // 3. fetch the AI response
469
542
  const { isFunctionCall } = await internal_fetchAIChatMessage(messages, assistantId, params);
470
543
 
471
- // 3. if it's the function call message, trigger the function method
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, { traceId });
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 { CreateMessageParams } from '@/services/message';
5
- import { ChatMessage, ChatPluginPayload, ChatToolPayload } from '@/types/message';
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 { CreateMessageParams, messageService } from '@/services/message';
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 { ChatMessage, ChatMessageError, ChatToolPayload, MessageToolCall } from '@/types/message';
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);
@@ -1,4 +1,7 @@
1
1
  export interface ChatPortalState {
2
+ portalFile?: {
3
+ fileId: string;
4
+ };
2
5
  portalToolMessage?: { id: string; identifier: string };
3
6
  showPortal: boolean;
4
7
  }
@@ -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
- showArtifactUI: (state: ChatStoreState) => !!state.portalToolMessage,
16
+ previewFileId,
17
+ showArtifactUI,
18
+ showFilePreview,
13
19
  showPortal,
14
- toolUIIdentifier: (state: ChatStoreState) => state.portalToolMessage?.identifier,
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
  };