@lobehub/chat 1.11.9 → 1.12.1

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 (356) hide show
  1. package/.github/workflows/release.yml +2 -1
  2. package/.github/workflows/test.yml +2 -1
  3. package/CHANGELOG.md +50 -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/0007_fix_embedding_table.sql +18 -0
  128. package/src/database/server/migrations/meta/0005_snapshot.json +2119 -0
  129. package/src/database/server/migrations/meta/0006_snapshot.json +3006 -0
  130. package/src/database/server/migrations/meta/0007_snapshot.json +3012 -0
  131. package/src/database/server/migrations/meta/_journal.json +21 -0
  132. package/src/database/server/models/__tests__/_test_template.ts +155 -0
  133. package/src/database/server/models/__tests__/agent.test.ts +226 -0
  134. package/src/database/server/models/__tests__/asyncTask.test.ts +176 -0
  135. package/src/database/server/models/__tests__/chunk.test.ts +336 -0
  136. package/src/database/server/models/__tests__/file.test.ts +317 -29
  137. package/src/database/server/models/__tests__/fixtures/embedding.ts +568 -0
  138. package/src/database/server/models/__tests__/knowledgeBase.test.ts +132 -0
  139. package/src/database/server/models/__tests__/message.test.ts +7 -4
  140. package/src/database/server/models/_template.ts +10 -1
  141. package/src/database/server/models/agent.ts +165 -0
  142. package/src/database/server/models/asyncTask.ts +96 -0
  143. package/src/database/server/models/chunk.ts +203 -0
  144. package/src/database/server/models/embedding.ts +50 -0
  145. package/src/database/server/models/file.ts +231 -12
  146. package/src/database/server/models/knowledgeBase.ts +94 -0
  147. package/src/database/server/models/message.ts +156 -30
  148. package/src/database/server/models/user.ts +12 -1
  149. package/src/database/server/schemas/lobechat/agent.ts +93 -0
  150. package/src/database/server/schemas/lobechat/discover.ts +1 -1
  151. package/src/database/server/schemas/lobechat/file.ts +118 -1
  152. package/src/database/server/schemas/lobechat/index.ts +5 -1
  153. package/src/database/server/schemas/lobechat/message.ts +169 -0
  154. package/src/database/server/schemas/lobechat/rag.ts +53 -0
  155. package/src/database/server/schemas/lobechat/relations.ts +68 -48
  156. package/src/database/server/schemas/lobechat/session.ts +77 -0
  157. package/src/database/server/schemas/lobechat/topic.ts +32 -0
  158. package/src/database/server/schemas/lobechat/user.ts +40 -25
  159. package/src/database/server/utils/idGenerator.ts +1 -0
  160. package/src/features/ChatInput/ActionBar/Clear.tsx +1 -1
  161. package/src/features/ChatInput/ActionBar/Knowledge/Dropdown.tsx +160 -0
  162. package/src/features/ChatInput/ActionBar/Knowledge/ListItem.tsx +52 -0
  163. package/src/features/ChatInput/ActionBar/Knowledge/index.tsx +54 -0
  164. package/src/features/ChatInput/ActionBar/Tools/index.tsx +1 -1
  165. package/src/features/ChatInput/ActionBar/Upload/ClientMode.tsx +52 -0
  166. package/src/features/ChatInput/ActionBar/Upload/ServerMode.tsx +104 -0
  167. package/src/features/ChatInput/ActionBar/Upload/index.tsx +8 -0
  168. package/src/features/ChatInput/ActionBar/config.ts +14 -5
  169. package/src/features/ChatInput/useSend.ts +16 -7
  170. package/src/features/Conversation/Messages/Assistant/FileChunks/Item/index.tsx +51 -0
  171. package/src/features/Conversation/Messages/Assistant/FileChunks/Item/style.ts +38 -0
  172. package/src/features/Conversation/Messages/Assistant/FileChunks/index.tsx +76 -0
  173. package/src/features/Conversation/Messages/Assistant/index.tsx +13 -4
  174. package/src/features/Conversation/Messages/Default.tsx +4 -0
  175. package/src/features/Conversation/Messages/User/BelowMessage.tsx +78 -0
  176. package/src/features/Conversation/Messages/User/FileListViewer/Item.tsx +53 -0
  177. package/src/features/Conversation/Messages/User/FileListViewer/index.tsx +21 -0
  178. package/src/{components/FileList/FileListViewer.tsx → features/Conversation/Messages/User/ImageFileListViewer.tsx} +10 -2
  179. package/src/features/Conversation/Messages/{User.tsx → User/index.tsx} +11 -2
  180. package/src/features/Conversation/Messages/index.ts +8 -3
  181. package/src/features/Conversation/components/ChatItem/index.tsx +33 -10
  182. package/src/features/Conversation/components/InboxWelcome/QuestionSuggest.tsx +1 -1
  183. package/src/features/Conversation/types/index.tsx +1 -0
  184. package/src/features/FileManager/ChunkDrawer/ChunkList/ChunkItem.tsx +61 -0
  185. package/src/features/FileManager/ChunkDrawer/ChunkList/index.tsx +42 -0
  186. package/src/features/FileManager/ChunkDrawer/Content.tsx +38 -0
  187. package/src/features/FileManager/ChunkDrawer/Loading/index.tsx +16 -0
  188. package/src/features/FileManager/ChunkDrawer/SimilaritySearchList/Item.tsx +62 -0
  189. package/src/features/FileManager/ChunkDrawer/SimilaritySearchList/index.tsx +31 -0
  190. package/src/features/FileManager/ChunkDrawer/index.tsx +48 -0
  191. package/src/features/FileManager/FileList/EmptyStatus.tsx +153 -0
  192. package/src/features/FileManager/FileList/FileListItem/ChunkTag.tsx +35 -0
  193. package/src/features/FileManager/FileList/FileListItem/DropdownMenu.tsx +150 -0
  194. package/src/features/FileManager/FileList/FileListItem/index.tsx +211 -0
  195. package/src/features/FileManager/FileList/FileSkeleton.tsx +25 -0
  196. package/src/features/FileManager/FileList/ToolBar/Config.tsx +28 -0
  197. package/src/features/FileManager/FileList/ToolBar/MultiSelectActions.tsx +152 -0
  198. package/src/features/FileManager/FileList/ToolBar/index.tsx +114 -0
  199. package/src/features/FileManager/FileList/index.tsx +143 -0
  200. package/src/features/FileManager/FileList/useCheckTaskStatus.ts +27 -0
  201. package/src/features/FileManager/Header/FilesSearchBar.tsx +41 -0
  202. package/src/features/FileManager/Header/UploadFileButton.tsx +79 -0
  203. package/src/features/FileManager/Header/index.tsx +39 -0
  204. package/src/features/FileManager/UploadDock/Item.tsx +124 -0
  205. package/src/features/FileManager/UploadDock/index.tsx +183 -0
  206. package/src/features/FileManager/index.tsx +38 -0
  207. package/src/features/FileSidePanel/index.tsx +79 -0
  208. package/src/features/FileViewer/NotSupport/index.tsx +54 -0
  209. package/src/features/FileViewer/PDFViewer/HighlightLayer.tsx +81 -0
  210. package/src/features/FileViewer/PDFViewer/index.tsx +93 -0
  211. package/src/features/FileViewer/PDFViewer/style.ts +20 -0
  212. package/src/features/FileViewer/PDFViewer/useResizeObserver.ts +33 -0
  213. package/src/features/FileViewer/TXTViewer/index.tsx +41 -0
  214. package/src/features/FileViewer/index.tsx +45 -0
  215. package/src/features/KnowledgeBaseModal/AddFilesToKnowledgeBase/SelectForm.tsx +115 -0
  216. package/src/features/KnowledgeBaseModal/AddFilesToKnowledgeBase/index.tsx +43 -0
  217. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/Action.tsx +103 -0
  218. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/EditCustomPlugin.tsx +55 -0
  219. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/PluginTag.tsx +58 -0
  220. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/index.tsx +70 -0
  221. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/List.tsx +49 -0
  222. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Loading.tsx +13 -0
  223. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/index.tsx +39 -0
  224. package/src/features/KnowledgeBaseModal/CreateNew/CreateForm.tsx +73 -0
  225. package/src/features/KnowledgeBaseModal/CreateNew/index.tsx +35 -0
  226. package/src/features/KnowledgeBaseModal/index.ts +3 -0
  227. package/src/libs/langchain/loaders/pdf/index.ts +2 -2
  228. package/src/libs/trpc/async/asyncAuth.ts +24 -0
  229. package/src/libs/trpc/async/index.ts +10 -0
  230. package/src/libs/trpc/async/init.ts +11 -0
  231. package/src/libs/trpc/client/async.ts +14 -0
  232. package/src/libs/trpc/client/index.ts +1 -0
  233. package/src/libs/trpc/client/lambda.ts +9 -0
  234. package/src/libs/trpc/middleware/keyVaults.ts +18 -0
  235. package/src/libs/unstructured/__tests__/index.test.ts +0 -10
  236. package/src/libs/unstructured/index.ts +6 -11
  237. package/src/locales/default/chat.ts +47 -3
  238. package/src/locales/default/common.ts +1 -0
  239. package/src/locales/default/components.ts +2 -0
  240. package/src/locales/default/error.ts +6 -1
  241. package/src/locales/default/file.ts +92 -0
  242. package/src/locales/default/index.ts +4 -0
  243. package/src/locales/default/knowledgeBase.ts +31 -0
  244. package/src/locales/default/portal.ts +1 -0
  245. package/src/middleware.ts +3 -0
  246. package/src/server/asyncContext.ts +40 -0
  247. package/src/server/modules/ContentChunk/index.ts +135 -0
  248. package/src/server/modules/S3/index.ts +30 -5
  249. package/src/server/routers/async/caller.ts +27 -0
  250. package/src/server/routers/async/file.ts +247 -0
  251. package/src/server/routers/async/index.ts +12 -0
  252. package/src/server/routers/lambda/_template.ts +77 -0
  253. package/src/server/routers/lambda/agent.ts +159 -0
  254. package/src/server/routers/lambda/chunk.ts +189 -0
  255. package/src/server/routers/lambda/file.ts +129 -5
  256. package/src/server/routers/lambda/index.ts +6 -0
  257. package/src/server/routers/lambda/knowledgeBase.ts +79 -0
  258. package/src/server/routers/lambda/message.ts +6 -0
  259. package/src/server/routers/lambda/session.ts +0 -25
  260. package/src/server/routers/lambda/user.ts +5 -1
  261. package/src/server/services/chunk/index.ts +74 -0
  262. package/src/server/utils/files.ts +9 -0
  263. package/src/services/__tests__/chat.test.ts +18 -20
  264. package/src/services/__tests__/{upload.test.ts → upload_legacy.test.ts} +1 -1
  265. package/src/services/agent.ts +45 -0
  266. package/src/services/chat.ts +17 -15
  267. package/src/services/file/client.test.ts +1 -50
  268. package/src/services/file/client.ts +12 -25
  269. package/src/services/file/server.ts +25 -3
  270. package/src/services/file/type.ts +7 -4
  271. package/src/services/knowledgeBase.ts +34 -0
  272. package/src/services/message/client.test.ts +1 -1
  273. package/src/services/message/client.ts +29 -3
  274. package/src/services/message/index.ts +0 -2
  275. package/src/services/message/server.ts +9 -3
  276. package/src/services/message/type.ts +1 -13
  277. package/src/services/rag.ts +29 -0
  278. package/src/services/session/server.ts +1 -1
  279. package/src/services/upload.ts +89 -84
  280. package/src/services/upload_legacy.ts +104 -0
  281. package/src/services/user/client.ts +7 -2
  282. package/src/services/user/server.ts +6 -2
  283. package/src/services/user/type.ts +3 -2
  284. package/src/store/agent/slices/chat/action.ts +90 -18
  285. package/src/store/agent/slices/chat/initialState.ts +1 -0
  286. package/src/store/agent/slices/chat/selectors.ts +58 -0
  287. package/src/store/chat/slices/builtinTool/action.test.ts +2 -2
  288. package/src/store/chat/slices/builtinTool/action.ts +2 -2
  289. package/src/store/chat/slices/message/action.test.ts +2 -1
  290. package/src/store/chat/slices/message/action.ts +102 -26
  291. package/src/store/chat/slices/message/actions/rag.ts +148 -0
  292. package/src/store/chat/slices/message/initialState.ts +7 -0
  293. package/src/store/chat/slices/message/reducer.ts +6 -2
  294. package/src/store/chat/slices/message/selectors.ts +38 -3
  295. package/src/store/chat/slices/plugin/action.ts +8 -2
  296. package/src/store/chat/slices/portal/action.ts +8 -0
  297. package/src/store/chat/slices/portal/initialState.ts +3 -0
  298. package/src/store/chat/slices/portal/selectors.ts +8 -2
  299. package/src/store/file/initialState.ts +5 -1
  300. package/src/store/file/reducers/uploadFileList.ts +133 -0
  301. package/src/store/file/selectors.ts +3 -0
  302. package/src/store/file/slices/chat/action.test.ts +90 -90
  303. package/src/store/file/slices/chat/action.ts +164 -109
  304. package/src/store/file/slices/chat/initialState.ts +7 -2
  305. package/src/store/file/slices/chat/selectors.test.ts +84 -61
  306. package/src/store/file/slices/chat/selectors.ts +22 -32
  307. package/src/store/file/slices/chunk/action.ts +36 -0
  308. package/src/store/file/slices/chunk/index.ts +3 -0
  309. package/src/store/file/slices/chunk/initialState.ts +15 -0
  310. package/src/store/file/slices/chunk/selectors.ts +10 -0
  311. package/src/store/file/slices/fileManager/action.ts +187 -0
  312. package/src/store/file/slices/fileManager/index.ts +3 -0
  313. package/src/store/file/slices/fileManager/initialState.ts +18 -0
  314. package/src/store/file/slices/fileManager/selectors.ts +58 -0
  315. package/src/store/file/slices/tts/action.test.ts +1 -1
  316. package/src/store/file/slices/tts/action.ts +2 -2
  317. package/src/store/file/slices/upload/action.ts +164 -0
  318. package/src/store/file/store.ts +12 -1
  319. package/src/store/knowledgeBase/index.ts +2 -0
  320. package/src/store/knowledgeBase/initialState.ts +7 -0
  321. package/src/store/knowledgeBase/selectors.ts +1 -0
  322. package/src/store/knowledgeBase/slices/content/action.ts +27 -0
  323. package/src/store/knowledgeBase/slices/content/index.ts +1 -0
  324. package/src/store/knowledgeBase/slices/crud/action.ts +78 -0
  325. package/src/store/knowledgeBase/slices/crud/index.ts +3 -0
  326. package/src/store/knowledgeBase/slices/crud/initialState.ts +12 -0
  327. package/src/store/knowledgeBase/slices/crud/selectors.ts +7 -0
  328. package/src/store/knowledgeBase/store.ts +30 -0
  329. package/src/store/serverConfig/selectors.test.ts +1 -1
  330. package/src/store/user/slices/preference/selectors.ts +8 -0
  331. package/src/store/user/slices/settings/selectors/systemAgent.ts +2 -0
  332. package/src/tools/dalle/Render/Item/ImageFileItem.tsx +3 -23
  333. package/src/types/agent/index.ts +9 -0
  334. package/src/types/asyncTask.ts +31 -0
  335. package/src/types/chunk/document.ts +9 -0
  336. package/src/types/chunk/index.ts +52 -0
  337. package/src/types/files/index.ts +35 -0
  338. package/src/types/files/list.ts +44 -0
  339. package/src/types/files/upload.ts +91 -0
  340. package/src/types/knowledgeBase/index.ts +45 -0
  341. package/src/types/message/index.ts +54 -5
  342. package/src/types/rag.ts +16 -0
  343. package/src/utils/filter.test.ts +2 -0
  344. package/src/utils/server/auth.ts +23 -0
  345. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/LocalFiles.tsx +0 -46
  346. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files.tsx +0 -19
  347. package/src/components/FileList/EditableFileList.tsx +0 -47
  348. package/src/components/FileList/index.ts +0 -2
  349. package/src/components/FileList/type.tsx +0 -7
  350. package/src/database/server/schemas/lobechat/chat.ts +0 -331
  351. package/src/features/ChatInput/ActionBar/FileUpload.tsx +0 -69
  352. package/src/features/ChatInput/useChatInput.ts +0 -45
  353. package/src/features/FileList/EditableFileList.tsx +0 -31
  354. package/src/features/FileList/FileListPreviewer.tsx +0 -17
  355. package/src/features/FileList/index.tsx +0 -2
  356. package/src/types/files.ts +0 -42
