@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
@@ -1,9 +1,17 @@
1
- import { eq } from 'drizzle-orm';
1
+ import { asc, count, eq, ilike, inArray, notExists } from 'drizzle-orm';
2
2
  import { and, desc } from 'drizzle-orm/expressions';
3
3
 
4
4
  import { serverDB } from '@/database/server/core/db';
5
+ import { FilesTabs, QueryFileListParams, SortType } from '@/types/files';
5
6
 
6
- import { FileItem, NewFile, files } from '../schemas/lobechat';
7
+ import {
8
+ FileItem,
9
+ NewFile,
10
+ NewGlobalFile,
11
+ files,
12
+ globalFiles,
13
+ knowledgeBaseFiles,
14
+ } from '../schemas/lobechat';
7
15
 
8
16
  export class FileModel {
9
17
  private readonly userId: string;
@@ -12,27 +20,204 @@ export class FileModel {
12
20
  this.userId = userId;
13
21
  }
14
22
 
15
- create = async (params: Omit<NewFile, 'id' | 'userId'>) => {
16
- const result = await serverDB
17
- .insert(files)
18
- .values({ ...params, userId: this.userId })
19
- .returning();
23
+ create = async (params: Omit<NewFile, 'id' | 'userId'> & { knowledgeBaseId?: string }) => {
24
+ const result = await serverDB.transaction(async (trx) => {
25
+ const result = await trx
26
+ .insert(files)
27
+ .values({ ...params, userId: this.userId })
28
+ .returning();
29
+
30
+ const item = result[0];
31
+
32
+ if (params.knowledgeBaseId) {
33
+ await trx
34
+ .insert(knowledgeBaseFiles)
35
+ .values({ fileId: item.id, knowledgeBaseId: params.knowledgeBaseId });
36
+ }
37
+
38
+ return item;
39
+ });
40
+
41
+ return { id: result.id };
42
+ };
43
+
44
+ createGlobalFile = async (file: Omit<NewGlobalFile, 'id' | 'userId'>) => {
45
+ return serverDB.insert(globalFiles).values(file).returning();
46
+ };
20
47
 
21
- return { id: result[0].id };
48
+ checkHash = async (hash: string) => {
49
+ const item = await serverDB.query.globalFiles.findFirst({
50
+ where: eq(globalFiles.hashId, hash),
51
+ });
52
+ if (!item) return { isExist: false };
53
+
54
+ return {
55
+ fileType: item.fileType,
56
+ isExist: true,
57
+ metadata: item.metadata,
58
+ size: item.size,
59
+ url: item.url,
60
+ };
22
61
  };
23
62
 
24
63
  delete = async (id: string) => {
25
- return serverDB.delete(files).where(and(eq(files.id, id), eq(files.userId, this.userId)));
64
+ const file = await this.findById(id);
65
+ if (!file) return;
66
+
67
+ const fileHash = file.fileHash!;
68
+
69
+ return await serverDB.transaction(async (trx) => {
70
+ await trx.delete(files).where(and(eq(files.id, id), eq(files.userId, this.userId)));
71
+
72
+ const result = await trx
73
+ .select({ count: count() })
74
+ .from(files)
75
+ .where(and(eq(files.fileHash, fileHash)));
76
+
77
+ const fileCount = result[0].count;
78
+
79
+ // delete the file from global file if it is not used by other files
80
+ if (fileCount === 0) {
81
+ await trx.delete(globalFiles).where(eq(globalFiles.hashId, fileHash));
82
+
83
+ return file;
84
+ }
85
+ });
86
+ };
87
+
88
+ deleteGlobalFile = async (hashId: string) => {
89
+ return serverDB.delete(globalFiles).where(eq(globalFiles.hashId, hashId));
90
+ };
91
+
92
+ deleteMany = async (ids: string[]) => {
93
+ const fileList = await this.findByIds(ids);
94
+ const hashList = fileList.map((file) => file.fileHash!);
95
+
96
+ return await serverDB.transaction(async (trx) => {
97
+ // delete the files
98
+ await trx.delete(files).where(and(inArray(files.id, ids), eq(files.userId, this.userId)));
99
+
100
+ // count the files by hash
101
+ const result = await trx
102
+ .select({
103
+ count: count(),
104
+ hashId: files.fileHash,
105
+ })
106
+ .from(files)
107
+ .where(inArray(files.fileHash, hashList))
108
+ .groupBy(files.fileHash);
109
+
110
+ // Create a Map to store the query result
111
+ const countMap = new Map(result.map((item) => [item.hashId, item.count]));
112
+
113
+ // Ensure that all incoming hashes have a result, even if it is 0
114
+ const fileHashCounts = hashList.map((hashId) => ({
115
+ count: countMap.get(hashId) || 0,
116
+ hashId: hashId,
117
+ }));
118
+
119
+ const needToDeleteList = fileHashCounts.filter((item) => item.count === 0);
120
+
121
+ if (needToDeleteList.length === 0) return;
122
+
123
+ // delete the file from global file if it is not used by other files
124
+ await trx.delete(globalFiles).where(
125
+ inArray(
126
+ globalFiles.hashId,
127
+ needToDeleteList.map((item) => item.hashId!),
128
+ ),
129
+ );
130
+
131
+ return fileList.filter((file) =>
132
+ needToDeleteList.some((item) => item.hashId === file.fileHash),
133
+ );
134
+ });
26
135
  };
27
136
 
28
137
  clear = async () => {
29
138
  return serverDB.delete(files).where(eq(files.userId, this.userId));
30
139
  };
31
140
 
32
- query = async () => {
141
+ query = async ({
142
+ category,
143
+ q,
144
+ sortType,
145
+ sorter,
146
+ knowledgeBaseId,
147
+ showFilesInKnowledgeBase,
148
+ }: QueryFileListParams = {}) => {
149
+ // 1. query where
150
+ let whereClause = and(
151
+ q ? ilike(files.name, `%${q}%`) : undefined,
152
+ eq(files.userId, this.userId),
153
+ );
154
+ if (category && category !== FilesTabs.All) {
155
+ const fileTypePrefix = this.getFileTypePrefix(category as FilesTabs);
156
+ whereClause = and(whereClause, ilike(files.fileType, `${fileTypePrefix}%`));
157
+ }
158
+
159
+ // 2. order part
160
+
161
+ let orderByClause = desc(files.createdAt);
162
+ // create a map for sortable fields
163
+ const sortableFields = {
164
+ createdAt: files.createdAt,
165
+ name: files.name,
166
+ size: files.size,
167
+ updatedAt: files.updatedAt,
168
+ } as const;
169
+ type SortableField = keyof typeof sortableFields;
170
+
171
+ if (sorter && sortType && sorter in sortableFields) {
172
+ const sortFunction = sortType.toLowerCase() === SortType.Asc ? asc : desc;
173
+ orderByClause = sortFunction(sortableFields[sorter as SortableField]);
174
+ }
175
+
176
+ // 3. build query
177
+ let query = serverDB
178
+ .select({
179
+ chunkTaskId: files.chunkTaskId,
180
+ createdAt: files.createdAt,
181
+ embeddingTaskId: files.embeddingTaskId,
182
+ fileType: files.fileType,
183
+ id: files.id,
184
+ name: files.name,
185
+ size: files.size,
186
+ updatedAt: files.updatedAt,
187
+ url: files.url,
188
+ })
189
+ .from(files);
190
+
191
+ // 4. add knowledge base query
192
+ if (knowledgeBaseId) {
193
+ // if knowledgeBaseId is provided, it means we are querying files in a knowledge-base
194
+
195
+ // @ts-ignore
196
+ query = query.innerJoin(
197
+ knowledgeBaseFiles,
198
+ and(
199
+ eq(files.id, knowledgeBaseFiles.fileId),
200
+ eq(knowledgeBaseFiles.knowledgeBaseId, knowledgeBaseId),
201
+ ),
202
+ );
203
+ }
204
+ // 5.if we don't show files in knowledge base, we need exclude files in knowledge base
205
+ else if (!showFilesInKnowledgeBase) {
206
+ whereClause = and(
207
+ whereClause,
208
+ notExists(
209
+ serverDB.select().from(knowledgeBaseFiles).where(eq(knowledgeBaseFiles.fileId, files.id)),
210
+ ),
211
+ );
212
+ }
213
+
214
+ // or we are just filter in the global files
215
+ return query.where(whereClause).orderBy(orderByClause);
216
+ };
217
+
218
+ findByIds = async (ids: string[]) => {
33
219
  return serverDB.query.files.findMany({
34
- orderBy: [desc(files.updatedAt)],
35
- where: eq(files.userId, this.userId),
220
+ where: and(inArray(files.id, ids), eq(files.userId, this.userId)),
36
221
  });
37
222
  };
38
223
 
@@ -42,10 +227,44 @@ export class FileModel {
42
227
  });
43
228
  };
44
229
 
230
+ countFilesByHash = async (hash: string) => {
231
+ const result = await serverDB
232
+ .select({
233
+ count: count(),
234
+ })
235
+ .from(files)
236
+ .where(and(eq(files.fileHash, hash)));
237
+
238
+ return result[0].count;
239
+ };
240
+
45
241
  async update(id: string, value: Partial<FileItem>) {
46
242
  return serverDB
47
243
  .update(files)
48
244
  .set({ ...value, updatedAt: new Date() })
49
245
  .where(and(eq(files.id, id), eq(files.userId, this.userId)));
50
246
  }
247
+
248
+ /**
249
+ * get the corresponding file type prefix according to FilesTabs
250
+ */
251
+ private getFileTypePrefix = (category: FilesTabs): string => {
252
+ switch (category) {
253
+ case FilesTabs.Audios: {
254
+ return 'audio';
255
+ }
256
+ case FilesTabs.Documents: {
257
+ return 'application';
258
+ }
259
+ case FilesTabs.Images: {
260
+ return 'image';
261
+ }
262
+ case FilesTabs.Videos: {
263
+ return 'video';
264
+ }
265
+ default: {
266
+ return '';
267
+ }
268
+ }
269
+ };
51
270
  }
