@lobehub/chat 1.11.8 → 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 (440) 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 +46 -3
  7. package/locales/ar/common.json +1 -0
  8. package/locales/ar/components.json +2 -0
  9. package/locales/ar/error.json +1 -0
  10. package/locales/ar/file.json +91 -0
  11. package/locales/ar/knowledgeBase.json +31 -0
  12. package/locales/ar/portal.json +1 -0
  13. package/locales/bg-BG/chat.json +46 -3
  14. package/locales/bg-BG/common.json +1 -0
  15. package/locales/bg-BG/components.json +2 -0
  16. package/locales/bg-BG/error.json +1 -0
  17. package/locales/bg-BG/file.json +91 -0
  18. package/locales/bg-BG/knowledgeBase.json +31 -0
  19. package/locales/bg-BG/portal.json +1 -0
  20. package/locales/de-DE/chat.json +46 -3
  21. package/locales/de-DE/common.json +1 -0
  22. package/locales/de-DE/components.json +2 -0
  23. package/locales/de-DE/error.json +1 -0
  24. package/locales/de-DE/file.json +91 -0
  25. package/locales/de-DE/knowledgeBase.json +31 -0
  26. package/locales/de-DE/portal.json +1 -0
  27. package/locales/en-US/chat.json +46 -3
  28. package/locales/en-US/common.json +1 -0
  29. package/locales/en-US/components.json +2 -0
  30. package/locales/en-US/error.json +1 -0
  31. package/locales/en-US/file.json +91 -0
  32. package/locales/en-US/knowledgeBase.json +31 -0
  33. package/locales/en-US/portal.json +1 -0
  34. package/locales/es-ES/chat.json +46 -3
  35. package/locales/es-ES/common.json +1 -0
  36. package/locales/es-ES/components.json +2 -0
  37. package/locales/es-ES/error.json +1 -0
  38. package/locales/es-ES/file.json +91 -0
  39. package/locales/es-ES/knowledgeBase.json +31 -0
  40. package/locales/es-ES/portal.json +1 -0
  41. package/locales/fr-FR/chat.json +46 -3
  42. package/locales/fr-FR/common.json +1 -0
  43. package/locales/fr-FR/components.json +2 -0
  44. package/locales/fr-FR/error.json +1 -0
  45. package/locales/fr-FR/file.json +91 -0
  46. package/locales/fr-FR/knowledgeBase.json +31 -0
  47. package/locales/fr-FR/portal.json +1 -0
  48. package/locales/it-IT/chat.json +46 -3
  49. package/locales/it-IT/common.json +1 -0
  50. package/locales/it-IT/components.json +2 -0
  51. package/locales/it-IT/error.json +1 -0
  52. package/locales/it-IT/file.json +91 -0
  53. package/locales/it-IT/knowledgeBase.json +31 -0
  54. package/locales/it-IT/portal.json +1 -0
  55. package/locales/ja-JP/chat.json +46 -3
  56. package/locales/ja-JP/common.json +1 -0
  57. package/locales/ja-JP/components.json +2 -0
  58. package/locales/ja-JP/error.json +1 -0
  59. package/locales/ja-JP/file.json +91 -0
  60. package/locales/ja-JP/knowledgeBase.json +31 -0
  61. package/locales/ja-JP/portal.json +1 -0
  62. package/locales/ko-KR/chat.json +46 -3
  63. package/locales/ko-KR/common.json +1 -0
  64. package/locales/ko-KR/components.json +2 -0
  65. package/locales/ko-KR/error.json +1 -0
  66. package/locales/ko-KR/file.json +91 -0
  67. package/locales/ko-KR/knowledgeBase.json +31 -0
  68. package/locales/ko-KR/portal.json +1 -0
  69. package/locales/nl-NL/chat.json +46 -3
  70. package/locales/nl-NL/common.json +1 -0
  71. package/locales/nl-NL/components.json +2 -0
  72. package/locales/nl-NL/error.json +1 -0
  73. package/locales/nl-NL/file.json +91 -0
  74. package/locales/nl-NL/knowledgeBase.json +31 -0
  75. package/locales/nl-NL/portal.json +1 -0
  76. package/locales/pl-PL/chat.json +46 -3
  77. package/locales/pl-PL/common.json +1 -0
  78. package/locales/pl-PL/components.json +2 -0
  79. package/locales/pl-PL/error.json +1 -0
  80. package/locales/pl-PL/file.json +91 -0
  81. package/locales/pl-PL/knowledgeBase.json +31 -0
  82. package/locales/pl-PL/portal.json +1 -0
  83. package/locales/pt-BR/chat.json +46 -3
  84. package/locales/pt-BR/common.json +1 -0
  85. package/locales/pt-BR/components.json +2 -0
  86. package/locales/pt-BR/error.json +1 -0
  87. package/locales/pt-BR/file.json +91 -0
  88. package/locales/pt-BR/knowledgeBase.json +31 -0
  89. package/locales/pt-BR/portal.json +1 -0
  90. package/locales/ru-RU/chat.json +46 -3
  91. package/locales/ru-RU/common.json +1 -0
  92. package/locales/ru-RU/components.json +2 -0
  93. package/locales/ru-RU/error.json +1 -0
  94. package/locales/ru-RU/file.json +91 -0
  95. package/locales/ru-RU/knowledgeBase.json +31 -0
  96. package/locales/ru-RU/portal.json +1 -0
  97. package/locales/tr-TR/chat.json +46 -3
  98. package/locales/tr-TR/common.json +1 -0
  99. package/locales/tr-TR/components.json +2 -0
  100. package/locales/tr-TR/error.json +1 -0
  101. package/locales/tr-TR/file.json +91 -0
  102. package/locales/tr-TR/knowledgeBase.json +31 -0
  103. package/locales/tr-TR/portal.json +1 -0
  104. package/locales/vi-VN/chat.json +46 -3
  105. package/locales/vi-VN/common.json +1 -0
  106. package/locales/vi-VN/components.json +2 -0
  107. package/locales/vi-VN/error.json +1 -0
  108. package/locales/vi-VN/file.json +91 -0
  109. package/locales/vi-VN/knowledgeBase.json +31 -0
  110. package/locales/vi-VN/portal.json +1 -0
  111. package/locales/zh-CN/chat.json +46 -3
  112. package/locales/zh-CN/common.json +1 -0
  113. package/locales/zh-CN/components.json +2 -0
  114. package/locales/zh-CN/error.json +1 -0
  115. package/locales/zh-CN/file.json +91 -0
  116. package/locales/zh-CN/knowledgeBase.json +31 -0
  117. package/locales/zh-CN/portal.json +1 -0
  118. package/locales/zh-TW/chat.json +46 -3
  119. package/locales/zh-TW/common.json +1 -0
  120. package/locales/zh-TW/components.json +2 -0
  121. package/locales/zh-TW/error.json +1 -0
  122. package/locales/zh-TW/file.json +91 -0
  123. package/locales/zh-TW/knowledgeBase.json +31 -0
  124. package/locales/zh-TW/portal.json +1 -0
  125. package/package.json +3 -2
  126. package/scripts/migrateServerDB/docker.cjs +6 -0
  127. package/scripts/migrateServerDB/errorHint.js +17 -0
  128. package/scripts/migrateServerDB/index.ts +6 -0
  129. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/Content.tsx +37 -0
  130. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/index.tsx +87 -0
  131. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/style.ts +4 -0
  132. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileItem/utils.ts +28 -0
  133. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/FileList.tsx +41 -0
  134. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/FilePreview/index.tsx +40 -0
  135. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/SendMore.tsx +1 -1
  136. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/index.tsx +7 -22
  137. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/TextArea.tsx +1 -1
  138. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/index.tsx +2 -4
  139. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/File.tsx +72 -0
  140. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/Image.tsx +74 -0
  141. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/index.tsx +39 -0
  142. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/FileItem/style.ts +1 -0
  143. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/index.tsx +33 -0
  144. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/InputArea/Container.tsx +41 -0
  145. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/InputArea/index.tsx +154 -0
  146. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Send.tsx +34 -0
  147. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/index.tsx +24 -11
  148. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/components/UploadDetail/UploadStatus.tsx +71 -0
  149. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/components/UploadDetail/index.tsx +49 -0
  150. package/src/app/(main)/chat/(workspace)/@portal/FilePreview/index.tsx +26 -0
  151. package/src/app/(main)/chat/(workspace)/@portal/Home/Files/FileList/Item.tsx +53 -0
  152. package/src/app/(main)/chat/(workspace)/@portal/Home/Files/FileList/index.tsx +50 -0
  153. package/src/app/(main)/chat/(workspace)/@portal/Home/Files/index.tsx +21 -0
  154. package/src/app/(main)/chat/(workspace)/@portal/Home/index.tsx +2 -0
  155. package/src/app/(main)/chat/(workspace)/@portal/router.tsx +4 -0
  156. package/src/app/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/KnowledgeTag.tsx +41 -0
  157. package/src/app/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/Tags.tsx +7 -2
  158. package/src/app/(main)/chat/(workspace)/_layout/Desktop/HotKeys.tsx +1 -1
  159. package/src/app/(main)/files/(content)/@menu/default.tsx +27 -0
  160. package/src/app/(main)/files/(content)/@menu/features/FileMenu/index.tsx +97 -0
  161. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/EmptyStatus.tsx +53 -0
  162. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/Item/Content.tsx +175 -0
  163. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/Item/index.tsx +69 -0
  164. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/KnowledgeBaseList.tsx +30 -0
  165. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/SkeletonList.tsx +57 -0
  166. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/index.tsx +54 -0
  167. package/src/app/(main)/files/(content)/@modal/(.)[id]/FileDetail.tsx +16 -0
  168. package/src/app/(main)/files/(content)/@modal/(.)[id]/FilePreview.tsx +15 -0
  169. package/src/app/(main)/files/(content)/@modal/(.)[id]/FullscreenModal.tsx +85 -0
  170. package/src/app/(main)/files/(content)/@modal/(.)[id]/page.tsx +19 -0
  171. package/src/app/(main)/files/(content)/@modal/default.tsx +3 -0
  172. package/src/app/(main)/files/(content)/NotSupportClient.tsx +152 -0
  173. package/src/app/(main)/files/(content)/_layout/Desktop/index.tsx +28 -0
  174. package/src/app/(main)/files/(content)/_layout/Mobile.tsx +47 -0
  175. package/src/app/(main)/files/(content)/_layout/type.ts +7 -0
  176. package/src/app/(main)/files/(content)/layout.tsx +18 -0
  177. package/src/app/(main)/files/(content)/page.tsx +14 -0
  178. package/src/app/(main)/files/[id]/Header.tsx +63 -0
  179. package/src/app/(main)/files/[id]/page.tsx +44 -0
  180. package/src/app/(main)/files/features/FileDetail.tsx +93 -0
  181. package/src/app/(main)/files/hooks/useFileCategory.ts +9 -0
  182. package/src/app/(main)/files/layout.tsx +12 -0
  183. package/src/app/(main)/files/loading.tsx +21 -0
  184. package/src/app/(main)/repos/[id]/@menu/Head/index.tsx +33 -0
  185. package/src/app/(main)/repos/[id]/@menu/Menu/index.tsx +56 -0
  186. package/src/app/(main)/repos/[id]/@menu/default.tsx +25 -0
  187. package/src/app/(main)/repos/[id]/_layout/Desktop/index.tsx +25 -0
  188. package/src/app/(main)/repos/[id]/_layout/Mobile.tsx +47 -0
  189. package/src/app/(main)/repos/[id]/_layout/type.ts +6 -0
  190. package/src/app/(main)/repos/[id]/hooks/useKnowledgeItem.ts +7 -0
  191. package/src/app/(main)/repos/[id]/layout.tsx +13 -0
  192. package/src/app/(main)/repos/[id]/page.tsx +18 -0
  193. package/src/app/(main)/repos/layout.tsx +13 -0
  194. package/src/app/(main)/repos/page.tsx +5 -0
  195. package/src/app/trpc/async/[trpc]/route.ts +28 -0
  196. package/src/chains/abstractChunk.ts +19 -0
  197. package/src/chains/answerWithContext.ts +34 -0
  198. package/src/chains/rewriteQuery.ts +22 -0
  199. package/src/components/DragUpload/index.tsx +6 -99
  200. package/src/components/DragUpload/useDragUpload.tsx +146 -0
  201. package/src/components/FeatureList/index.tsx +64 -0
  202. package/src/components/FileParsingStatus/index.tsx +230 -0
  203. package/src/components/ImageItem/index.tsx +10 -2
  204. package/src/components/KnowledgeIcon/index.tsx +28 -0
  205. package/src/config/app.ts +6 -1
  206. package/src/config/featureFlags/schema.ts +1 -1
  207. package/src/config/modelProviders/bedrock.ts +5 -5
  208. package/src/const/file.ts +1 -0
  209. package/src/const/url.ts +1 -0
  210. package/src/database/client/models/file.ts +8 -2
  211. package/src/database/server/migrations/0005_pgvector.sql +2 -0
  212. package/src/database/server/migrations/0006_add_knowledge_base.sql +307 -0
  213. package/src/database/server/migrations/meta/0005_snapshot.json +2119 -0
  214. package/src/database/server/migrations/meta/0006_snapshot.json +3006 -0
  215. package/src/database/server/migrations/meta/_journal.json +14 -0
  216. package/src/database/server/models/__tests__/_test_template.ts +155 -0
  217. package/src/database/server/models/__tests__/agent.test.ts +226 -0
  218. package/src/database/server/models/__tests__/asyncTask.test.ts +176 -0
  219. package/src/database/server/models/__tests__/chunk.test.ts +336 -0
  220. package/src/database/server/models/__tests__/file.test.ts +317 -29
  221. package/src/database/server/models/__tests__/fixtures/embedding.ts +568 -0
  222. package/src/database/server/models/__tests__/knowledgeBase.test.ts +132 -0
  223. package/src/database/server/models/__tests__/message.test.ts +7 -4
  224. package/src/database/server/models/_template.ts +10 -1
  225. package/src/database/server/models/agent.ts +165 -0
  226. package/src/database/server/models/asyncTask.ts +96 -0
  227. package/src/database/server/models/chunk.ts +203 -0
  228. package/src/database/server/models/embedding.ts +47 -0
  229. package/src/database/server/models/file.ts +231 -12
  230. package/src/database/server/models/knowledgeBase.ts +94 -0
  231. package/src/database/server/models/message.ts +156 -30
  232. package/src/database/server/models/user.ts +12 -1
  233. package/src/database/server/schemas/lobechat/agent.ts +93 -0
  234. package/src/database/server/schemas/lobechat/discover.ts +1 -1
  235. package/src/database/server/schemas/lobechat/file.ts +118 -1
  236. package/src/database/server/schemas/lobechat/index.ts +5 -1
  237. package/src/database/server/schemas/lobechat/message.ts +169 -0
  238. package/src/database/server/schemas/lobechat/rag.ts +51 -0
  239. package/src/database/server/schemas/lobechat/relations.ts +68 -48
  240. package/src/database/server/schemas/lobechat/session.ts +77 -0
  241. package/src/database/server/schemas/lobechat/topic.ts +32 -0
  242. package/src/database/server/schemas/lobechat/user.ts +40 -25
  243. package/src/database/server/utils/idGenerator.ts +1 -0
  244. package/src/features/ChatInput/ActionBar/Clear.tsx +1 -1
  245. package/src/features/ChatInput/ActionBar/Knowledge/Dropdown.tsx +160 -0
  246. package/src/features/ChatInput/ActionBar/Knowledge/ListItem.tsx +52 -0
  247. package/src/features/ChatInput/ActionBar/Knowledge/index.tsx +54 -0
  248. package/src/features/ChatInput/ActionBar/Tools/index.tsx +1 -1
  249. package/src/features/ChatInput/ActionBar/Upload/ClientMode.tsx +52 -0
  250. package/src/features/ChatInput/ActionBar/Upload/ServerMode.tsx +104 -0
  251. package/src/features/ChatInput/ActionBar/Upload/index.tsx +8 -0
  252. package/src/features/ChatInput/ActionBar/config.ts +14 -5
  253. package/src/features/ChatInput/useSend.ts +16 -7
  254. package/src/features/Conversation/Messages/Assistant/FileChunks/Item/index.tsx +51 -0
  255. package/src/features/Conversation/Messages/Assistant/FileChunks/Item/style.ts +38 -0
  256. package/src/features/Conversation/Messages/Assistant/FileChunks/index.tsx +76 -0
  257. package/src/features/Conversation/Messages/Assistant/index.tsx +13 -4
  258. package/src/features/Conversation/Messages/Default.tsx +4 -0
  259. package/src/features/Conversation/Messages/User/BelowMessage.tsx +78 -0
  260. package/src/features/Conversation/Messages/User/FileListViewer/Item.tsx +53 -0
  261. package/src/features/Conversation/Messages/User/FileListViewer/index.tsx +21 -0
  262. package/src/{components/FileList/FileListViewer.tsx → features/Conversation/Messages/User/ImageFileListViewer.tsx} +10 -2
  263. package/src/features/Conversation/Messages/{User.tsx → User/index.tsx} +11 -2
  264. package/src/features/Conversation/Messages/index.ts +8 -3
  265. package/src/features/Conversation/components/ChatItem/index.tsx +33 -10
  266. package/src/features/Conversation/components/InboxWelcome/QuestionSuggest.tsx +1 -1
  267. package/src/features/Conversation/types/index.tsx +1 -0
  268. package/src/features/FileManager/ChunkDrawer/ChunkList/ChunkItem.tsx +61 -0
  269. package/src/features/FileManager/ChunkDrawer/ChunkList/index.tsx +42 -0
  270. package/src/features/FileManager/ChunkDrawer/Content.tsx +38 -0
  271. package/src/features/FileManager/ChunkDrawer/Loading/index.tsx +16 -0
  272. package/src/features/FileManager/ChunkDrawer/SimilaritySearchList/Item.tsx +62 -0
  273. package/src/features/FileManager/ChunkDrawer/SimilaritySearchList/index.tsx +31 -0
  274. package/src/features/FileManager/ChunkDrawer/index.tsx +48 -0
  275. package/src/features/FileManager/FileList/EmptyStatus.tsx +153 -0
  276. package/src/features/FileManager/FileList/FileListItem/ChunkTag.tsx +35 -0
  277. package/src/features/FileManager/FileList/FileListItem/DropdownMenu.tsx +150 -0
  278. package/src/features/FileManager/FileList/FileListItem/index.tsx +211 -0
  279. package/src/features/FileManager/FileList/FileSkeleton.tsx +25 -0
  280. package/src/features/FileManager/FileList/ToolBar/Config.tsx +28 -0
  281. package/src/features/FileManager/FileList/ToolBar/MultiSelectActions.tsx +152 -0
  282. package/src/features/FileManager/FileList/ToolBar/index.tsx +114 -0
  283. package/src/features/FileManager/FileList/index.tsx +143 -0
  284. package/src/features/FileManager/FileList/useCheckTaskStatus.ts +27 -0
  285. package/src/features/FileManager/Header/FilesSearchBar.tsx +41 -0
  286. package/src/features/FileManager/Header/UploadFileButton.tsx +79 -0
  287. package/src/features/FileManager/Header/index.tsx +39 -0
  288. package/src/features/FileManager/UploadDock/Item.tsx +124 -0
  289. package/src/features/FileManager/UploadDock/index.tsx +183 -0
  290. package/src/features/FileManager/index.tsx +38 -0
  291. package/src/features/FileSidePanel/index.tsx +79 -0
  292. package/src/features/FileViewer/NotSupport/index.tsx +54 -0
  293. package/src/features/FileViewer/PDFViewer/HighlightLayer.tsx +81 -0
  294. package/src/features/FileViewer/PDFViewer/index.tsx +93 -0
  295. package/src/features/FileViewer/PDFViewer/style.ts +20 -0
  296. package/src/features/FileViewer/PDFViewer/useResizeObserver.ts +33 -0
  297. package/src/features/FileViewer/TXTViewer/index.tsx +41 -0
  298. package/src/features/FileViewer/index.tsx +45 -0
  299. package/src/features/KnowledgeBaseModal/AddFilesToKnowledgeBase/SelectForm.tsx +115 -0
  300. package/src/features/KnowledgeBaseModal/AddFilesToKnowledgeBase/index.tsx +43 -0
  301. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/Action.tsx +103 -0
  302. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/EditCustomPlugin.tsx +55 -0
  303. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/PluginTag.tsx +58 -0
  304. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Item/index.tsx +70 -0
  305. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/List.tsx +49 -0
  306. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/Loading.tsx +13 -0
  307. package/src/features/KnowledgeBaseModal/AssignKnowledgeBase/index.tsx +39 -0
  308. package/src/features/KnowledgeBaseModal/CreateNew/CreateForm.tsx +73 -0
  309. package/src/features/KnowledgeBaseModal/CreateNew/index.tsx +35 -0
  310. package/src/features/KnowledgeBaseModal/index.ts +3 -0
  311. package/src/libs/langchain/loaders/pdf/index.ts +2 -2
  312. package/src/libs/trpc/async/asyncAuth.ts +24 -0
  313. package/src/libs/trpc/async/index.ts +10 -0
  314. package/src/libs/trpc/async/init.ts +11 -0
  315. package/src/libs/trpc/client/async.ts +14 -0
  316. package/src/libs/trpc/client/index.ts +1 -0
  317. package/src/libs/trpc/client/lambda.ts +9 -0
  318. package/src/libs/trpc/middleware/keyVaults.ts +18 -0
  319. package/src/libs/unstructured/__tests__/index.test.ts +0 -10
  320. package/src/libs/unstructured/index.ts +6 -11
  321. package/src/locales/default/chat.ts +47 -3
  322. package/src/locales/default/common.ts +1 -0
  323. package/src/locales/default/components.ts +2 -0
  324. package/src/locales/default/error.ts +6 -1
  325. package/src/locales/default/file.ts +92 -0
  326. package/src/locales/default/index.ts +4 -0
  327. package/src/locales/default/knowledgeBase.ts +31 -0
  328. package/src/locales/default/portal.ts +1 -0
  329. package/src/middleware.ts +3 -0
  330. package/src/server/asyncContext.ts +40 -0
  331. package/src/server/modules/ContentChunk/index.ts +135 -0
  332. package/src/server/modules/S3/index.ts +30 -5
  333. package/src/server/routers/async/caller.ts +27 -0
  334. package/src/server/routers/async/file.ts +247 -0
  335. package/src/server/routers/async/index.ts +12 -0
  336. package/src/server/routers/lambda/_template.ts +77 -0
  337. package/src/server/routers/lambda/agent.ts +159 -0
  338. package/src/server/routers/lambda/chunk.ts +189 -0
  339. package/src/server/routers/lambda/file.ts +129 -5
  340. package/src/server/routers/lambda/index.ts +6 -0
  341. package/src/server/routers/lambda/knowledgeBase.ts +79 -0
  342. package/src/server/routers/lambda/message.ts +6 -0
  343. package/src/server/routers/lambda/session.ts +0 -25
  344. package/src/server/routers/lambda/user.ts +5 -1
  345. package/src/server/services/chunk/index.ts +74 -0
  346. package/src/server/utils/files.ts +9 -0
  347. package/src/services/__tests__/chat.test.ts +18 -20
  348. package/src/services/__tests__/{upload.test.ts → upload_legacy.test.ts} +1 -1
  349. package/src/services/agent.ts +45 -0
  350. package/src/services/chat.ts +17 -15
  351. package/src/services/file/client.test.ts +1 -50
  352. package/src/services/file/client.ts +12 -25
  353. package/src/services/file/server.ts +25 -3
  354. package/src/services/file/type.ts +7 -4
  355. package/src/services/knowledgeBase.ts +34 -0
  356. package/src/services/message/client.test.ts +1 -1
  357. package/src/services/message/client.ts +29 -3
  358. package/src/services/message/index.ts +0 -2
  359. package/src/services/message/server.ts +9 -3
  360. package/src/services/message/type.ts +1 -13
  361. package/src/services/rag.ts +29 -0
  362. package/src/services/session/server.ts +1 -1
  363. package/src/services/upload.ts +89 -84
  364. package/src/services/upload_legacy.ts +104 -0
  365. package/src/services/user/client.ts +7 -2
  366. package/src/services/user/server.ts +6 -2
  367. package/src/services/user/type.ts +3 -2
  368. package/src/store/agent/slices/chat/action.ts +90 -18
  369. package/src/store/agent/slices/chat/initialState.ts +1 -0
  370. package/src/store/agent/slices/chat/selectors.ts +58 -0
  371. package/src/store/chat/slices/builtinTool/action.test.ts +2 -2
  372. package/src/store/chat/slices/builtinTool/action.ts +2 -2
  373. package/src/store/chat/slices/message/action.test.ts +2 -1
  374. package/src/store/chat/slices/message/action.ts +102 -26
  375. package/src/store/chat/slices/message/actions/rag.ts +148 -0
  376. package/src/store/chat/slices/message/initialState.ts +7 -0
  377. package/src/store/chat/slices/message/reducer.ts +6 -2
  378. package/src/store/chat/slices/message/selectors.ts +38 -3
  379. package/src/store/chat/slices/plugin/action.ts +8 -2
  380. package/src/store/chat/slices/portal/action.ts +8 -0
  381. package/src/store/chat/slices/portal/initialState.ts +3 -0
  382. package/src/store/chat/slices/portal/selectors.ts +8 -2
  383. package/src/store/file/initialState.ts +5 -1
  384. package/src/store/file/reducers/uploadFileList.ts +133 -0
  385. package/src/store/file/selectors.ts +3 -0
  386. package/src/store/file/slices/chat/action.test.ts +90 -90
  387. package/src/store/file/slices/chat/action.ts +164 -109
  388. package/src/store/file/slices/chat/initialState.ts +7 -2
  389. package/src/store/file/slices/chat/selectors.test.ts +84 -61
  390. package/src/store/file/slices/chat/selectors.ts +22 -32
  391. package/src/store/file/slices/chunk/action.ts +36 -0
  392. package/src/store/file/slices/chunk/index.ts +3 -0
  393. package/src/store/file/slices/chunk/initialState.ts +15 -0
  394. package/src/store/file/slices/chunk/selectors.ts +10 -0
  395. package/src/store/file/slices/fileManager/action.ts +187 -0
  396. package/src/store/file/slices/fileManager/index.ts +3 -0
  397. package/src/store/file/slices/fileManager/initialState.ts +18 -0
  398. package/src/store/file/slices/fileManager/selectors.ts +58 -0
  399. package/src/store/file/slices/tts/action.test.ts +1 -1
  400. package/src/store/file/slices/tts/action.ts +2 -2
  401. package/src/store/file/slices/upload/action.ts +164 -0
  402. package/src/store/file/store.ts +12 -1
  403. package/src/store/knowledgeBase/index.ts +2 -0
  404. package/src/store/knowledgeBase/initialState.ts +7 -0
  405. package/src/store/knowledgeBase/selectors.ts +1 -0
  406. package/src/store/knowledgeBase/slices/content/action.ts +27 -0
  407. package/src/store/knowledgeBase/slices/content/index.ts +1 -0
  408. package/src/store/knowledgeBase/slices/crud/action.ts +78 -0
  409. package/src/store/knowledgeBase/slices/crud/index.ts +3 -0
  410. package/src/store/knowledgeBase/slices/crud/initialState.ts +12 -0
  411. package/src/store/knowledgeBase/slices/crud/selectors.ts +7 -0
  412. package/src/store/knowledgeBase/store.ts +30 -0
  413. package/src/store/serverConfig/selectors.test.ts +1 -1
  414. package/src/store/user/slices/preference/selectors.ts +8 -0
  415. package/src/store/user/slices/settings/selectors/systemAgent.ts +2 -0
  416. package/src/tools/dalle/Render/Item/ImageFileItem.tsx +3 -23
  417. package/src/types/agent/index.ts +9 -0
  418. package/src/types/asyncTask.ts +31 -0
  419. package/src/types/chunk/document.ts +9 -0
  420. package/src/types/chunk/index.ts +52 -0
  421. package/src/types/files/index.ts +35 -0
  422. package/src/types/files/list.ts +44 -0
  423. package/src/types/files/upload.ts +91 -0
  424. package/src/types/knowledgeBase/index.ts +45 -0
  425. package/src/types/message/index.ts +54 -5
  426. package/src/types/rag.ts +16 -0
  427. package/src/utils/filter.test.ts +2 -0
  428. package/src/utils/server/auth.ts +23 -0
  429. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/LocalFiles.tsx +0 -46
  430. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files.tsx +0 -19
  431. package/src/components/FileList/EditableFileList.tsx +0 -47
  432. package/src/components/FileList/index.ts +0 -2
  433. package/src/components/FileList/type.tsx +0 -7
  434. package/src/database/server/schemas/lobechat/chat.ts +0 -331
  435. package/src/features/ChatInput/ActionBar/FileUpload.tsx +0 -69
  436. package/src/features/ChatInput/useChatInput.ts +0 -45
  437. package/src/features/FileList/EditableFileList.tsx +0 -31
  438. package/src/features/FileList/FileListPreviewer.tsx +0 -17
  439. package/src/features/FileList/index.tsx +0 -2
  440. package/src/types/files.ts +0 -42