@@ -8,7 +8,7 @@ import { SessionModel } from '@/database/server/models/session';
8
8
  import { UserModel, UserNotFoundError } from '@/database/server/models/user';
9
9
  import { authedProcedure, router } from '@/libs/trpc';
10
10
  import { UserService } from '@/server/services/user';
11
- import { UserInitializationState, UserPreference } from '@/types/user';
11
+ import { UserGuideSchema, UserInitializationState, UserPreference } from '@/types/user';
12
12
 
13
13
  const userProcedure = authedProcedure.use(async (opts) => {
14
14
  return opts.next({
@@ -84,6 +84,10 @@ export const userRouter = router({
84
84
  return ctx.userModel.deleteSetting(ctx.userId);
85
85
  }),
86
86
 
87
+ updateGuide: userProcedure.input(UserGuideSchema).mutation(async ({ ctx, input }) => {
88
+ return ctx.userModel.updateGuide(ctx.userId, input);
89
+ }),
90
+
87
91
  updatePreference: userProcedure.input(z.any()).mutation(async ({ ctx, input }) => {
88
92
  return ctx.userModel.updatePreference(ctx.userId, input);
89
93
  }),
@@ -0,0 +1,74 @@
1
+ import { JWTPayload } from '@/const/auth';
2
+ import { AsyncTaskModel } from '@/database/server/models/asyncTask';
3
+ import { FileModel } from '@/database/server/models/file';
4
+ import { ChunkContentParams, ContentChunk } from '@/server/modules/ContentChunk';
5
+ import { createAsyncServerClient } from '@/server/routers/async';
6
+ import { AsyncTaskStatus, AsyncTaskType } from '@/types/asyncTask';
7
+
8
+ export class ChunkService {
9
+ private userId: string;
10
+ private chunkClient: ContentChunk;
11
+ private fileModel: FileModel;
12
+ private asyncTaskModel: AsyncTaskModel;
13
+
14
+ constructor(userId: string) {
15
+ this.userId = userId;
16
+
17
+ this.chunkClient = new ContentChunk();
18
+
19
+ this.fileModel = new FileModel(userId);
20
+ this.asyncTaskModel = new AsyncTaskModel(userId);
21
+ }
22
+
23
+ async chunkContent(params: ChunkContentParams) {
24
+ return this.chunkClient.chunkContent(params);
25
+ }
26
+
27
+ async asyncEmbeddingFileChunks(fileId: string, payload: JWTPayload) {
28
+ const result = await this.fileModel.findById(fileId);
29
+
30
+ if (!result) return;
31
+
32
+ // 1. create a asyncTaskId
33
+ const asyncTaskId = await this.asyncTaskModel.create({
34
+ status: AsyncTaskStatus.Pending,
35
+ type: AsyncTaskType.Embedding,
36
+ });
37
+
38
+ await this.fileModel.update(fileId, { embeddingTaskId: asyncTaskId });
39
+
40
+ const asyncCaller = await createAsyncServerClient(this.userId, payload);
41
+
42
+ // trigger embedding task asynchronously
43
+ await asyncCaller.file.embeddingChunks.mutate({ fileId, taskId: asyncTaskId });
44
+
45
+ return asyncTaskId;
46
+ }
47
+
48
+ /**
49
+ * parse file to chunks with async task
50
+ */
51
+ async asyncParseFileToChunks(fileId: string, payload: JWTPayload, skipExist?: boolean) {
52
+ const result = await this.fileModel.findById(fileId);
53
+
54
+ if (!result) return;
55
+
56
+ // skip if already exist chunk tasks
57
+ if (skipExist && result.chunkTaskId) return;
58
+
59
+ // 1. create a asyncTaskId
60
+ const asyncTaskId = await this.asyncTaskModel.create({
61
+ status: AsyncTaskStatus.Processing,
62
+ type: AsyncTaskType.Chunking,
63
+ });
64
+
65
+ await this.fileModel.update(fileId, { chunkTaskId: asyncTaskId });
66
+
67
+ const asyncCaller = await createAsyncServerClient(this.userId, payload);
68
+
69
+ // trigger parse file task asynchronously
70
+ asyncCaller.file.parseFileToChunks.mutate({ fileId: fileId, taskId: asyncTaskId });
71
+
72
+ return asyncTaskId;
73
+ }
74
+ }
@@ -0,0 +1,9 @@
1
+ import urlJoin from 'url-join';
2
+
3
+ import { fileEnv } from '@/config/file';
4
+
5
+ export const getFullFileUrl = (url?: string | null) => {
6
+ if (!url) return '';
7
+
8
+ return urlJoin(fileEnv.NEXT_PUBLIC_S3_DOMAIN!, url);
9
+ };
@@ -129,25 +129,20 @@ describe('ChatService', () => {
129
129
  describe('should handle content correctly for vision models', () => {
130
130
  it('should include image content when with vision model', async () => {
131
131
  const messages = [
132
- { content: 'Hello', role: 'user', files: ['file1'] }, // Message with files
133
- { content: 'Hi', role: 'tool', plugin: { identifier: 'plugin1', apiName: 'api1' } }, // Message with tool role
134
- { content: 'Hey', role: 'assistant' }, // Regular user message
135
- ] as ChatMessage[];
136
-
137
- // Mock file store state to return a specific image URL or Base64 for the given files
138
- act(() => {
139
- useFileStore.setState({
140
- imagesMap: {
141
- file1: {
132
+ {
133
+ content: 'Hello',
134
+ role: 'user',
135
+ imageList: [
136
+ {
142
137
  id: 'file1',
143
- name: 'abc.png',
144
- saveMode: 'url',
145
- fileType: 'image/png',
146
138
  url: 'http://example.com/image.jpg',
139
+ alt: 'abc.png',
147
140
  },
148
- },
149
- });
150
- });
141
+ ],
142
+ }, // Message with files
143
+ { content: 'Hi', role: 'tool', plugin: { identifier: 'plugin1', apiName: 'api1' } }, // Message with tool role
144
+ { content: 'Hey', role: 'assistant' }, // Regular user message
145
+ ] as ChatMessage[];
151
146
 
152
147
  const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
153
148
  await chatService.createAssistantMessage({
@@ -615,7 +610,7 @@ Get data from users`,
615
610
  const abortController = new AbortController();
616
611
  const trace = {};
617
612
 
618
- const result = await chatService.fetchPresetTaskResult({
613
+ await chatService.fetchPresetTaskResult({
619
614
  params,
620
615
  onMessageHandle,
621
616
  onFinish,
@@ -625,9 +620,12 @@ Get data from users`,
625
620
  trace,
626
621
  });
627
622
 
628
- expect(result).toBe('AI response');
629
-
630
- expect(onFinish).toHaveBeenCalled();
623
+ expect(onFinish).toHaveBeenCalledWith('AI response', {
624
+ type: 'done',
625
+ observationId: null,
626
+ toolCalls: undefined,
627
+ traceId: null,
628
+ });
631
629
  expect(onError).not.toHaveBeenCalled();
632
630
  expect(onMessageHandle).toHaveBeenCalled();
633
631
  expect(onLoadingChange).toHaveBeenCalledWith(false); // 确认加载状态已经被设置为 false
@@ -6,7 +6,7 @@ import { API_ENDPOINTS } from '@/services/_url';
6
6
  import { serverConfigSelectors } from '@/store/serverConfig/selectors';
7
7
  import { createServerConfigStore } from '@/store/serverConfig/store';
8
8
 
9
- import { uploadService } from '../upload';
9
+ import { legacyUploadService as uploadService } from '../upload_legacy';
10
10
 
11
11
  vi.mock('@/store/serverConfig/selectors');
12
12
  vi.mock('@/libs/trpc/client', () => {
@@ -0,0 +1,45 @@
1
+ import { lambdaClient } from '@/libs/trpc/client';
2
+
3
+ class AgentService {
4
+ async createAgentKnowledgeBase(agentId: string, knowledgeBaseId: string, enabled?: boolean) {
5
+ return await lambdaClient.agent.createAgentKnowledgeBase.mutate({
6
+ agentId,
7
+ enabled,
8
+ knowledgeBaseId,
9
+ });
10
+ }
11
+
12
+ async deleteAgentKnowledgeBase(agentId: string, knowledgeBaseId: string) {
13
+ return await lambdaClient.agent.deleteAgentKnowledgeBase.mutate({ agentId, knowledgeBaseId });
14
+ }
15
+
16
+ async toggleKnowledgeBase(agentId: string, knowledgeBaseId: string, enabled?: boolean) {
17
+ return await lambdaClient.agent.toggleKnowledgeBase.mutate({
18
+ agentId,
19
+ enabled,
20
+ knowledgeBaseId,
21
+ });
22
+ }
23
+
24
+ async createAgentFiles(agentId: string, fileIds: string[], enabled?: boolean) {
25
+ return await lambdaClient.agent.createAgentFiles.mutate({ agentId, enabled, fileIds });
26
+ }
27
+
28
+ async deleteAgentFile(agentId: string, fileId: string) {
29
+ return await lambdaClient.agent.deleteAgentFile.mutate({ agentId, fileId });
30
+ }
31
+
32
+ async toggleFile(agentId: string, fileId: string, enabled?: boolean) {
33
+ return await lambdaClient.agent.toggleFile.mutate({
34
+ agentId,
35
+ enabled,
36
+ fileId,
37
+ });
38
+ }
39
+
40
+ async getFilesAndKnowledgeBases(agentId: string) {
41
+ return await lambdaClient.agent.getKnowledgeBasesAndFiles.query({ agentId });
42
+ }
43
+ }
44
+
45
+ export const agentService = new AgentService();
@@ -8,7 +8,6 @@ import { INBOX_SESSION_ID } from '@/const/session';
8
8
  import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
9
9
  import { TracePayload, TraceTagMap } from '@/const/trace';
10
10
  import { AgentRuntime, ChatCompletionErrorPayload, ModelProvider } from '@/libs/agent-runtime';
11
- import { filesSelectors, useFileStore } from '@/store/file';
12
11
  import { useSessionStore } from '@/store/session';
13
12
  import { sessionMetaSelectors } from '@/store/session/selectors';
14
13
  import { useToolStore } from '@/store/tool';
@@ -367,23 +366,26 @@ class ChatService {
367
366
  return;
368
367
  }
369
368
  onError?.(error, errorContent);
369
+ console.error(error);
370
370
  };
371
371
 
372
372
  onLoadingChange?.(true);
373
373
 
374
- const data = await this.getChatCompletion(params, {
375
- onErrorHandle: (error) => {
376
- errorHandle(new Error(error.message), error);
377
- },
378
- onFinish,
379
- onMessageHandle,
380
- signal: abortController?.signal,
381
- trace: this.mapTrace(trace, TraceTagMap.SystemChain),
382
- }).catch(errorHandle);
374
+ try {
375
+ await this.getChatCompletion(params, {
376
+ onErrorHandle: (error) => {
377
+ errorHandle(new Error(error.message), error);
378
+ },
379
+ onFinish,
380
+ onMessageHandle,
381
+ signal: abortController?.signal,
382
+ trace: this.mapTrace(trace, TraceTagMap.SystemChain),
383
+ });
383
384
 
384
- onLoadingChange?.(false);
385
-
386
- return await data?.text();
385
+ onLoadingChange?.(false);
386
+ } catch (e) {
387
+ errorHandle(e as Error);
388
+ }
387
389
  };
388
390
 
389
391
  private processMessages = (
@@ -402,9 +404,9 @@ class ChatService {
402
404
  // for the models with visual ability, add image url to content
403
405
  // refs: https://platform.openai.com/docs/guides/vision/quick-start
404
406
  const getContent = (m: ChatMessage) => {
405
- if (!m.files) return m.content;
407
+ if (!m.imageList) return m.content;
406
408
 
407
- const imageList = filesSelectors.getImageUrlOrBase64ByList(m.files)(useFileStore.getState());
409
+ const imageList = m.imageList;
408
410
 
409
411
  if (imageList.length === 0) return m.content;
410
412
 
@@ -58,7 +58,7 @@ describe('FileService', () => {
58
58
  const result = await fileService.createFile(localFile);
59
59
 
60
60
  expect(FileModel.create).toHaveBeenCalledWith(localFile);
61
- expect(result).toEqual(localFile);
61
+ expect(result).toEqual({ url: 'data:image/png;base64,AA==' });
62
62
  });
63
63
 
64
64
  it('removeFile should delete the file from the database', async () => {
@@ -99,55 +99,6 @@ describe('FileService', () => {
99
99
  });
100
100
  });
101
101
 
102
- it('should retrieve and convert URL file info to FilePreview when enableServer is true', async () => {
103
- const fileId = '1';
104
- const fileData: DB_File = {
105
- name: 'test',
106
- fileType: 'image/png',
107
- saveMode: 'url',
108
- metadata: {
109
- filename: 'test.png',
110
- },
111
- size: 1,
112
- url: '/test.png',
113
- };
114
-
115
- (FileModel.findById as Mock).mockResolvedValue(fileData);
116
- vi.spyOn(serverConfigSelectors, 'enableUploadFileToServer').mockReturnValue(true);
117
- s3Domain = 'https://example.com';
118
-
119
- const result = await fileService.getFile(fileId);
120
-
121
- expect(FileModel.findById).toHaveBeenCalledWith(fileId);
122
- expect(result).toEqual({
123
- fileType: 'image/png',
124
- id: '1',
125
- name: 'test.png',
126
- saveMode: 'url',
127
- url: 'https://example.com/test.png',
128
- });
129
- });
130
-
131
- it('should throw an error when enableServer is true but NEXT_PUBLIC_S3_DOMAIN is not set', async () => {
132
- const fileId = '1';
133
- const fileData: DB_File = {
134
- name: 'test',
135
- fileType: 'image/png',
136
- saveMode: 'url',
137
- size: 1,
138
- url: '/test.png',
139
- };
140
-
141
- (FileModel.findById as Mock).mockResolvedValue(fileData);
142
- vi.spyOn(serverConfigSelectors, 'enableUploadFileToServer').mockReturnValue(true);
143
-
144
- const getFilePromise = fileService.getFile(fileId);
145
-
146
- await expect(getFilePromise).rejects.toThrow(
147
- 'fileEnv.NEXT_PUBLIC_S3_DOMAIN is not set while enable server upload',
148
- );
149
- });
150
-
151
102
  it('should throw an error when the file is not found', async () => {
152
103
  const fileId = 'non-existent';
153
104
  (FileModel.findById as Mock).mockResolvedValue(null);
@@ -1,9 +1,5 @@
1
- import urlJoin from 'url-join';
2
-
3
- import { fileEnv } from '@/config/file';
4
1
  import { FileModel } from '@/database/client/models/file';
5
2
  import { DB_File } from '@/database/client/schemas/files';
6
- import { serverConfigSelectors } from '@/store/serverConfig/selectors';
7
3
  import { FilePreview } from '@/types/files';
8
4
 
9
5
  import { IFileService } from './type';
@@ -12,7 +8,14 @@ export class ClientService implements IFileService {
12
8
  async createFile(file: DB_File) {
13
9
  // save to local storage
14
10
  // we may want to save to a remote server later
15
- return FileModel.create(file);
11
+ const res = await FileModel.create(file);
12
+ // arrayBuffer to url
13
+ const base64 = Buffer.from(file.data!).toString('base64');
14
+
15
+ return {
16
+ id: res.id,
17
+ url: `data:${file.fileType};base64,${base64}`,
18
+ };
16
19
  }
17
20
 
18
21
  async getFile(id: string): Promise<FilePreview> {
@@ -21,20 +24,6 @@ export class ClientService implements IFileService {
21
24
  throw new Error('file not found');
22
25
  }
23
26
 
24
- if (item.saveMode === 'url') {
25
- if (this.enableServer && !fileEnv.NEXT_PUBLIC_S3_DOMAIN) {
26
- throw new Error('fileEnv.NEXT_PUBLIC_S3_DOMAIN is not set while enable server upload');
27
- }
28
-
29
- return {
30
- fileType: item.fileType,
31
- id,
32
- name: item.metadata.filename,
33
- saveMode: 'url',
34
- url: urlJoin(fileEnv.NEXT_PUBLIC_S3_DOMAIN!, item.url!),
35
- };
36
- }
37
-
38
27
  // arrayBuffer to url
39
28
  const url = URL.createObjectURL(new Blob([item.data!], { type: item.fileType }));
40
29
  const base64 = Buffer.from(item.data!).toString('base64');
@@ -53,13 +42,11 @@ export class ClientService implements IFileService {
53
42
  return FileModel.delete(id);
54
43
  }
55
44
 
56
- async removeAllFiles() {
57
- return FileModel.clear();
45
+ async removeFiles(ids: string[]) {
46
+ await Promise.all(ids.map((id) => FileModel.delete(id)));
58
47
  }
59
48
 
60
- private get enableServer() {
61
- return serverConfigSelectors.enableUploadFileToServer(
62
- window.global_serverConfigStore.getState(),
63
- );
49
+ async removeAllFiles() {
50
+ return FileModel.clear();
64
51
  }
65
52
  }
@@ -2,17 +2,23 @@ import urlJoin from 'url-join';
2
2
 
3
3
  import { fileEnv } from '@/config/file';
4
4
  import { lambdaClient } from '@/libs/trpc/client';
5
- import { FilePreview, UploadFileParams } from '@/types/files';
5
+ import {
6
+ FilePreview,
7
+ QueryFileListParams,
8
+ QueryFileListSchemaType,
9
+ UploadFileParams,
10
+ } from '@/types/files';
6
11
 
7
12
  import { IFileService } from './type';
8
13
 
9
14
  interface CreateFileParams extends Omit<UploadFileParams, 'url'> {
15
+ knowledgeBaseId?: string;
10
16
  url: string;
11
17
  }
12
18
 
13
19
  export class ServerService implements IFileService {
14
- async createFile(params: UploadFileParams) {
15
- return lambdaClient.file.createFile.mutate(params as CreateFileParams);
20
+ async createFile(params: UploadFileParams, knowledgeBaseId?: string) {
21
+ return lambdaClient.file.createFile.mutate({ ...params, knowledgeBaseId } as CreateFileParams);
16
22
  }
17
23
 
18
24
  async getFile(id: string): Promise<FilePreview> {
@@ -39,7 +45,23 @@ export class ServerService implements IFileService {
39
45
  await lambdaClient.file.removeFile.mutate({ id });
40
46
  }
41
47
 
48
+ async removeFiles(ids: string[]) {
49
+ await lambdaClient.file.removeFiles.mutate({ ids });
50
+ }
51
+
42
52
  async removeAllFiles() {
43
53
  await lambdaClient.file.removeAllFiles.mutate();
44
54
  }
55
+
56
+ async getFiles(params: QueryFileListParams) {
57
+ return lambdaClient.file.getFiles.query(params as QueryFileListSchemaType);
58
+ }
59
+
60
+ async getFileItem(id: string) {
61
+ return lambdaClient.file.getFileItemById.query({ id });
62
+ }
63
+
64
+ async checkFileHash(hash: string) {
65
+ return lambdaClient.file.checkFileHash.mutate({ hash });
66
+ }
45
67
  }
@@ -1,9 +1,12 @@
1
- /* eslint-disable typescript-sort-keys/interface */
2
1
  import { FilePreview, UploadFileParams } from '@/types/files';
3
2
 
4
3
  export interface IFileService {
5
- createFile(file: UploadFileParams): Promise<{ id: string }>;
6
- removeFile(id: string): Promise<any>;
7
- removeAllFiles(): Promise<any>;
4
+ createFile(
5
+ file: UploadFileParams,
6
+ knowledgeBaseId?: string,
7
+ ): Promise<{ id: string; url: string }>;
8
8
  getFile(id: string): Promise<FilePreview>;
9
+ removeAllFiles(): Promise<any>;
10
+ removeFile(id: string): Promise<any>;
11
+ removeFiles(ids: string[]): Promise<any>;
9
12
  }
@@ -0,0 +1,34 @@
1
+ import { lambdaClient } from '@/libs/trpc/client';
2
+ import { CreateKnowledgeBaseParams } from '@/types/knowledgeBase';
3
+
4
+ class KnowledgeBaseService {
5
+ async createKnowledgeBase(params: CreateKnowledgeBaseParams) {
6
+ return await lambdaClient.knowledgeBase.createKnowledgeBase.mutate(params);
7
+ }
8
+
9
+ async getKnowledgeBaseList() {
10
+ return await lambdaClient.knowledgeBase.getKnowledgeBases.query();
11
+ }
12
+
13
+ async getKnowledgeBaseById(id: string) {
14
+ return await lambdaClient.knowledgeBase.getKnowledgeBaseById.query({ id });
15
+ }
16
+
17
+ async updateKnowledgeBaseList(id: string, value: any) {
18
+ return await lambdaClient.knowledgeBase.updateKnowledgeBase.mutate({ id, value });
19
+ }
20
+
21
+ async deleteKnowledgeBase(id: string) {
22
+ return await lambdaClient.knowledgeBase.removeKnowledgeBase.mutate({ id });
23
+ }
24
+
25
+ async addFilesToKnowledgeBase(knowledgeBaseId: string, ids: string[]) {
26
+ return lambdaClient.knowledgeBase.addFilesToKnowledgeBase.mutate({ ids, knowledgeBaseId });
27
+ }
28
+
29
+ async removeFilesFromKnowledgeBase(knowledgeBaseId: string, ids: string[]) {
30
+ return lambdaClient.knowledgeBase.removeFilesFromKnowledgeBase.mutate({ ids, knowledgeBaseId });
31
+ }
32
+ }
33
+
34
+ export const knowledgeBaseService = new KnowledgeBaseService();
@@ -127,7 +127,7 @@ describe('MessageClientService', () => {
127
127
 
128
128
  // Assert
129
129
  expect(MessageModel.query).toHaveBeenCalledWith({ sessionId, topicId });
130
- expect(messages).toBe(mockMessages);
130
+ expect(messages).toEqual(mockMessages.map((i) => ({ ...i, imageList: [] })));
131
131
  });
132
132
  });
133
133
 
@@ -1,10 +1,18 @@
1
1
  import dayjs from 'dayjs';
2
2
 
3
+ import { FileModel } from '@/database/client/models/file';
3
4
  import { MessageModel } from '@/database/client/models/message';
4
5
  import { DB_Message } from '@/database/client/schemas/message';
5
- import { ChatMessage, ChatMessageError, ChatTTS, ChatTranslate } from '@/types/message';
6
+ import {
7
+ ChatFileItem,
8
+ ChatMessage,
9
+ ChatMessageError,
10
+ ChatTTS,
11
+ ChatTranslate,
12
+ CreateMessageParams,
13
+ } from '@/types/message';
6
14
 
7
- import { CreateMessageParams, IMessageService } from './type';
15
+ import { IMessageService } from './type';
8
16
 
9
17
  export class ClientService implements IMessageService {
10
18
  async createMessage(data: CreateMessageParams) {
@@ -18,7 +26,25 @@ export class ClientService implements IMessageService {
18
26
  }
19
27
 
20
28
  async getMessages(sessionId: string, topicId?: string): Promise<ChatMessage[]> {
21
- return MessageModel.query({ sessionId, topicId });
29
+ const messages = await MessageModel.query({ sessionId, topicId });
30
+
31
+ const fileList = (await Promise.all(
32
+ messages
33
+ .flatMap((item) => item.files)
34
+ .filter(Boolean)
35
+ .map(async (id) => FileModel.findById(id!)),
36
+ )) as ChatFileItem[];
37
+
38
+ return messages.map((item) => ({
39
+ ...item,
40
+ imageList: fileList
41
+ .filter((file) => item.files?.includes(file.id) && file.fileType.startsWith('image'))
42
+ .map((file) => ({
43
+ alt: file.name,
44
+ id: file.id,
45
+ url: file.url,
46
+ })),
47
+ }));
22
48
  }
23
49
 
24
50
  async getAllMessages() {
@@ -3,6 +3,4 @@ import { isServerMode } from '@/const/version';
3
3
  import { ClientService } from './client';
4
4
  import { ServerService } from './server';
5
5
 
6
- export type { CreateMessageParams } from './type';
7
-
8
6
  export const messageService = isServerMode ? new ServerService() : new ClientService();
@@ -1,9 +1,15 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
2
  import { INBOX_SESSION_ID } from '@/const/session';
3
3
  import { lambdaClient } from '@/libs/trpc/client';
4
- import { ChatMessage, ChatMessageError, ChatTTS, ChatTranslate } from '@/types/message';
5
-
6
- import { CreateMessageParams, IMessageService } from './type';
4
+ import {
5
+ ChatMessage,
6
+ ChatMessageError,
7
+ ChatTTS,
8
+ ChatTranslate,
9
+ CreateMessageParams,
10
+ } from '@/types/message';
11
+
12
+ import { IMessageService } from './type';
7
13
 
8
14
  export class ServerService implements IMessageService {
9
15
  createMessage({ sessionId, ...params }: CreateMessageParams): Promise<string> {
@@ -4,23 +4,11 @@ import {
4
4
  ChatMessageError,
5
5
  ChatTTS,
6
6
  ChatTranslate,
7
- MessageRoleType,
7
+ CreateMessageParams,
8
8
  } from '@/types/message';
9
9
 
10
10
  /* eslint-disable typescript-sort-keys/interface */
11
11
 
12
- export interface CreateMessageParams
13
- extends Partial<Omit<ChatMessage, 'content' | 'role' | 'topicId'>> {
14
- fromModel?: string;
15
- fromProvider?: string;
16
- sessionId: string;
17
- traceId?: string;
18
- topicId?: string;
19
- content: string;
20
- error?: ChatMessageError | null;
21
- role: MessageRoleType;
22
- }
23
-
24
12
  export interface IMessageService {
25
13
  createMessage(data: CreateMessageParams): Promise<string>;
26
14
  batchCreateMessages(messages: ChatMessage[]): Promise<any>;
@@ -0,0 +1,29 @@
1
+ import { lambdaClient } from '@/libs/trpc/client';
2
+ import { SemanticSearchSchemaType } from '@/types/rag';
3
+
4
+ class RAGService {
5
+ async createParseFileTask(id: string, skipExist?: boolean) {
6
+ return await lambdaClient.chunk.createParseFileTask.mutate({ id, skipExist });
7
+ }
8
+ async retryParseFile(id: string) {
9
+ return await lambdaClient.chunk.retryParseFileTask.mutate({ id });
10
+ }
11
+
12
+ async createEmbeddingChunksTask(id: string) {
13
+ return await lambdaClient.chunk.createEmbeddingChunksTask.mutate({ id });
14
+ }
15
+
16
+ async semanticSearch(query: string, fileIds?: string[]) {
17
+ return await lambdaClient.chunk.semanticSearch.mutate({ fileIds, query });
18
+ }
19
+
20
+ async semanticSearchForChat(params: SemanticSearchSchemaType) {
21
+ return await lambdaClient.chunk.semanticSearchForChat.mutate(params);
22
+ }
23
+
24
+ async deleteMessageRagQuery(id: string) {
25
+ return await lambdaClient.message.removeMessageQuery.mutate({ id });
26
+ }
27
+ }
28
+
29
+ export const ragService = new RAGService();
@@ -68,7 +68,7 @@ export class ServerService implements ISessionService {
68
68
 
69
69
  // TODO: Need to be fixed
70
70
  // @ts-ignore
71
- return lambdaClient.session.getSessionConfig.query({ id });
71
+ return lambdaClient.agent.getAgentConfig.query({ sessionId: id });
72
72
  }
73
73
 
74
74
  updateSessionConfig(