@@ -0,0 +1,94 @@
1
+ import { eq, inArray } from 'drizzle-orm';
2
+ import { and, desc } from 'drizzle-orm/expressions';
3
+
4
+ import { serverDB } from '@/database/server';
5
+ import { KnowledgeBaseItem } from '@/types/knowledgeBase';
6
+
7
+ import { NewKnowledgeBase, knowledgeBaseFiles, knowledgeBases } from '../schemas/lobechat';
8
+
9
+ export class KnowledgeBaseModel {
10
+ private userId: string;
11
+
12
+ constructor(userId: string) {
13
+ this.userId = userId;
14
+ }
15
+
16
+ // create
17
+
18
+ create = async (params: Omit<NewKnowledgeBase, 'userId'>) => {
19
+ const [result] = await serverDB
20
+ .insert(knowledgeBases)
21
+ .values({ ...params, userId: this.userId })
22
+ .returning();
23
+
24
+ return result;
25
+ };
26
+
27
+ addFilesToKnowledgeBase = async (id: string, fileIds: string[]) => {
28
+ return serverDB
29
+ .insert(knowledgeBaseFiles)
30
+ .values(fileIds.map((fileId) => ({ fileId, knowledgeBaseId: id, userId: this.userId })))
31
+ .returning();
32
+ };
33
+
34
+ // delete
35
+ delete = async (id: string) => {
36
+ return serverDB
37
+ .delete(knowledgeBases)
38
+ .where(and(eq(knowledgeBases.id, id), eq(knowledgeBases.userId, this.userId)));
39
+ };
40
+
41
+ deleteAll = async () => {
42
+ return serverDB.delete(knowledgeBases).where(eq(knowledgeBases.userId, this.userId));
43
+ };
44
+
45
+ removeFilesFromKnowledgeBase = async (knowledgeBaseId: string, ids: string[]) => {
46
+ return serverDB.delete(knowledgeBaseFiles).where(
47
+ and(
48
+ eq(knowledgeBaseFiles.knowledgeBaseId, knowledgeBaseId),
49
+ inArray(knowledgeBaseFiles.fileId, ids),
50
+ // eq(knowledgeBaseFiles.userId, this.userId),
51
+ ),
52
+ );
53
+ };
54
+ // query
55
+ query = async () => {
56
+ const data = await serverDB
57
+ .select({
58
+ avatar: knowledgeBases.avatar,
59
+ createdAt: knowledgeBases.createdAt,
60
+ description: knowledgeBases.description,
61
+ id: knowledgeBases.id,
62
+ isPublic: knowledgeBases.isPublic,
63
+ name: knowledgeBases.name,
64
+ settings: knowledgeBases.settings,
65
+ type: knowledgeBases.type,
66
+ updatedAt: knowledgeBases.updatedAt,
67
+ })
68
+ .from(knowledgeBases)
69
+ .where(eq(knowledgeBases.userId, this.userId))
70
+ .orderBy(desc(knowledgeBases.updatedAt));
71
+
72
+ return data as KnowledgeBaseItem[];
73
+ };
74
+
75
+ findById = async (id: string) => {
76
+ return serverDB.query.knowledgeBases.findFirst({
77
+ where: and(eq(knowledgeBases.id, id), eq(knowledgeBases.userId, this.userId)),
78
+ });
79
+ };
80
+
81
+ // update
82
+ async update(id: string, value: Partial<KnowledgeBaseItem>) {
83
+ return serverDB
84
+ .update(knowledgeBases)
85
+ .set({ ...value, updatedAt: new Date() })
86
+ .where(and(eq(knowledgeBases.id, id), eq(knowledgeBases.userId, this.userId)));
87
+ }
88
+
89
+ static async findById(id: string) {
90
+ return serverDB.query.knowledgeBases.findFirst({
91
+ where: eq(knowledgeBases.id, id),
92
+ });
93
+ }
94
+ }
@@ -1,21 +1,33 @@
1
- import { count, sql } from 'drizzle-orm';
2
- import { and, asc, desc, eq, isNull, like } from 'drizzle-orm/expressions';
3
- import { inArray } from 'drizzle-orm/sql/expressions/conditions';
1
+ import { count } from 'drizzle-orm';
2
+ import { and, asc, desc, eq, gte, inArray, isNull, like, lt } from 'drizzle-orm/expressions';
4
3
 