@@ -0,0 +1,77 @@
1
+ /* eslint-disable sort-keys-fix/sort-keys-fix */
2
+ import { boolean, integer, pgTable, text, unique, uniqueIndex, varchar } from 'drizzle-orm/pg-core';
3
+ import { createInsertSchema } from 'drizzle-zod';
4
+
5
+ import { idGenerator, randomSlug } from '../../utils/idGenerator';
6
+ import { createdAt, updatedAt } from './_helpers';
7
+ import { users } from './user';
8
+
9
+ // ======= sessionGroups ======= //
10
+
11
+ export const sessionGroups = pgTable(
12
+ 'session_groups',
13
+ {
14
+ id: text('id')
15
+ .$defaultFn(() => idGenerator('sessionGroups'))
16
+ .primaryKey(),
17
+ name: text('name').notNull(),
18
+ sort: integer('sort'),
19
+
20
+ userId: text('user_id')
21
+ .references(() => users.id, { onDelete: 'cascade' })
22
+ .notNull(),
23
+
24
+ clientId: text('client_id'),
25
+ createdAt: createdAt(),
26
+ updatedAt: updatedAt(),
27
+ },
28
+ (table) => ({
29
+ clientIdUnique: unique('session_group_client_id_user_unique').on(table.clientId, table.userId),
30
+ }),
31
+ );
32
+
33
+ export const insertSessionGroupSchema = createInsertSchema(sessionGroups);
34
+
35
+ export type NewSessionGroup = typeof sessionGroups.$inferInsert;
36
+ export type SessionGroupItem = typeof sessionGroups.$inferSelect;
37
+
38
+ // ======= sessions ======= //
39
+
40
+ export const sessions = pgTable(
41
+ 'sessions',
42
+ {
43
+ id: text('id')
44
+ .$defaultFn(() => idGenerator('sessions'))
45
+ .primaryKey(),
46
+ slug: varchar('slug', { length: 100 })
47
+ .notNull()
48
+ .$defaultFn(() => randomSlug()),
49
+ title: text('title'),
50
+ description: text('description'),
51
+ avatar: text('avatar'),
52
+ backgroundColor: text('background_color'),
53
+
54
+ type: text('type', { enum: ['agent', 'group'] }).default('agent'),
55
+
56
+ userId: text('user_id')
57
+ .references(() => users.id, { onDelete: 'cascade' })
58
+ .notNull(),
59
+ groupId: text('group_id').references(() => sessionGroups.id, { onDelete: 'set null' }),
60
+ clientId: text('client_id'),
61
+ pinned: boolean('pinned').default(false),
62
+
63
+ createdAt: createdAt(),
64
+ updatedAt: updatedAt(),
65
+ },
66
+ (t) => ({
67
+ slugUserIdUnique: uniqueIndex('slug_user_id_unique').on(t.slug, t.userId),
68
+
69
+ clientIdUnique: unique('sessions_client_id_user_id_unique').on(t.clientId, t.userId),
70
+ }),
71
+ );
72
+
73
+ export const insertSessionSchema = createInsertSchema(sessions);
74
+ // export const selectSessionSchema = createSelectSchema(sessions);
75
+
76
+ export type NewSession = typeof sessions.$inferInsert;
77
+ export type SessionItem = typeof sessions.$inferSelect;
@@ -0,0 +1,32 @@
1
+ // ======== topics ======= //
2
+ import { boolean, pgTable, text, unique } from 'drizzle-orm/pg-core';
3
+
4
+ import { idGenerator } from '../../utils/idGenerator';
5
+ import { createdAt, updatedAt } from './_helpers';
6
+ import { sessions } from './session';
7
+ import { users } from './user';
8
+
9
+ export const topics = pgTable(
10
+ 'topics',
11
+ {
12
+ clientId: text('client_id'),
13
+ createdAt: createdAt(),
14
+ favorite: boolean('favorite').default(false),
15
+ id: text('id')
16
+ .$defaultFn(() => idGenerator('topics'))
17
+ .primaryKey(),
18
+ sessionId: text('session_id').references(() => sessions.id, { onDelete: 'cascade' }),
19
+ title: text('title'),
20
+
21
+ updatedAt: updatedAt(),
22
+ userId: text('user_id')
23
+ .references(() => users.id, { onDelete: 'cascade' })
24
+ .notNull(),
25
+ },
26
+ (t) => ({
27
+ clientIdUnique: unique('topic_client_id_user_id_unique').on(t.clientId, t.userId),
28
+ }),
29
+ );
30
+
31
+ export type NewTopic = typeof topics.$inferInsert;
32
+ export type TopicItem = typeof topics.$inferSelect;
@@ -1,22 +1,13 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix */
2
- import {
3
- boolean,
4
- integer,
5
- jsonb,
6
- pgTable,
7
- text,
8
- } from 'drizzle-orm/pg-core';
2
+ import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
3
+ import { boolean, integer, jsonb, pgTable, primaryKey, text } from 'drizzle-orm/pg-core';
9
4
 
