@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
@@ -50,6 +50,8 @@
50
50
  "chunks": {
51
51
  "embeddingStatus": {
52
52
  "empty": "Os blocos de texto ainda não foram completamente vetorizados, o que resultará na funcionalidade de busca semântica indisponível. Para melhorar a qualidade da busca, por favor, vetorize os blocos de texto.",
53
+ "error": "Falha na vetorização",
54
+ "errorResult": "Falha na vetorização, por favor verifique e tente novamente. Motivo da falha:",
53
55
  "processing": "Os blocos de texto estão sendo vetorizados, por favor, aguarde.",
54
56
  "success": "Atualmente, todos os blocos de texto foram vetorizados."
55
57
  },
@@ -62,6 +62,7 @@
62
62
  "pin": "Закрепить",
63
63
  "pinOff": "Открепить",
64
64
  "rag": {
65
+ "referenceChunks": "Цитируемые источники",
65
66
  "userQuery": {
66
67
  "actions": {
67
68
  "delete": "Удалить переписанный запрос",
@@ -155,9 +156,18 @@
155
156
  },
156
157
  "updateAgent": "Обновить информацию помощника",
157
158
  "upload": {
158
- "actionFiletip": "Загрузите файл",
159
- "actionTooltip": "Загрузить изображение",
160
- "disabled": "Текущая модель не поддерживает визуальное распознавание. Пожалуйста, выберите другую модель.",
159
+ "action": {
160
+ "fileUpload": "Загрузить файл",
161
+ "folderUpload": "Загрузить папку",
162
+ "imageDisabled": "Текущая модель не поддерживает визуальное распознавание, пожалуйста, переключитесь на другую модель",
163
+ "imageUpload": "Загрузить изображение",
164
+ "tooltip": "Загрузить"
165
+ },
166
+ "clientMode": {
167
+ "actionFiletip": "Загрузить файл",
168
+ "actionTooltip": "Загрузить",
169
+ "disabled": "Текущая модель не поддерживает визуальное распознавание и анализ файлов, пожалуйста, переключитесь на другую модель"
170
+ },
161
171
  "preview": {
162
172
  "prepareTasks": "Подготовка блоков...",
163
173
  "status": {
@@ -50,6 +50,8 @@
50
50
  "chunks": {
51
51
  "embeddingStatus": {
52
52
  "empty": "Текстовые блоки еще не полностью векторизованы, что приведет к недоступности функции семантического поиска. Для повышения качества поиска, пожалуйста, векторизуйте текстовые блоки.",
53
+ "error": "Ошибка векторизации",
54
+ "errorResult": "Ошибка векторизации, пожалуйста, проверьте и повторите попытку. Причина сбоя:",
53
55
  "processing": "Текстовые блоки векторизуются, пожалуйста, подождите.",
54
56
  "success": "Все текущие текстовые блоки успешно векторизованы."
55
57
  },
@@ -62,6 +62,7 @@
62
62
  "pin": "Pin",
63
63
  "pinOff": "Unpin",
64
64
  "rag": {
65
+ "referenceChunks": "Referans Parçaları",
65
66
  "userQuery": {
66
67
  "actions": {
67
68
  "delete": "Sorguyu Sil",
@@ -155,9 +156,18 @@
155
156
  },
156
157
  "updateAgent": "Asistan Bilgilerini Güncelle",
157
158
  "upload": {
158
- "actionFiletip": "Dosyayı Yükle",
159
- "actionTooltip": "Resim Yükle",
160
- "disabled": "Geçerli model görüntü tanıma desteğini desteklemiyor, lütfen modeli değiştirerek kullanın",
159
+ "action": {
160
+ "fileUpload": "Dosya Yükle",
161
+ "folderUpload": "Klasör Yükle",
162
+ "imageDisabled": "Mevcut model görsel tanımayı desteklemiyor, lütfen modeli değiştirin ve tekrar deneyin",
163
+ "imageUpload": "Görüntü Yükle",
164
+ "tooltip": "Yükle"
165
+ },
166
+ "clientMode": {
167
+ "actionFiletip": "Dosya Yükle",
168
+ "actionTooltip": "Yükle",
169
+ "disabled": "Mevcut model görsel tanımayı ve dosya analizini desteklemiyor, lütfen modeli değiştirin ve tekrar deneyin"
170
+ },
161
171
  "preview": {
162
172
  "prepareTasks": "Parçaları Hazırlıyor...",
163
173
  "status": {
@@ -50,6 +50,8 @@
50
50
  "chunks": {
51
51
  "embeddingStatus": {
52
52
  "empty": "Metin parçaları henüz tamamen vektörleştirilmedi, bu durum anlamsal arama işlevinin kullanılamamasına neden olabilir, arama kalitesini artırmak için lütfen metin parçalarını vektörleştirin",
53
+ "error": "Vektörleştirme başarısız oldu",
54
+ "errorResult": "Vektörleştirme başarısız oldu, lütfen kontrol edip tekrar deneyin. Başarısız olma nedeni:",
53
55
  "processing": "Metin parçaları vektörleştiriliyor, lütfen bekleyin",
54
56
  "success": "Mevcut metin parçaları tamamen vektörleştirildi"
55
57
  },
@@ -62,6 +62,7 @@
62
62
  "pin": "Ghim",
63
63
  "pinOff": "Bỏ ghim",
64
64
  "rag": {
65
+ "referenceChunks": "Trích dẫn nguồn",
65
66
  "userQuery": {
66
67
  "actions": {
67
68
  "delete": "Xóa truy vấn",
@@ -155,9 +156,18 @@
155
156
  },
156
157
  "updateAgent": "Cập nhật thông tin trợ lý",
157
158
  "upload": {
158
- "actionFiletip": "Tải lên tập tin",
159
- "actionTooltip": "Tải lên hình ảnh",
160
- "disabled": " hình hiện tại không hỗ trợ nhận diện hình ảnh, vui lòng chuyển đổi mô hình trước khi sử dụng",
159
+ "action": {
160
+ "fileUpload": "Tải lên tệp",
161
+ "folderUpload": "Tải lên thư mục",
162
+ "imageDisabled": "Mô hình hiện tại không hỗ trợ nhận diện hình ảnh, vui lòng chuyển đổi mô hình để sử dụng",
163
+ "imageUpload": "Tải lên hình ảnh",
164
+ "tooltip": "Tải lên"
165
+ },
166
+ "clientMode": {
167
+ "actionFiletip": "Tải lên tệp",
168
+ "actionTooltip": "Tải lên",
169
+ "disabled": "Mô hình hiện tại không hỗ trợ nhận diện hình ảnh và phân tích tệp, vui lòng chuyển đổi mô hình để sử dụng"
170
+ },
161
171
  "preview": {
162
172
  "prepareTasks": "Chuẩn bị phân đoạn...",
163
173
  "status": {
@@ -50,6 +50,8 @@
50
50
  "chunks": {
51
51
  "embeddingStatus": {
52
52
  "empty": "Các khối văn bản chưa được vector hóa hoàn toàn, sẽ dẫn đến chức năng tìm kiếm ngữ nghĩa không khả dụng, để nâng cao chất lượng tìm kiếm, vui lòng vector hóa các khối văn bản",
53
+ "error": "Lỗi vector hóa",
54
+ "errorResult": "Lỗi vector hóa, vui lòng kiểm tra và thử lại. Nguyên nhân thất bại:",
53
55
  "processing": "Các khối văn bản đang được vector hóa, vui lòng chờ",
54
56
  "success": "Hiện tại tất cả các khối văn bản đã được vector hóa"
55
57
  },
@@ -62,6 +62,7 @@
62
62
  "pin": "置顶",
63
63
  "pinOff": "取消置顶",
64
64
  "rag": {
65
+ "referenceChunks": "引用源",
65
66
  "userQuery": {
66
67
  "actions": {
67
68
  "delete": "删除 Query 重写",
@@ -155,9 +156,18 @@
155
156
  },
156
157
  "updateAgent": "更新助理信息",
157
158
  "upload": {
158
- "actionFiletip": "上传文件",
159
- "actionTooltip": "上传图片",
160
- "disabled": "当前模型不支持视觉识别和文件分析,请切换模型后使用",
159
+ "action": {
160
+ "fileUpload": "上传文件",
161
+ "folderUpload": "上传文件夹",
162
+ "imageDisabled": "当前模型不支持视觉识别,请切换模型后使用",
163
+ "imageUpload": "上传图片",
164
+ "tooltip": "上传"
165
+ },
166
+ "clientMode": {
167
+ "actionFiletip": "上传文件",
168
+ "actionTooltip": "上传",
169
+ "disabled": "当前模型不支持视觉识别和文件分析,请切换模型后使用"
170
+ },
161
171
  "preview": {
162
172
  "prepareTasks": "准备分块...",
163
173
  "status": {
@@ -50,6 +50,8 @@
50
50
  "chunks": {
51
51
  "embeddingStatus": {
52
52
  "empty": "文本块尚未完全向量化,将导致语义检索功能不可用,为提升检索质量,请对文本块向量化",
53
+ "error": "向量化失败",
54
+ "errorResult": "向量化失败,请检查后重试。失败原因:",
53
55
  "processing": "文本块正在向量化,请耐心等待",
54
56
  "success": "当前文本块均已向量化"
55
57
  },
@@ -62,6 +62,7 @@
62
62
  "pin": "置頂",
63
63
  "pinOff": "取消置頂",
64
64
  "rag": {
65
+ "referenceChunks": "引用來源",
65
66
  "userQuery": {
66
67
  "actions": {
67
68
  "delete": "刪除 Query 重寫",
@@ -155,9 +156,18 @@
155
156
  },
156
157
  "updateAgent": "更新助理信息",
157
158
  "upload": {
158
- "actionFiletip": "上傳文件",
159
- "actionTooltip": "上傳圖片",
160
- "disabled": "當前模型不支援視覺識別,請切換模型後使用",
159
+ "action": {
160
+ "fileUpload": "上傳檔案",
161
+ "folderUpload": "上傳資料夾",
162
+ "imageDisabled": "當前模型不支援視覺識別,請切換模型後使用",
163
+ "imageUpload": "上傳圖片",
164
+ "tooltip": "上傳"
165
+ },
166
+ "clientMode": {
167
+ "actionFiletip": "上傳檔案",
168
+ "actionTooltip": "上傳",
169
+ "disabled": "當前模型不支援視覺識別和檔案分析,請切換模型後使用"
170
+ },
161
171
  "preview": {
162
172
  "prepareTasks": "準備分塊...",
163
173
  "status": {
@@ -50,6 +50,8 @@
50
50
  "chunks": {
51
51
  "embeddingStatus": {
52
52
  "empty": "文本塊尚未完全向量化,將導致語義檢索功能不可用,為提升檢索質量,請對文本塊向量化",
53
+ "error": "向量化失敗",
54
+ "errorResult": "向量化失敗,請檢查後重試。失敗原因:",
53
55
  "processing": "文本塊正在向量化,請耐心等待",
54
56
  "success": "當前文本塊均已向量化"
55
57
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.11.9",
3
+ "version": "1.12.0",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -53,7 +53,8 @@
53
53
  "pull": "git pull",
54
54
  "release": "semantic-release",
55
55
  "self-hosting:docker": "docker build -t lobe-chat:local .",
56
- "self-hosting:docker-cn": "docker build -t lobe-chat:local --build-arg USE_CN_MIRROR=true .",
56
+ "self-hosting:docker-cn": "docker build -t lobe-chat-local --build-arg USE_CN_MIRROR=true .",
57
+ "self-hosting:docker-cn@database": "docker build -t lobe-chat-database-local -f Dockerfile.database --build-arg USE_CN_MIRROR=true .",
57
58
  "start": "next start -p 3210",
58
59
  "stylelint": "stylelint \"src/**/*.{js,jsx,ts,tsx}\" --fix",
59
60
  "test": "npm run test-app && npm run test-server",
@@ -2,6 +2,7 @@ const { join } = require('node:path');
2
2
  const { Pool } = require('pg');
3
3
  const { drizzle } = require('drizzle-orm/node-postgres');
4
4
  const migrator = require('drizzle-orm/node-postgres/migrator');
5
+ const { PGVECTOR_HINT } = require('./errorHint');
5
6
 
6
7
  if (!process.env.DATABASE_URL) {
7
8
  throw new Error('DATABASE_URL is not set, please set it in your environment variables.');
@@ -29,6 +30,11 @@ runMigrations().catch((err) => {
29
30
  '❌ Database migrate failed. Please check your database is valid and DATABASE_URL is set correctly. The error detail is below:',
30
31
  );
31
32
  console.error(err);
33
+
34
+ if (err.message.includes('extension "vector" is not available')) {
35
+ console.info(PGVECTOR_HINT);
36
+ }
37
+
32
38
  // eslint-disable-next-line unicorn/no-process-exit
33
39
  process.exit(1);
34
40
  });
@@ -0,0 +1,17 @@
1
+ const PGVECTOR_HINT = `⚠️ Database migrate failed due to \`pgvector\` extension not found. Please install the \`pgvector\` extension on your postgres instance.
2
+
3
+ 1) if you are using docker postgres image:
4
+ you can just use \`pgvector/pgvector:pg16\` image instead of \`postgres\`, e.g:
5
+
6
+ \`\`\`
7
+ docker run -p 5432:5432 -d --name pg -e POSTGRES_PASSWORD=mysecretpassword pgvector/pgvector:pg16
8
+ \`\`\`
9
+
10
+ 2) if you are using cloud postgres instance, please contact your cloud provider for help.
11
+
12
+ if you have any other question, please open issue here: https://github.com/lobehub/lobe-chat/issues
13
+ `;
14
+
15
+ module.exports = {
16
+ PGVECTOR_HINT,
17
+ };
@@ -3,6 +3,7 @@ import * as migrator from 'drizzle-orm/neon-serverless/migrator';
3
3
  import { join } from 'node:path';
4
4
 
5
5
  import { serverDB } from '../../src/database/server/core/db';
6
+ import { PGVECTOR_HINT } from './errorHint';
6
7
 
7
8
  // Read the `.env` file if it exists, or a file specified by the
8
9
  // dotenv_config_path parameter that's passed to Node.js
@@ -24,6 +25,11 @@ if (connectionString) {
24
25
  // eslint-disable-next-line unicorn/prefer-top-level-await
25
26
  runMigrations().catch((err) => {
26
27
  console.error('❌ Database migrate failed:', err);
28
+
29
+ if ((err.message as string).includes('extension "vector" is not available')) {
30
+ console.info(PGVECTOR_HINT);
31
+ }
32
+
27
33
  // eslint-disable-next-line unicorn/no-process-exit
28
34
  process.exit(1);
29
35
  });
@@ -0,0 +1,37 @@
1
+ import { Image } from '@lobehub/ui';
2
+ import { createStyles } from 'antd-style';
3
+ import { memo } from 'react';
4
+
5
+ import FileIcon from '@/components/FileIcon';
6
+ import { UploadFileItem } from '@/types/files/upload';
7
+
8
+ const useStyles = createStyles(({ css }) => ({
9
+ image: css`
10
+ margin-block: 0 !important;
11
+ box-shadow: none;
12
+
13
+ img {
14
+ object-fit: contain;
15
+ }
16
+ `,
17
+ video: css`
18
+ overflow: hidden;
19
+ border-radius: 8px;
20
+ `,
21
+ }));
22
+
23
+ const Content = memo<UploadFileItem>(({ file, previewUrl }) => {
24
+ const { styles } = useStyles();
25
+
26
+ if (file.type.startsWith('image')) {
27
+ return <Image alt={file.name} src={previewUrl} wrapperClassName={styles.image} />;
28
+ }
29
+
30
+ if (file.type.startsWith('video')) {
31
+ return <video className={styles.video} src={previewUrl} width={'100%'} />;
32
+ }
33
+
34
+ return <FileIcon fileName={file.name} fileType={file.type} size={100} />;
35
+ });
36
+
37
+ export default Content;
@@ -0,0 +1,87 @@
1
+ import { ActionIcon } from '@lobehub/ui';
2
+ import { Typography } from 'antd';
3
+ import { createStyles } from 'antd-style';
4
+ import { Trash2Icon } from 'lucide-react';
5
+ import { memo } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { Center, Flexbox } from 'react-layout-kit';
8
+
9
+ import { useFileStore } from '@/store/file';
10
+ import { UploadFileItem } from '@/types/files/upload';
11
+
12
+ import UploadDetail from '../../../components/UploadDetail';
13
+ import Content from './Content';
14
+ import { FILE_ITEM_SIZE } from './style';
15
+
16
+ const useStyles = createStyles(({ css, token }) => ({
17
+ actions: css`
18
+ position: absolute;
19
+ z-index: 10;
20
+ inset-block-start: -4px;
21
+ inset-inline-end: -4px;
22
+
23
+ background: ${token.colorBgElevated};
24
+ border-radius: 5px;
25
+ box-shadow:
26
+ 0 0 0 0.5px ${token.colorFillSecondary} inset,
27
+ ${token.boxShadowTertiary};
28
+ `,
29
+ container: css`
30
+ position: relative;
31
+
32
+ width: ${FILE_ITEM_SIZE}px;
33
+ min-width: ${FILE_ITEM_SIZE}px;
34
+ height: ${FILE_ITEM_SIZE}px;
35
+
36
+ background: ${token.colorBgContainer};
37
+ border-radius: 8px;
38
+ `,
39
+ image: css`
40
+ margin-block: 0 !important;
41
+ `,
42
+ status: css`
43
+ &.ant-tag {
44
+ padding-inline: 0;
45
+ background: none;
46
+ }
47
+ `,
48
+ }));
49
+
50
+ type FileItemProps = UploadFileItem;
51
+
52
+ const spacing = 8;
53
+
54
+ const FileItem = memo<FileItemProps>((props) => {
55
+ const { file, uploadState, status, id, tasks } = props;
56
+ const { t } = useTranslation(['chat', 'common']);
57
+ const { styles } = useStyles();
58
+ const [removeChatUploadFile] = useFileStore((s) => [s.removeChatUploadFile]);
59
+
60
+ return (
61
+ <Flexbox className={styles.container} distribution={'space-between'}>
62
+ <Center flex={1} height={FILE_ITEM_SIZE - 46} padding={spacing}>
63
+ <Content {...props} />
64
+ </Center>
65
+ <Flexbox gap={4} style={{ paddingBottom: 4, paddingInline: spacing }}>
66
+ <Typography.Text ellipsis={{ tooltip: true }} style={{ fontSize: 12 }}>
67
+ {file.name}
68
+ </Typography.Text>
69
+
70
+ <UploadDetail size={file.size} status={status} tasks={tasks} uploadState={uploadState} />
71
+ </Flexbox>
72
+ <Flexbox className={styles.actions}>
73
+ <ActionIcon
74
+ color={'red'}
75
+ icon={Trash2Icon}
76
+ onClick={() => {
77
+ removeChatUploadFile(id);
78
+ }}
79
+ size={'small'}
80
+ title={t('delete', { ns: 'common' })}
81
+ />
82
+ </Flexbox>
83
+ </Flexbox>
84
+ );
85
+ });
86
+
87
+ export default FileItem;
@@ -0,0 +1,4 @@
1
+ export const FILE_ITEM_SIZE = 200;
2
+
3
+ // 8px on each side
4
+ export const IMAGE_FILE_SIZE = 200 - 2 * 8;
@@ -0,0 +1,28 @@
1
+ export const getHarmoniousSize = (
2
+ inputWidth: number,
3
+ inputHeight: number,
4
+ {
5
+ spacing = 24,
6
+ containerWidth,
7
+ containerHeight,
8
+ }: { containerHeight: number; containerWidth: number; spacing: number },
9
+ ) => {
10
+ let width = String(inputWidth);
11
+ let height = String(inputHeight);
12
+
13
+ const maxWidth = containerWidth - spacing;
14
+ const maxHeight = containerHeight - spacing;
15
+
16
+ if (inputHeight >= inputWidth && inputHeight >= maxHeight) {
17
+ height = maxHeight + 'px';
18
+ width = 'auto';
19
+ } else if (inputWidth >= inputHeight && inputWidth >= maxWidth) {
20
+ height = 'auto';
21
+ width = maxWidth + 'px';
22
+ } else {
23
+ width = width + 'px';
24
+ height = height + 'px';
25
+ }
26
+
27
+ return { height, width };
28
+ };
@@ -0,0 +1,41 @@
1
+ import { createStyles } from 'antd-style';
2
+ import { lighten } from 'polished';
3
+ import { memo } from 'react';
4
+ import { Flexbox } from 'react-layout-kit';
5
+
6
+ import { fileChatSelectors, useFileStore } from '@/store/file';
7
+
8
+ import FileItem from './FileItem';
9
+
10
+ const useStyles = createStyles(({ css, token }) => ({
11
+ container: css`
12
+ overflow-x: scroll;
13
+
14
+ width: 100%;
15
+
16
+ background: ${lighten(0.01, token.colorBgLayout)};
17
+ border-start-start-radius: 8px;
18
+ border-start-end-radius: 8px;
19
+ `,
20
+ }));
21
+
22
+ const FileList = memo(() => {
23
+ const inputFilesList = useFileStore(fileChatSelectors.chatUploadFileList);
24
+ const showFileList = useFileStore(fileChatSelectors.chatUploadFileListHasItem);
25
+ const { styles } = useStyles();
26
+
27
+ return (
28
+ <Flexbox
29
+ className={styles.container}
30
+ gap={6}
31
+ horizontal
32
+ padding={showFileList ? '16px 16px 12px' : 0}
33
+ >
34
+ {inputFilesList.map((item) => (
35
+ <FileItem key={item.id} {...item} />
36
+ ))}
37
+ </Flexbox>
38
+ );
39
+ });
40
+
41
+ export default FileList;
@@ -0,0 +1,40 @@
1
+ import { memo } from 'react';
2
+
3
+ import DragUpload from '@/components/DragUpload';
4
+ import { useAgentStore } from '@/store/agent';
5
+ import { agentSelectors } from '@/store/agent/slices/chat';
6
+ import { useFileStore } from '@/store/file';
7
+ import { useUserStore } from '@/store/user';
8
+ import { modelProviderSelectors } from '@/store/user/selectors';
9
+
10
+ import FileItemList from './FileList';
11
+
12
+ const FilePreview = memo(() => {
13
+ const model = useAgentStore(agentSelectors.currentAgentModel);
14
+
15
+ const canUploadImage = useUserStore(modelProviderSelectors.isModelEnabledUpload(model));
16
+
17
+ const [uploadFiles] = useFileStore((s) => [s.uploadChatFiles]);
18
+
19
+ const upload = async (fileList: FileList | File[] | undefined) => {
20
+ if (!fileList || fileList.length === 0) return;
21
+
22
+ // Filter out files that are not images if the model does not support image uploads
23
+ const files = Array.from(fileList).filter((file) => {
24
+ if (canUploadImage) return true;
25
+
26
+ return !file.type.startsWith('image');
27
+ });
28
+
29
+ uploadFiles(files);
30
+ };
31
+
32
+ return (
33
+ <>
34
+ <DragUpload onUploadFiles={upload} />
35
+ <FileItemList />
36
+ </>
37
+ );
38
+ });
39
+
40
+ export default FilePreview;
@@ -40,7 +40,7 @@ const SendMore = memo<SendMoreProps>(({ disabled, isMac }) => {
40
40
  ]);
41
41
  const addAIMessage = useChatStore((s) => s.addAIMessage);
42
42
 
43
- const sendMessage = useSendMessage();
43
+ const { send: sendMessage } = useSendMessage();
44
44
 
45
45
  const hotKey = [ALT_KEY, 'enter'].join('+');
46
46
  useHotkeys(
@@ -11,13 +11,12 @@ import StopLoadingIcon from '@/components/StopLoading';
11
11
  import SaveTopic from '@/features/ChatInput/Topic';
12
12
  import { useSendMessage } from '@/features/ChatInput/useSend';
13
13
  import { useChatStore } from '@/store/chat';
14
- import { chatSelectors, topicSelectors } from '@/store/chat/selectors';
15
- import { filesSelectors, useFileStore } from '@/store/file';
14
+ import { chatSelectors } from '@/store/chat/selectors';
16
15
  import { useUserStore } from '@/store/user';
17
16
  import { preferenceSelectors } from '@/store/user/selectors';
18
17
  import { isMacOS } from '@/utils/platform';
19
18
 
20
- import LocalFiles from '../LocalFiles';
19
+ import LocalFiles from '../FilePreview';
21
20
  import SendMore from './SendMore';
22
21
 
23
22
  const useStyles = createStyles(({ css, prefixCls, token }) => {
@@ -57,25 +56,14 @@ const Footer = memo<FooterProps>(({ setExpand, expand }) => {
57
56
 
58
57
  const { theme, styles } = useStyles();
59
58
 
60
- const [
61
- isAIGenerating,
62
- isHasMessageLoading,
63
- isCreatingMessage,
64
- isCreatingTopic,
65
- stopGenerateMessage,
66
- ] = useChatStore((s) => [
59
+ const [isAIGenerating, stopGenerateMessage] = useChatStore((s) => [
67
60
  chatSelectors.isAIGenerating(s),
68
- chatSelectors.isHasMessageLoading(s),
69
- chatSelectors.isCreatingMessage(s),
70
- topicSelectors.isCreatingTopic(s),
71
61
  s.stopGenerateMessage,
72
62
  ]);
73
63
 
74
- const isImageUploading = useFileStore(filesSelectors.isImageUploading);
75
-
76
64
  const [useCmdEnterToSend] = useUserStore((s) => [preferenceSelectors.useCmdEnterToSend(s)]);
77
65
 
78
- const sendMessage = useSendMessage();
66
+ const { send: sendMessage, canSend } = useSendMessage();
79
67
 
80
68
  const [isMac, setIsMac] = useState<boolean>();
81
69
  useEffect(() => {
@@ -105,9 +93,6 @@ const Footer = memo<FooterProps>(({ setExpand, expand }) => {
105
93
 
106
94
  const wrapperShortcut = useCmdEnterToSend ? enter : cmdEnter;
107
95
 
108
- const buttonDisabled =
109
- isImageUploading || isHasMessageLoading || isCreatingTopic || isCreatingMessage;
110
-
111
96
  return (
112
97
  <Flexbox
113
98
  align={'end'}
@@ -146,8 +131,8 @@ const Footer = memo<FooterProps>(({ setExpand, expand }) => {
146
131
  ) : (
147
132
  <Space.Compact>
148
133
  <Button
149
- disabled={buttonDisabled}
150
- loading={buttonDisabled}
134
+ disabled={!canSend}
135
+ loading={!canSend}
151
136
  onClick={() => {
152
137
  sendMessage();
153
138
  setExpand?.(false);
@@ -156,7 +141,7 @@ const Footer = memo<FooterProps>(({ setExpand, expand }) => {
156
141
  >
157
142
  {t('input.send')}
158
143
  </Button>
159
- <SendMore disabled={buttonDisabled} isMac={isMac} />
144
+ <SendMore disabled={!canSend} isMac={isMac} />
160
145
  </Space.Compact>
161
146
  )}
162
147
  </Flexbox>
@@ -51,7 +51,7 @@ const InputArea = memo<InputAreaProps>(({ setExpand }) => {
51
51
 
52
52
  const useCmdEnterToSend = useUserStore(preferenceSelectors.useCmdEnterToSend);
53
53
 
54
- const sendMessage = useSendMessage();
54
+ const { send: sendMessage } = useSendMessage();
55
55
 
56
56
  useAutoFocus(ref);
57
57
 
@@ -9,13 +9,12 @@ import {
9
9
  CHAT_TEXTAREA_MAX_HEIGHT,
10
10
  HEADER_HEIGHT,
11
11
  } from '@/const/layoutTokens';
12
- import { useFileStore } from '@/store/file';
13
12
  import { useGlobalStore } from '@/store/global';
14
13
  import { systemStatusSelectors } from '@/store/global/selectors';
15
14
 
15
+ import LocalFiles from './FilePreview';
16
16
  import Footer from './Footer';
17
17
  import Head from './Header';
18
- import LocalFiles from './LocalFiles';
19
18
  import TextArea from './TextArea';
20
19
 
21
20
  const DesktopChatInput = memo(() => {
@@ -25,11 +24,10 @@ const DesktopChatInput = memo(() => {
25
24
  systemStatusSelectors.inputHeight(s),
26
25
  s.updateSystemStatus,
27
26
  ]);
28
- const showFileList = useFileStore((s) => s.inputFilesList.length > 0);
29
27
 
30
28
  return (
31
29
  <>
32
- {!expand && <LocalFiles padding={showFileList ? '8px 16px' : 0} />}
30
+ {!expand && <LocalFiles />}
33
31
  <DraggablePanel
34
32
  fullscreen={expand}
35
33
  headerHeight={HEADER_HEIGHT}