5
- import { CreateMessageParams } from '@/database/client/models/message';
6
4
  import { serverDB } from '@/database/server/core/db';
7
5
  import { idGenerator } from '@/database/server/utils/idGenerator';
8
- import { ChatTTS, ChatToolPayload } from '@/types/message';
6
+ import { getFullFileUrl } from '@/server/utils/files';
7
+ import {
8
+ ChatFileItem,
9
+ ChatImageItem,
10
+ ChatTTS,
11
+ ChatToolPayload,
12
+ CreateMessageParams,
13
+ } from '@/types/message';
9
14
  import { merge } from '@/utils/merge';
10
15
 
11
16
  import {
12
17
  MessageItem,
13
18
  MessagePluginItem,
14
- filesToMessages,
19
+ NewMessageQuery,
20
+ chunks,
21
+ embeddings,
22
+ fileChunks,
23
+ files,
15
24
  messagePlugins,
25
+ messageQueries,
26
+ messageQueryChunks,
16
27
  messageTTS,
17
28
  messageTranslates,
18
29
  messages,
30
+ messagesFiles,
19
31
  } from '../schemas/lobechat';
20
32
 
21
33
  export interface QueryMessageParams {
@@ -41,6 +53,7 @@ export class MessageModel {
41
53
  }: QueryMessageParams = {}): Promise<MessageItem[]> {
42
54
  const offset = current * pageSize;
43
55
 
56
+ // 1. get basic messages
44
57
  const result = await serverDB
45
58
  .select({
46
59
  /* eslint-disable sort-keys-fix/sort-keys-fix*/
@@ -102,13 +115,55 @@ export class MessageModel {
102
115
 
103
116
  if (messageIds.length === 0) return result;
104
117
 
105
- const fileIds = await serverDB
118
+ // 2. get relative files
119
+ const rawRelatedFileList = await serverDB
106
120
  .select({
107
- fileId: filesToMessages.fileId,
108
- messageId: filesToMessages.messageId,
121
+ fileType: files.fileType,
122
+ id: messagesFiles.fileId,
123
+ messageId: messagesFiles.messageId,
124
+ name: files.name,
125
+ size: files.size,
126
+ url: files.url,
109
127
  })
110
- .from(filesToMessages)
111
- .where(inArray(filesToMessages.messageId, messageIds));
128
+ .from(messagesFiles)
129
+ .leftJoin(files, eq(files.id, messagesFiles.fileId))
130
+ .where(inArray(messagesFiles.messageId, messageIds));
131
+
132
+ const relatedFileList = rawRelatedFileList.map((file) => ({
133
+ ...file,
134
+ url: getFullFileUrl(file.url),
135
+ }));
136
+
137
+ const imageList = relatedFileList.filter((i) => (i.fileType || '').startsWith('image'));
138
+ const fileList = relatedFileList.filter((i) => !(i.fileType || '').startsWith('image'));
139
+
140
+ // 3. get relative file chunks
141
+ const chunksList = await serverDB
142
+ .select({
143
+ fileId: files.id,
144
+ fileType: files.fileType,
145
+ fileUrl: files.url,
146
+ filename: files.name,
147
+ id: chunks.id,
148
+ messageId: messageQueryChunks.messageId,
149
+ text: chunks.text,
150
+ })
151
+ .from(messageQueryChunks)
152
+ .leftJoin(chunks, eq(chunks.id, messageQueryChunks.chunkId))
153
+ .leftJoin(fileChunks, eq(fileChunks.chunkId, chunks.id))
154
+ .innerJoin(files, eq(fileChunks.fileId, files.id))
155
+ .where(inArray(messageQueryChunks.messageId, messageIds));
156
+
157
+ // 3. get relative message query
158
+ const messageQueriesList = await serverDB
159
+ .select({
160
+ id: messageQueries.id,
161
+ messageId: messageQueries.messageId,
162
+ rewriteQuery: messageQueries.rewriteQuery,
163
+ userQuery: messageQueries.userQuery,
164
+ })
165
+ .from(messageQueries)
166
+ .where(inArray(messageQueries.messageId, messageIds));
112
167
 
113
168
  return result.map(
114
169
  ({
@@ -118,22 +173,45 @@ export class MessageModel {
118
173
  ttsId,
119
174
  // ttsFile, ttsId, ttsContentMd5, ttsVoice,
120
175
  ...item
121
- }) => ({
122
- ...item,
123
- extra: {
124
- fromModel: model,
125
- fromProvider: provider,
126
- translate,
127
- tts: ttsId
128
- ? {
129
- // contentMd5: ttsContentMd5,
130
- // file: ttsFile,
131
- // voice: ttsVoice,
132
- }
133
- : undefined,
134
- },
135
- files: fileIds.filter((relation) => relation.messageId === item.id).map((r) => r.fileId),
136
- }),
176
+ }) => {
177
+ const messageQuery = messageQueriesList.find((relation) => relation.messageId === item.id);
178
+ return {
179
+ ...item,
180
+ chunksList: chunksList.filter((relation) => relation.messageId === item.id),
181
+
182
+ extra: {
183
+ fromModel: model,
184
+ fromProvider: provider,
185
+ translate,
186
+ tts: ttsId
187
+ ? {
188
+ // contentMd5: ttsContentMd5,
189
+ // file: ttsFile,
190
+ // voice: ttsVoice,
191
+ }
192
+ : undefined,
193
+ },
194
+ fileList: fileList
195
+ .filter((relation) => relation.messageId === item.id)
196
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
197
+ .map<ChatFileItem>(({ id, url, size, fileType, name }) => ({
198
+ fileType: fileType!,
199
+ id,
200
+ name: name!,
201
+ size: size!,
202
+ url,
203
+ })),
204
+
205
+ imageList: imageList
206
+ .filter((relation) => relation.messageId === item.id)
207
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
208
+ .map<ChatImageItem>(({ id, url, name }) => ({ alt: name!, id, url })),
209
+
210
+ ragQuery: messageQuery?.rewriteQuery,
211
+ ragQueryId: messageQuery?.id,
212
+ ragRawQuery: messageQuery?.userQuery,
213
+ };
214
+ },
137
215
  );
138
216
  }
139
217
 
@@ -143,6 +221,24 @@ export class MessageModel {
143
221
  });
144
222
  }