10
5
  import { DEFAULT_PREFERENCE } from '@/const/user';
6
+ import { CustomPluginParams } from '@/types/tool/plugin';
11
7
 
12
8
  import { createdAt, timestamptz, updatedAt } from './_helpers';
13
9
 
14
- /**
15
- * This table stores users. Users are created in Clerk, then Clerk calls a
16
- * webhook at /api/webhook/clerk to inform this application a user was created.
17
- */
18
10
  export const users = pgTable('users', {
19
- // The ID will be the user's ID from Clerk
20
11
  id: text('id').primaryKey().notNull(),
21
12
  username: text('username').unique(),
22
13
  email: text('email'),
@@ -43,6 +34,20 @@ export const users = pgTable('users', {
43
34
  export type NewUser = typeof users.$inferInsert;
44
35
  export type UserItem = typeof users.$inferSelect;
45
36
 
37
+ export const userSettings = pgTable('user_settings', {
38
+ id: text('id')
39
+ .references(() => users.id, { onDelete: 'cascade' })
40
+ .primaryKey(),
41
+
42
+ tts: jsonb('tts'),
43
+ keyVaults: text('key_vaults'),
44
+ general: jsonb('general'),
45
+ languageModel: jsonb('language_model'),
46
+ systemAgent: jsonb('system_agent'),
47
+ defaultAgent: jsonb('default_agent'),
48
+ tool: jsonb('tool'),
49
+ });
50
+
46
51
  export const userSubscriptions = pgTable('user_subscriptions', {
47
52
  id: text('id').primaryKey().notNull(),
48
53
  userId: text('user_id')
@@ -96,16 +101,26 @@ export const userBudgets = pgTable('user_budgets', {
96
101
  export type NewUserBudgets = typeof userBudgets.$inferInsert;
97
102
  export type UserBudgetItem = typeof userBudgets.$inferSelect;
98
103
 
99
- export const userSettings = pgTable('user_settings', {
100
- id: text('id')
101
- .references(() => users.id, { onDelete: 'cascade' })
102
- .primaryKey(),
103
-
104
- tts: jsonb('tts'),
105
- keyVaults: text('key_vaults'),
106
- general: jsonb('general'),
107
- languageModel: jsonb('language_model'),
108
- systemAgent: jsonb('system_agent'),
109
- defaultAgent: jsonb('default_agent'),
110
- tool: jsonb('tool'),
111
- });
104
+ export const installedPlugins = pgTable(
105
+ 'user_installed_plugins',
106
+ {
107
+ userId: text('user_id')
108
+ .references(() => users.id, { onDelete: 'cascade' })
109
+ .notNull(),
110
+
111
+ identifier: text('identifier').notNull(),
112
+ type: text('type', { enum: ['plugin', 'customPlugin'] }).notNull(),
113
+ manifest: jsonb('manifest').$type<LobeChatPluginManifest>(),
114
+ settings: jsonb('settings'),
115
+ customParams: jsonb('custom_params').$type<CustomPluginParams>(),
116
+
117
+ createdAt: createdAt(),
118
+ updatedAt: updatedAt(),
119
+ },
120
+ (self) => ({
121
+ id: primaryKey({ columns: [self.userId, self.identifier] }),
122
+ }),
123
+ );
124
+
125
+ export type NewInstalledPlugin = typeof installedPlugins.$inferInsert;
126
+ export type InstalledPluginItem = typeof installedPlugins.$inferSelect;
@@ -5,6 +5,7 @@ import { createNanoId } from '@/utils/uuid';
5
5
  const prefixes = {
6
6
  agents: 'agt',
7
7
  files: 'file',
8
+ knowledgeBases: 'kb',
8
9
  messages: 'msg',
9
10
  plugins: 'plg',
10
11
  sessionGroups: 'sg',
@@ -13,7 +13,7 @@ import { useFileStore } from '@/store/file';
13
13
  const Clear = memo(() => {
14
14
  const { t } = useTranslation('setting');
15
15
  const [clearMessage] = useChatStore((s) => [s.clearMessage]);
16
- const [clearImageList] = useFileStore((s) => [s.clearImageList]);
16
+ const [clearImageList] = useFileStore((s) => [s.clearChatUploadFileList]);
17
17
  const hotkeys = [META_KEY, ALT_KEY, CLEAN_MESSAGE_KEY].join('+');
18
18
  const [confirmOpened, updateConfirmOpened] = useState(false);
19
19
  const mobile = useIsMobile();
@@ -0,0 +1,160 @@
1
+ import { Icon } from '@lobehub/ui';
2
+ import { Dropdown } from 'antd';
3
+ import { createStyles } from 'antd-style';
4
+ import type { ItemType } from 'antd/es/menu/interface';
5
+ import isEqual from 'fast-deep-equal';
6
+ import { ArrowRight, LibraryBig } from 'lucide-react';
7
+ import { PropsWithChildren, memo, useState } from 'react';
8
+ import { useTranslation } from 'react-i18next';
9
+ import { Flexbox } from 'react-layout-kit';
10
+
11
+ import FileIcon from '@/components/FileIcon';
12
+ import RepoIcon from '@/components/RepoIcon';
13
+ import { AssignKnowledgeBaseModal } from '@/features/KnowledgeBaseModal';
14
+ import { useAgentStore } from '@/store/agent';
15
+ import { agentSelectors } from '@/store/agent/selectors';
16
+
17
+ import ListItem from './ListItem';
18
+
19
+ const useStyles = createStyles(({ css, prefixCls }) => ({
20
+ knowledgeBase: css``,
21
+ menu: css`
22
+ &.${prefixCls}-dropdown-menu {
23
+ padding-block: 8px;
24
+ }
25
+
26
+ .${prefixCls}-dropdown-menu-item-group-list .${prefixCls}-dropdown-menu-item {
27
+ padding: 0;
28
+ padding-inline-start: 8px;
29
+ border-radius: 4px;
30
+ }
31
+ `,
32
+ }));
33
+
34
+ const DropdownMenu = memo<PropsWithChildren>(({ children }) => {
35
+ const { t } = useTranslation('chat');
36
+
37
+ const { styles } = useStyles();
38
+ const [open, setOpen] = useState(false);
39
+ const files = useAgentStore(agentSelectors.currentAgentFiles, isEqual);
40
+ const knowledgeBases = useAgentStore(agentSelectors.currentAgentKnowledgeBases, isEqual);
41
+
42
+ const [toggleFile, toggleKnowledgeBase] = useAgentStore((s) => [
43
+ s.toggleFile,
44
+ s.toggleKnowledgeBase,
45
+ ]);
46
+
47
+ const items: ItemType[] = [
48
+ // {
49
+ // children: [
50
+ // {
51
+ // icon: <RepoIcon />,
52
+ // key: 'allFiles',
53
+ // label: <KnowledgeBaseItem id={'all'} label={t('knowledgeBase.allFiles')} />,
54
+ // },
55
+ // {
56
+ // icon: <RepoIcon />,
57
+ // key: 'allRepos',
58
+ // label: <KnowledgeBaseItem id={'all'} label={t('knowledgeBase.allKnowledgeBases')} />,
59
+ // },
60
+ // ],
61
+ // key: 'all',
62
+ // label: (
63
+ // <Flexbox horizontal justify={'space-between'}>
64
+ // {t('knowledgeBase.all')}
65
+ // {/*<Link href={'/files'}>{t('knowledgeBase.more')}</Link>*/}
66
+ // </Flexbox>
67
+ // ),
68
+ // type: 'group',
69
+ // },
70
+ {
71
+ children: [
72
+ // first the files
73
+ ...files.map((item) => ({
74
+ icon: <FileIcon fileName={item.name} fileType={item.type} size={20} />,
75
+ key: item.id,
76
+ label: (
77
+ <ListItem
78
+ enabled={item.enabled}
79
+ id={item.id}
80
+ label={item.name}
81
+ onUpdate={async (id, enabled) => {
82
+ await toggleFile(id, enabled);
83
+ }}
84
+ />
85
+ ),
86
+ })),
87
+
88
+ // then the knowledge bases
89
+ ...knowledgeBases.map((item) => ({
90
+ icon: <RepoIcon />,
91
+ key: item.id,
92
+ label: (
93
+ <ListItem
94
+ enabled={item.enabled}
95
+ id={item.id}
96
+ label={item.name}
97
+ onUpdate={async (id, enabled) => {
98
+ await toggleKnowledgeBase(id, enabled);
99
+ }}
100
+ />
101
+ ),
102
+ })),
103
+ {
104
+ icon: (
105
+ <Icon
106
+ icon={LibraryBig}
107
+ size={{ fontSize: 16 }}
108
+ style={{ marginInlineEnd: 0, paddingInlineStart: 4 }}
109
+ />
110
+ ),
111
+ key: 'knowledge-base-store',
112
+ label: (
113
+ <Flexbox gap={40} horizontal justify={'space-between'} padding={'8px 12px'}>
114
+ {t('knowledgeBase.viewMore')} <Icon icon={ArrowRight} />
115
+ </Flexbox>
116
+ ),
117
+ onClick: (e) => {
118
+ e.domEvent.stopPropagation();
119
+ setOpen(true);
120
+ },
121
+ },
122
+ ],
123
+ className: styles.knowledgeBase,
124
+ key: 'relativeFilesOrKnowledgeBases',
125
+ label: (
126
+ <Flexbox horizontal justify={'space-between'}>
127
+ {t('knowledgeBase.relativeFilesOrKnowledgeBases')}
128
+ {/*<Link href={'/files'}>{t('knowledgeBase.more')}</Link>*/}
129
+ </Flexbox>
130
+ ),
131
+ type: 'group',
132
+ },
133
+ ];
134
+
135
+ return (
136
+ <>
137
+ <Dropdown
138
+ arrow={false}
139
+ menu={{
140
+ className: styles.menu,
141
+ items,
142
+ onClick: (e) => {
143
+ e.domEvent.preventDefault();
144
+ },
145
+ style: {
146
+ maxHeight: 500,
147
+ overflowY: 'scroll',
148
+ },
149
+ }}
150
+ placement={'top'}
151
+ trigger={['click']}
152
+ >
153
+ {children}
154
+ </Dropdown>
155
+ <AssignKnowledgeBaseModal open={open} setOpen={setOpen} />
156
+ </>
157
+ );
158
+ });
159
+
160
+ export default DropdownMenu;
@@ -0,0 +1,52 @@
1
+ import { Icon } from '@lobehub/ui';
2
+ import { Checkbox } from 'antd';
3
+ import { Loader2 } from 'lucide-react';
4
+ import { memo, useState } from 'react';
5
+ import { Center, Flexbox } from 'react-layout-kit';
6
+
7
+ interface FileItemProps {
8
+ enabled?: boolean;
9
+ id: string;
10
+ label: string;
11
+ onUpdate: (id: string, enabled: boolean) => Promise<void>;
12
+ }
13
+
14
+ const ListItem = memo<FileItemProps>(({ id, onUpdate, label, enabled }) => {
15
+ const [loading, setLoading] = useState(false);
16
+
17
+ const updateState = async () => {
18
+ setLoading(true);
19
+ await onUpdate(id, !enabled);
20
+ setLoading(false);
21
+ };
22
+
23
+ return (
24
+ <Flexbox
25
+ gap={24}
26
+ horizontal
27
+ justify={'space-between'}
28
+ onClick={async (e) => {
29
+ e.stopPropagation();
30
+ updateState();
31
+ }}
32
+ padding={'8px 12px'}
33
+ >
34
+ {label}
35
+ {loading ? (
36
+ <Center width={18}>
37
+ <Icon icon={Loader2} spin />
38
+ </Center>
39
+ ) : (
40
+ <Checkbox
41
+ checked={enabled}
42
+ onClick={(e) => {
43
+ e.stopPropagation();
44
+ updateState();
45
+ }}
46
+ />
47
+ )}
48
+ </Flexbox>
49
+ );
50
+ });
51
+
52
+ export default ListItem;
@@ -0,0 +1,54 @@
1
+ import { ActionIcon } from '@lobehub/ui';
2
+ import { LibraryBig, LucideLoader2 } from 'lucide-react';
3
+ import { Suspense, memo } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ import TipGuide from '@/components/TipGuide';
7
+ import { isServerMode } from '@/const/version';
8
+ import { useUserStore } from '@/store/user';
9
+ import { preferenceSelectors } from '@/store/user/selectors';
10
+
11
+ import DropdownMenu from './Dropdown';
12
+
13
+ const enableKnowledge = isServerMode;
14
+
15
+ const Knowledge = memo(() => {
16
+ const { t } = useTranslation('chat');
17
+
18
+ const [showTip, updateGuideState] = useUserStore((s) => [
19
+ preferenceSelectors.showUploadFileInKnowledgeBaseTip(s),
20
+ s.updateGuideState,
21
+ ]);
22
+
23
+ const content = (
24
+ <DropdownMenu>
25
+ <ActionIcon
26
+ disable={!enableKnowledge}
27
+ icon={LibraryBig}
28
+ placement={'bottom'}
29
+ title={enableKnowledge ? t('knowledgeBase.title') : t('knowledgeBase.disabled')}
30
+ />
31
+ </DropdownMenu>
32
+ );
33
+
34
+ return (
35
+ <Suspense fallback={<ActionIcon icon={LucideLoader2} spin />}>
36
+ {showTip ? (
37
+ <TipGuide
38
+ onOpenChange={() => {
39
+ updateGuideState({ uploadFileInKnowledgeBase: false });
40
+ }}
41
+ open={showTip}
42
+ placement={'top'}
43
+ title={t('knowledgeBase.uploadGuide')}
44
+ >
45
+ {content}
46
+ </TipGuide>
47
+ ) : (
48
+ content
49
+ )}
50
+ </Suspense>
51
+ );
52
+ });
53
+
54
+ export default Knowledge;
@@ -17,7 +17,7 @@ const Tools = memo(() => {
17
17
  const enableFC = useUserStore(modelProviderSelectors.isModelEnabledFunctionCall(model));
18
18
 
19
19
  return (
20
- <Suspense fallback={<ActionIcon icon={LucideLoader2} />}>
20
+ <Suspense fallback={<ActionIcon icon={LucideLoader2} spin />}>
21
21
  <DropdownMenu>
22
22
  <ActionIcon
23
23
  disable={!enableFC}
@@ -0,0 +1,52 @@
1
+ import { ActionIcon } from '@lobehub/ui';
2
+ import { Upload } from 'antd';
3
+ import { FileUp, LucideImage } from 'lucide-react';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ import { useAgentStore } from '@/store/agent';
8
+ import { agentSelectors } from '@/store/agent/slices/chat';
9
+ import { useFileStore } from '@/store/file';
10
+ import { useUserStore } from '@/store/user';
11
+ import { modelProviderSelectors } from '@/store/user/selectors';
12
+
13
+ const FileUpload = memo(() => {
14
+ const { t } = useTranslation('chat');
15
+
16
+ const upload = useFileStore((s) => s.uploadChatFiles);
17
+
18
+ const model = useAgentStore(agentSelectors.currentAgentModel);
19
+ const [canUpload, enabledFiles] = useUserStore((s) => [
20
+ modelProviderSelectors.isModelEnabledUpload(model)(s),
21
+ modelProviderSelectors.isModelEnabledFiles(model)(s),
22
+ ]);
23
+
24
+ return (
25
+ <Upload
26
+ accept={enabledFiles ? undefined : 'image/*'}
27
+ beforeUpload={async (file) => {
28
+ await upload([file]);
29
+
30
+ return false;
31
+ }}
32
+ disabled={!canUpload}
33
+ multiple={true}
34
+ showUploadList={false}
35
+ >
36
+ <ActionIcon
37
+ disable={!canUpload}
38
+ icon={enabledFiles ? FileUp : LucideImage}
39
+ placement={'bottom'}
40
+ title={t(
41
+ canUpload
42
+ ? enabledFiles
43
+ ? 'upload.clientMode.actionFiletip'
44
+ : 'upload.clientMode.actionTooltip'
45
+ : 'upload.clientMode.disabled',
46
+ )}
47
+ />
48
+ </Upload>
49
+ );
50
+ });
51
+
52
+ export default FileUpload;
@@ -0,0 +1,104 @@
1
+ import { ActionIcon, Icon, Tooltip } from '@lobehub/ui';
2
+ import { Dropdown, MenuProps, Upload } from 'antd';
3
+ import { css, cx } from 'antd-style';
4
+ import { FileUp, FolderUp, ImageUp, Paperclip } from 'lucide-react';
5
+ import { memo } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+
8
+ import { useAgentStore } from '@/store/agent';
9
+ import { agentSelectors } from '@/store/agent/slices/chat';
10
+ import { useFileStore } from '@/store/file';
11
+ import { useUserStore } from '@/store/user';
12
+ import { modelProviderSelectors } from '@/store/user/selectors';
13
+
14
+ const hotArea = css`
15
+ &::before {
16
+ content: '';
17
+ position: absolute;
18
+ inset: 0;
19
+ background-color: transparent;
20
+ }
21
+ `;
22
+
23
+ const FileUpload = memo(() => {
24
+ const { t } = useTranslation('chat');
25
+
26
+ const upload = useFileStore((s) => s.uploadChatFiles);
27
+
28
+ const model = useAgentStore(agentSelectors.currentAgentModel);
29
+
30
+ const canUploadImage = useUserStore(modelProviderSelectors.isModelEnabledVision(model));
31
+
32
+ const items: MenuProps['items'] = [
33
+ {
34
+ disabled: !canUploadImage,
35
+ icon: <Icon icon={ImageUp} />,
36
+ key: 'upload-image',
37
+ label: canUploadImage ? (
38
+ <Upload
39
+ accept={'image/*'}
40
+ beforeUpload={async (file) => {
41
+ await upload([file]);
42
+
43
+ return false;
44
+ }}
45
+ multiple
46
+ showUploadList={false}
47
+ >
48
+ <div className={cx(hotArea)}>{t('upload.action.imageUpload')}</div>
49
+ </Upload>
50
+ ) : (
51
+ <Tooltip placement={'right'} title={t('upload.action.imageDisabled')}>
52
+ <div className={cx(hotArea)}>{t('upload.action.imageUpload')}</div>
53
+ </Tooltip>
54
+ ),
55
+ },
56
+ {
57
+ icon: <Icon icon={FileUp} />,
58
+ key: 'upload-file',
59
+ label: (
60
+ <Upload
61
+ beforeUpload={async (file) => {
62
+ if (!canUploadImage && file.type.startsWith('image')) return false;
63
+
64
+ await upload([file]);
65
+
66
+ return false;
67
+ }}
68
+ multiple
69
+ showUploadList={false}
70
+ >
71
+ <div className={cx(hotArea)}>{t('upload.action.fileUpload')}</div>
72
+ </Upload>
73
+ ),
74
+ },
75
+ {
76
+ icon: <Icon icon={FolderUp} />,
77
+ key: 'upload-folder',
78
+ label: (
79
+ <Upload
80
+ beforeUpload={async (file) => {
81
+ if (!canUploadImage && file.type.startsWith('image')) return false;
82
+
83
+ await upload([file]);
84
+
85
+ return false;
86
+ }}
87
+ directory
88
+ multiple={true}
89
+ showUploadList={false}
90
+ >
91
+ <div className={cx(hotArea)}>{t('upload.action.folderUpload')}</div>
92
+ </Upload>
93
+ ),
94
+ },
95
+ ];
96
+
97
+ return (
98
+ <Dropdown menu={{ items }} placement="top">
99
+ <ActionIcon icon={Paperclip} placement={'bottom'} title={t('upload.action.tooltip')} />
100
+ </Dropdown>
101
+ );
102
+ });
103
+
104
+ export default FileUpload;
@@ -0,0 +1,8 @@
1
+ import { isServerMode } from '@/const/version';
2
+
3
+ import ClientMode from './ClientMode';
4
+ import ServerMode from './ServerMode';
5
+
6
+ const Upload = isServerMode ? ServerMode : ClientMode;
7
+
8
+ export default Upload;