145
223
 
224
+ async findMessageQueriesById(messageId: string) {
225
+ const result = await serverDB
226
+ .select({
227
+ embeddings: embeddings.embeddings,
228
+ id: messageQueries.id,
229
+ query: messageQueries.rewriteQuery,
230
+ rewriteQuery: messageQueries.rewriteQuery,
231
+ userQuery: messageQueries.userQuery,
232
+ })
233
+ .from(messageQueries)
234
+ .where(and(eq(messageQueries.messageId, messageId)))
235
+ .leftJoin(embeddings, eq(embeddings.id, messageQueries.embeddingsId));
236
+
237
+ if (result.length === 0) return undefined;
238
+
239
+ return result[0];
240
+ }
241
+
146
242
  async queryAll(): Promise<MessageItem[]> {
147
243
  return serverDB
148
244
  .select()
@@ -195,7 +291,8 @@ export class MessageModel {
195
291
  .where(
196
292
  and(
197
293
  eq(messages.userId, this.userId),
198
- sql`${messages.createdAt} >= ${today} AND ${messages.createdAt} < ${tomorrow}`,
294
+ gte(messages.createdAt, today),
295
+ lt(messages.createdAt, tomorrow),
199
296
  ),
200
297
  )
201
298
  .execute();
@@ -206,7 +303,16 @@ export class MessageModel {
206
303
  // **************** Create *************** //
207
304
 
208
305
  async create(
209
- { fromModel, fromProvider, files, plugin, pluginState, ...message }: CreateMessageParams,
306
+ {
307
+ fromModel,
308
+ fromProvider,
309
+ files,
310
+ plugin,
311
+ pluginState,
312
+ fileChunks,
313
+ ragQueryId,
314
+ ...message
315
+ }: CreateMessageParams,
210
316
  id: string = this.genId(),
211
317
  ): Promise<MessageItem> {
212
318
  return serverDB.transaction(async (trx) => {
@@ -236,10 +342,21 @@ export class MessageModel {
236
342
 
237
343
  if (files && files.length > 0) {
238
344
  await trx
239
- .insert(filesToMessages)
345
+ .insert(messagesFiles)
240
346
  .values(files.map((file) => ({ fileId: file, messageId: id })));
241
347
  }
242
348
 
349
+ if (fileChunks && fileChunks.length > 0 && ragQueryId) {
350
+ await trx.insert(messageQueryChunks).values(
351
+ fileChunks.map((chunk) => ({
352
+ chunkId: chunk.id,
353
+ messageId: id,
354
+ queryId: ragQueryId,
355
+ similarity: chunk.similarity.toString(),
356
+ })),
357
+ );
358
+ }
359
+
243
360
  return item;
244
361
  });
245
362
  }
@@ -252,6 +369,11 @@ export class MessageModel {
252
369
  return serverDB.insert(messages).values(messagesToInsert);
253
370
  }
254
371
 
372
+ async createMessageQuery(params: NewMessageQuery) {
373
+ const result = await serverDB.insert(messageQueries).values(params).returning();
374
+
375
+ return result[0];
376
+ }
255
377
  // **************** Update *************** //
256
378
 
257
379
  async update(id: string, message: Partial<MessageItem>) {
@@ -367,6 +489,10 @@ export class MessageModel {
367
489
  return serverDB.delete(messageTTS).where(and(eq(messageTTS.id, id)));
368
490
  }
369
491
 
492
+ async deleteMessageQuery(id: string) {
493
+ return serverDB.delete(messageQueries).where(and(eq(messageQueries.id, id)));
494
+ }
495
+
370
496
  async deleteMessagesBySession(sessionId?: string | null, topicId?: string | null) {
371
497
  return serverDB
372
498
  .delete(messages)
@@ -4,7 +4,7 @@ import { DeepPartial } from 'utility-types';
4
4
 
5
5
  import { serverDB } from '@/database/server/core/db';
6
6
  import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
7
- import { UserPreference } from '@/types/user';
7
+ import { UserGuide, UserPreference } from '@/types/user';
8
8
  import { UserSettings } from '@/types/user/settings';
9
9
  import { merge } from '@/utils/merge';
10
10
 
@@ -145,4 +145,15 @@ export class UserModel {
145
145
  .set({ preference: merge(user.preference, value) })
146
146
  .where(eq(users.id, id));
147
147
  }
148
+
149
+ async updateGuide(id: string, value: Partial<UserGuide>) {
150
+ const user = await serverDB.query.users.findFirst({ where: eq(users.id, id) });
151
+ if (!user) return;
152
+
153
+ const prevPreference = (user.preference || {}) as UserPreference;
154
+ return serverDB
155
+ .update(users)
156
+ .set({ preference: { ...prevPreference, guide: merge(prevPreference.guide || {}, value) } })
157
+ .where(eq(users.id, id));
158
+ }
148
159
  }