@lobehub/lobehub 2.0.0-next.34 → 2.0.0-next.36

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 (282) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/next.config.ts +5 -6
  4. package/package.json +2 -2
  5. package/packages/agent-runtime/src/core/__tests__/runtime.test.ts +112 -77
  6. package/packages/agent-runtime/src/core/runtime.ts +63 -18
  7. package/packages/agent-runtime/src/types/generalAgent.ts +55 -0
  8. package/packages/agent-runtime/src/types/index.ts +1 -0
  9. package/packages/agent-runtime/src/types/instruction.ts +10 -3
  10. package/packages/const/src/user.ts +0 -1
  11. package/packages/context-engine/src/processors/GroupMessageFlatten.ts +8 -6
  12. package/packages/context-engine/src/processors/__tests__/GroupMessageFlatten.test.ts +12 -12
  13. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/assistant-group-branches.json +249 -0
  14. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/index.ts +4 -0
  15. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/multi-assistant-group.json +260 -0
  16. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/active-index-1.json +4 -0
  17. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/assistant-group-branches.json +481 -0
  18. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/conversation.json +5 -1
  19. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/index.ts +4 -0
  20. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/multi-assistant-group.json +407 -0
  21. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/nested.json +18 -2
  22. package/packages/conversation-flow/src/__tests__/fixtures/outputs/complex-scenario.json +25 -3
  23. package/packages/conversation-flow/src/__tests__/parse.test.ts +12 -0
  24. package/packages/conversation-flow/src/index.ts +1 -1
  25. package/packages/conversation-flow/src/transformation/FlatListBuilder.ts +112 -34
  26. package/packages/conversation-flow/src/types/flatMessageList.ts +0 -12
  27. package/packages/conversation-flow/src/{types.ts → types/index.ts} +3 -14
  28. package/packages/database/src/models/message.ts +18 -19
  29. package/packages/types/src/aiChat.ts +2 -0
  30. package/packages/types/src/importer.ts +2 -2
  31. package/packages/types/src/message/ui/chat.ts +17 -1
  32. package/packages/types/src/message/ui/extra.ts +2 -2
  33. package/packages/types/src/message/ui/params.ts +2 -2
  34. package/packages/types/src/user/preference.ts +0 -4
  35. package/packages/utils/src/tokenizer/index.ts +3 -11
  36. package/src/app/[variants]/(main)/chat/ChatRouter.tsx +83 -0
  37. package/src/app/[variants]/(main)/chat/_layout/ChatLayout.tsx +22 -0
  38. package/src/app/[variants]/(main)/chat/_layout/Desktop/SessionPanel.tsx +12 -7
  39. package/src/app/[variants]/(main)/chat/_layout/Desktop/index.tsx +2 -2
  40. package/src/app/[variants]/(main)/chat/_layout/FeatureFlagsProvider.tsx +24 -0
  41. package/src/app/[variants]/(main)/chat/_layout/Mobile.tsx +3 -2
  42. package/src/app/[variants]/(main)/chat/_layout/type.ts +0 -1
  43. package/src/app/[variants]/(main)/chat/components/ConversationArea.tsx +29 -0
  44. package/src/app/[variants]/(main)/chat/components/MainChatPage.tsx +25 -0
  45. package/src/app/[variants]/(main)/chat/components/PortalPanel.tsx +28 -0
  46. package/src/app/[variants]/(main)/chat/components/SessionPanel.tsx +33 -0
  47. package/src/app/[variants]/(main)/chat/{settings/page.tsx → components/SettingsPage.tsx} +35 -3
  48. package/src/app/[variants]/(main)/chat/components/TopicSidebar.tsx +30 -0
  49. package/src/app/[variants]/(main)/chat/components/WorkspaceLayout.tsx +73 -0
  50. package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Desktop/MessageFromUrl.tsx +3 -3
  51. package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/index.tsx +1 -1
  52. package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/useSend.ts +3 -3
  53. package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/useSend.ts +6 -6
  54. package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/ChatItem/index.tsx +1 -1
  55. package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/Content.tsx +5 -3
  56. package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/AgentWelcome/OpeningQuestions.tsx +2 -2
  57. package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/GroupWelcome/GroupUsageSuggest.tsx +2 -2
  58. package/src/app/[variants]/(main)/chat/{layout.ts → layout.tsx} +0 -1
  59. package/src/app/[variants]/(main)/chat/page.tsx +12 -0
  60. package/src/app/[variants]/(main)/labs/page.tsx +0 -9
  61. package/src/features/ChatInput/ActionBar/STT/browser.tsx +3 -3
  62. package/src/features/ChatInput/ActionBar/STT/openai.tsx +3 -3
  63. package/src/features/Conversation/Error/AccessCodeForm.tsx +1 -1
  64. package/src/features/Conversation/Error/ChatInvalidApiKey.tsx +1 -1
  65. package/src/features/Conversation/Error/ClerkLogin/index.tsx +1 -1
  66. package/src/features/Conversation/Error/OAuthForm.tsx +1 -1
  67. package/src/features/Conversation/Error/index.tsx +0 -5
  68. package/src/features/Conversation/Messages/Assistant/Actions/index.tsx +13 -10
  69. package/src/features/Conversation/Messages/Assistant/Extra/index.test.tsx +3 -8
  70. package/src/features/Conversation/Messages/Assistant/Extra/index.tsx +2 -6
  71. package/src/features/Conversation/Messages/Assistant/MessageContent.tsx +7 -9
  72. package/src/features/Conversation/Messages/Assistant/Tool/Inspector/PluginResult.tsx +2 -2
  73. package/src/features/Conversation/Messages/Assistant/Tool/Inspector/PluginState.tsx +2 -2
  74. package/src/features/Conversation/Messages/Assistant/Tool/Render/PluginSettings.tsx +4 -1
  75. package/src/features/Conversation/Messages/Assistant/Tool/Render/index.tsx +2 -3
  76. package/src/features/Conversation/Messages/Assistant/index.tsx +57 -60
  77. package/src/features/Conversation/Messages/Default.tsx +1 -0
  78. package/src/features/Conversation/Messages/Group/Actions/WithContentId.tsx +38 -10
  79. package/src/features/Conversation/Messages/Group/Actions/index.tsx +1 -1
  80. package/src/features/Conversation/Messages/Group/ContentBlock.tsx +1 -3
  81. package/src/features/Conversation/Messages/Group/GroupChildren.tsx +12 -12
  82. package/src/features/Conversation/Messages/Group/MessageContent.tsx +7 -1
  83. package/src/features/Conversation/Messages/Group/Tool/Render/PluginSettings.tsx +1 -1
  84. package/src/features/Conversation/Messages/Group/index.tsx +2 -1
  85. package/src/features/Conversation/Messages/Supervisor/index.tsx +2 -2
  86. package/src/features/Conversation/Messages/User/{Actions.tsx → Actions/ActionsBar.tsx} +26 -25
  87. package/src/features/Conversation/Messages/User/Actions/MessageBranch.tsx +107 -0
  88. package/src/features/Conversation/Messages/User/Actions/index.tsx +42 -0
  89. package/src/features/Conversation/Messages/User/index.tsx +43 -44
  90. package/src/features/Conversation/Messages/index.tsx +3 -3
  91. package/src/features/Conversation/components/AutoScroll.tsx +3 -3
  92. package/src/features/Conversation/components/Extras/Usage/UsageDetail/AnimatedNumber.tsx +55 -0
  93. package/src/features/Conversation/components/Extras/Usage/UsageDetail/index.tsx +5 -2
  94. package/src/features/Conversation/components/VirtualizedList/index.tsx +29 -20
  95. package/src/features/Conversation/hooks/useChatListActionsBar.tsx +8 -10
  96. package/src/features/Portal/GroupThread/Body/index.tsx +1 -1
  97. package/src/features/Portal/Thread/Chat/ChatInput/useSend.ts +3 -3
  98. package/src/hooks/useHotkeys/chatScope.ts +16 -8
  99. package/src/server/routers/lambda/__tests__/aiChat.test.ts +1 -1
  100. package/src/server/routers/lambda/__tests__/integration/message.integration.test.ts +0 -26
  101. package/src/server/routers/lambda/aiChat.ts +3 -2
  102. package/src/server/routers/lambda/message.ts +8 -16
  103. package/src/server/services/message/__tests__/index.test.ts +29 -39
  104. package/src/server/services/message/index.ts +41 -36
  105. package/src/services/electron/desktopNotification.ts +6 -6
  106. package/src/services/electron/file.ts +6 -6
  107. package/src/services/file/ClientS3/index.ts +8 -8
  108. package/src/services/message/__tests__/metadata-race-condition.test.ts +157 -0
  109. package/src/services/message/index.ts +21 -15
  110. package/src/services/upload.ts +11 -11
  111. package/src/services/utils/abortableRequest.test.ts +161 -0
  112. package/src/services/utils/abortableRequest.ts +67 -0
  113. package/src/store/chat/agents/GeneralChatAgent.ts +137 -0
  114. package/src/store/chat/agents/createAgentExecutors.ts +395 -0
  115. package/src/store/chat/helpers.test.ts +0 -99
  116. package/src/store/chat/helpers.ts +0 -11
  117. package/src/store/chat/slices/aiChat/actions/__tests__/conversationControl.test.ts +332 -0
  118. package/src/store/chat/slices/aiChat/actions/__tests__/conversationLifecycle.test.ts +257 -0
  119. package/src/store/chat/slices/aiChat/actions/__tests__/helpers.ts +11 -2
  120. package/src/store/chat/slices/aiChat/actions/__tests__/rag.test.ts +6 -6
  121. package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +391 -0
  122. package/src/store/chat/slices/aiChat/actions/__tests__/streamingStates.test.ts +179 -0
  123. package/src/store/chat/slices/aiChat/actions/conversationControl.ts +157 -0
  124. package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +329 -0
  125. package/src/store/chat/slices/aiChat/actions/generateAIGroupChat.ts +14 -14
  126. package/src/store/chat/slices/aiChat/actions/index.ts +12 -6
  127. package/src/store/chat/slices/aiChat/actions/rag.ts +9 -6
  128. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +604 -0
  129. package/src/store/chat/slices/aiChat/actions/streamingStates.ts +84 -0
  130. package/src/store/chat/slices/builtinTool/actions/__tests__/localSystem.test.ts +4 -4
  131. package/src/store/chat/slices/builtinTool/actions/__tests__/search.test.ts +11 -11
  132. package/src/store/chat/slices/builtinTool/actions/interpreter.ts +8 -8
  133. package/src/store/chat/slices/builtinTool/actions/localSystem.ts +2 -2
  134. package/src/store/chat/slices/builtinTool/actions/search.ts +8 -8
  135. package/src/store/chat/slices/message/action.test.ts +79 -68
  136. package/src/store/chat/slices/message/actions/index.ts +39 -0
  137. package/src/store/chat/slices/message/actions/internals.ts +77 -0
  138. package/src/store/chat/slices/message/actions/optimisticUpdate.ts +260 -0
  139. package/src/store/chat/slices/message/actions/publicApi.ts +224 -0
  140. package/src/store/chat/slices/message/actions/query.ts +120 -0
  141. package/src/store/chat/slices/message/actions/runtimeState.ts +108 -0
  142. package/src/store/chat/slices/message/initialState.ts +13 -0
  143. package/src/store/chat/slices/message/reducer.test.ts +48 -370
  144. package/src/store/chat/slices/message/reducer.ts +17 -81
  145. package/src/store/chat/slices/message/selectors/chat.test.ts +13 -50
  146. package/src/store/chat/slices/message/selectors/chat.ts +78 -242
  147. package/src/store/chat/slices/message/selectors/dbMessage.ts +140 -0
  148. package/src/store/chat/slices/message/selectors/displayMessage.ts +301 -0
  149. package/src/store/chat/slices/message/selectors/messageState.ts +5 -2
  150. package/src/store/chat/slices/plugin/action.test.ts +62 -64
  151. package/src/store/chat/slices/plugin/action.ts +34 -28
  152. package/src/store/chat/slices/thread/action.test.ts +28 -31
  153. package/src/store/chat/slices/thread/action.ts +13 -10
  154. package/src/store/chat/slices/thread/selectors/index.ts +8 -6
  155. package/src/store/chat/slices/topic/reducer.ts +11 -3
  156. package/src/store/chat/store.ts +1 -1
  157. package/src/store/user/slices/preference/selectors/labPrefer.ts +0 -3
  158. package/packages/database/src/models/__tests__/message.grouping.test.ts +0 -812
  159. package/packages/database/src/utils/__tests__/groupMessages.test.ts +0 -1132
  160. package/packages/database/src/utils/groupMessages.ts +0 -361
  161. package/packages/utils/src/tokenizer/client.ts +0 -35
  162. package/packages/utils/src/tokenizer/estimated.ts +0 -4
  163. package/packages/utils/src/tokenizer/server.ts +0 -11
  164. package/packages/utils/src/tokenizer/tokenizer.worker.ts +0 -12
  165. package/src/app/(backend)/webapi/tokenizer/index.test.ts +0 -32
  166. package/src/app/(backend)/webapi/tokenizer/route.ts +0 -8
  167. package/src/app/[variants]/(main)/chat/(workspace)/layout.ts +0 -11
  168. package/src/app/[variants]/(main)/chat/(workspace)/page.tsx +0 -53
  169. package/src/app/[variants]/(main)/chat/@session/default.tsx +0 -31
  170. package/src/app/[variants]/(main)/chat/settings/layout.tsx +0 -21
  171. package/src/features/Conversation/Error/InvalidAccessCode.tsx +0 -79
  172. package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts +0 -975
  173. package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +0 -1050
  174. package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +0 -720
  175. package/src/store/chat/slices/aiChat/actions/generateAIChatV2.ts +0 -849
  176. package/src/store/chat/slices/message/action.ts +0 -629
  177. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/default.tsx +0 -0
  178. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatHydration/index.tsx +0 -0
  179. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Desktop/ClassicChat.tsx +0 -0
  180. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Desktop/GroupChat.tsx +0 -0
  181. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Desktop/index.tsx +0 -0
  182. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Desktop/useSendMenuItems.tsx +0 -0
  183. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Mobile/MentionedUsers/MentionedUserItem.tsx +0 -0
  184. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Mobile/MentionedUsers/index.tsx +0 -0
  185. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/Mobile/index.tsx +0 -0
  186. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/ActionBar.tsx +0 -0
  187. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/Files/index.tsx +0 -0
  188. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/InputArea/Container.tsx +0 -0
  189. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/InputArea/index.tsx +0 -0
  190. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/V1Mobile/Send.tsx +0 -0
  191. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatInput/index.tsx +0 -0
  192. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/ChatItem/OrchestratorThinking.tsx +0 -0
  193. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/ChatItem/Thread.tsx +0 -0
  194. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/ChatItem/ThreadItem.tsx +0 -0
  195. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/AgentWelcome/AddButton.tsx +0 -0
  196. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/AgentWelcome/index.tsx +0 -0
  197. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/GroupWelcome/index.tsx +0 -0
  198. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/GroupWelcome/useTemplateMatching.ts +0 -0
  199. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/WelcomeChatItem/index.tsx +0 -0
  200. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatList/index.tsx +0 -0
  201. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ChatMinimap/index.tsx +0 -0
  202. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ThreadHydration.tsx +0 -0
  203. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ZenModeToast/Toast.tsx +0 -0
  204. /package/src/app/[variants]/(main)/chat/{(workspace)/@conversation → components/conversation}/features/ZenModeToast/index.tsx +0 -0
  205. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/AgentSettings/index.tsx +0 -0
  206. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/AgentTeamSettings/index.tsx +0 -0
  207. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/ChangelogModal.tsx +0 -0
  208. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/SettingButton.tsx +0 -0
  209. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/ShareButton/index.tsx +0 -0
  210. /package/src/app/[variants]/(main)/chat/{(workspace) → components}/features/TelemetryNotification.tsx +0 -0
  211. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/HeaderAction.tsx +0 -0
  212. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Main.tsx +0 -0
  213. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Tags/HistoryLimitTags.tsx +0 -0
  214. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Tags/KnowledgeTag.tsx +0 -0
  215. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Tags/MemberCountTag.tsx +0 -0
  216. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Tags/SearchTags.tsx +0 -0
  217. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/Tags/index.tsx +0 -0
  218. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/ChatHeader/index.tsx +0 -0
  219. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/Portal.tsx +0 -0
  220. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/TopicPanel.tsx +0 -0
  221. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Desktop/index.tsx +0 -0
  222. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Mobile/ChatHeader/ChatHeaderTitle.tsx +0 -0
  223. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Mobile/ChatHeader/index.tsx +0 -0
  224. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Mobile/TopicModal.tsx +0 -0
  225. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/Mobile/index.tsx +0 -0
  226. /package/src/app/[variants]/(main)/chat/{(workspace)/_layout → components/layout}/type.ts +0 -0
  227. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/_layout/Desktop.tsx +0 -0
  228. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/_layout/Mobile.tsx +0 -0
  229. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/default.tsx +0 -0
  230. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/error.tsx +0 -0
  231. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/features/Body.tsx +0 -0
  232. /package/src/app/[variants]/(main)/chat/{(workspace)/@portal → components/portal}/loading.tsx +0 -0
  233. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/_layout/Desktop.tsx +0 -0
  234. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/_layout/Mobile.tsx +0 -0
  235. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/default.tsx +0 -0
  236. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/AgentConfig/SystemRole.tsx +0 -0
  237. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/AgentConfig/index.tsx +0 -0
  238. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/ConfigLayout.tsx +0 -0
  239. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/ConfigSwitcher.tsx +0 -0
  240. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/GroupConfig/GroupMember.tsx +0 -0
  241. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/GroupConfig/GroupMemberItem.tsx +0 -0
  242. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/GroupConfig/GroupRole.tsx +0 -0
  243. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/GroupConfig/index.tsx +0 -0
  244. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/GroupConfig/style.ts +0 -0
  245. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/SkeletonList.tsx +0 -0
  246. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/Header.tsx +0 -0
  247. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/ByTimeMode/GroupItem.tsx +0 -0
  248. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/ByTimeMode/index.tsx +0 -0
  249. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/FlatMode/index.tsx +0 -0
  250. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/SearchResult/index.tsx +0 -0
  251. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/ThreadItem/Content.tsx +0 -0
  252. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/ThreadItem/index.tsx +0 -0
  253. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/ThreadList/index.tsx +0 -0
  254. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/TopicItem/DefaultContent.tsx +0 -0
  255. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/TopicItem/TopicContent.tsx +0 -0
  256. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/TopicItem/index.tsx +0 -0
  257. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicListContent/index.tsx +0 -0
  258. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/TopicSearchBar/index.tsx +0 -0
  259. /package/src/app/[variants]/(main)/chat/{(workspace)/@topic → components/topic}/features/Topic/index.tsx +0 -0
  260. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionHydration.tsx +0 -0
  261. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/CollapseGroup/Actions.tsx +0 -0
  262. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/CollapseGroup/index.tsx +0 -0
  263. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/DefaultMode.tsx +0 -0
  264. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/Inbox/index.tsx +0 -0
  265. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/List/AddButton.tsx +0 -0
  266. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/List/Item/Actions.tsx +0 -0
  267. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/List/Item/index.tsx +0 -0
  268. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/List/index.tsx +0 -0
  269. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/ListItem/index.tsx +0 -0
  270. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/Modals/ConfigGroupModal/GroupItem.tsx +0 -0
  271. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/Modals/ConfigGroupModal/index.tsx +0 -0
  272. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/Modals/CreateGroupModal.tsx +0 -0
  273. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/Modals/RenameGroupModal.tsx +0 -0
  274. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/SearchMode.tsx +0 -0
  275. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionListContent/index.tsx +0 -0
  276. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SessionSearchBar.tsx +0 -0
  277. /package/src/app/[variants]/(main)/chat/{@session → session}/features/SkeletonList.tsx +0 -0
  278. /package/src/app/[variants]/(main)/chat/{@session/_layout → session/layout}/Desktop/PanelBody.tsx +0 -0
  279. /package/src/app/[variants]/(main)/chat/{@session/_layout → session/layout}/Desktop/SessionHeader.tsx +0 -0
  280. /package/src/app/[variants]/(main)/chat/{@session/_layout → session/layout}/Desktop/index.tsx +0 -0
  281. /package/src/app/[variants]/(main)/chat/{@session/_layout → session/layout}/Mobile/SessionHeader.tsx +0 -0
  282. /package/src/app/[variants]/(main)/chat/{@session/_layout → session/layout}/Mobile/index.tsx +0 -0
@@ -4,17 +4,15 @@ import { ActionIconGroupItemType } from '@lobehub/ui/es/ActionIconGroup';
4
4
  import { ActionIconGroupEvent } from '@lobehub/ui/es/ActionIconGroup/type';
5
5
  import { App } from 'antd';
6
6
  import { useSearchParams } from 'next/navigation';
7
- import { memo, use, useCallback, useMemo } from 'react';
7
+ import { memo, use, useCallback } from 'react';
8
8
  import { useTranslation } from 'react-i18next';
9
9
 
10
10
  import { useChatStore } from '@/store/chat';
11
- import { threadSelectors } from '@/store/chat/selectors';
12
- import { useSessionStore } from '@/store/session';
13
- import { sessionSelectors } from '@/store/session/selectors';
11
+ import { messageStateSelectors, threadSelectors } from '@/store/chat/selectors';
14
12
 
15
- import { VirtuosoContext } from '../../components/VirtualizedList/VirtuosoContext';
16
- import { InPortalThreadContext } from '../../context/InPortalThreadContext';
17
- import { useChatListActionsBar } from '../../hooks/useChatListActionsBar';
13
+ import { VirtuosoContext } from '../../../components/VirtualizedList/VirtuosoContext';
14
+ import { InPortalThreadContext } from '../../../context/InPortalThreadContext';
15
+ import { useChatListActionsBar } from '../../../hooks/useChatListActionsBar';
18
16
 
19
17
  interface UserActionsProps {
20
18
  data: UIChatMessage;
@@ -28,11 +26,12 @@ export const UserActionsBar = memo<UserActionsProps>(({ id, data, index }) => {
28
26
  const topic = searchParams.get('topic');
29
27
 
30
28
  const [
31
- isThreadMode,
29
+ // isThreadMode,
32
30
  hasThread,
31
+ isRegenerating,
33
32
  toggleMessageEditing,
34
33
  deleteMessage,
35
- regenerateMessage,
34
+ regenerateUserMessage,
36
35
  translateMessage,
37
36
  ttsMessage,
38
37
  delAndRegenerateMessage,
@@ -41,12 +40,13 @@ export const UserActionsBar = memo<UserActionsProps>(({ id, data, index }) => {
41
40
  resendThreadMessage,
42
41
  delAndResendThreadMessage,
43
42
  ] = useChatStore((s) => [
44
- !!s.activeThreadId,
43
+ // !!s.activeThreadId,
45
44
  threadSelectors.hasThreadBySourceMsgId(id)(s),
45
+ messageStateSelectors.isMessageRegenerating(id)(s),
46
46
 
47
47
  s.toggleMessageEditing,
48
48
  s.deleteMessage,
49
- s.regenerateMessage,
49
+ s.regenerateUserMessage,
50
50
  s.translateMessage,
51
51
  s.ttsMessage,
52
52
  s.delAndRegenerateMessage,
@@ -56,22 +56,21 @@ export const UserActionsBar = memo<UserActionsProps>(({ id, data, index }) => {
56
56
  s.delAndResendThreadMessage,
57
57
  ]);
58
58
 
59
- const isGroupSession = useSessionStore(sessionSelectors.isCurrentSessionGroupSession);
59
+ // const isGroupSession = useSessionStore(sessionSelectors.isCurrentSessionGroupSession);
60
60
 
61
- const { regenerate, edit, copy, divider, del, branching, tts, translate } = useChatListActionsBar(
62
- { hasThread },
63
- );
61
+ const { regenerate, edit, copy, divider, del, tts, translate } = useChatListActionsBar({
62
+ hasThread,
63
+ isRegenerating,
64
+ });
64
65
 
65
66
  const inPortalThread = use(InPortalThreadContext);
66
- const inThread = isThreadMode || inPortalThread;
67
-
68
- const items = useMemo(
69
- () =>
70
- [regenerate, edit, inThread || isGroupSession ? null : branching].filter(
71
- Boolean,
72
- ) as ActionIconGroupItemType[],
73
- [inThread, isGroupSession],
74
- );
67
+ // const inThread = isThreadMode || inPortalThread;
68
+
69
+ const items = [
70
+ regenerate,
71
+ edit,
72
+ // inThread || isGroupSession ? null : branching
73
+ ].filter(Boolean) as ActionIconGroupItemType[];
75
74
 
76
75
  const { message } = App.useApp();
77
76
 
@@ -113,7 +112,7 @@ export const UserActionsBar = memo<UserActionsProps>(({ id, data, index }) => {
113
112
  case 'regenerate': {
114
113
  if (inPortalThread) {
115
114
  resendThreadMessage(id);
116
- } else regenerateMessage(id);
115
+ } else regenerateUserMessage(id);
117
116
 
118
117
  // if this message is an error message, we need to delete it
119
118
  if (data.error) deleteMessage(id);
@@ -153,6 +152,8 @@ export const UserActionsBar = memo<UserActionsProps>(({ id, data, index }) => {
153
152
  items: [edit, copy, divider, tts, translate, divider, regenerate, del],
154
153
  }}
155
154
  onActionClick={onActionClick}
155
+ size={'small'}
156
+ variant={'borderless'}
156
157
  />
157
158
  );
158
159
  });
@@ -0,0 +1,107 @@
1
+ import { Icon } from '@lobehub/ui';
2
+ import { createStyles } from 'antd-style';
3
+ import { ChevronLeft, ChevronRight } from 'lucide-react';
4
+ import { memo } from 'react';
5
+ import { Center, Flexbox } from 'react-layout-kit';
6
+
7
+ import { useChatStore } from '@/store/chat';
8
+
9
+ const useStyles = createStyles(({ css, token, prefixCls }) => ({
10
+ button: css`
11
+ cursor: pointer;
12
+
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+
17
+ width: 20px;
18
+ height: 20px;
19
+ border-radius: 4px;
20
+
21
+ color: ${token.colorTextSecondary};
22
+
23
+ transition: all 0.2s ease;
24
+
25
+ &:hover:not(.${prefixCls}-disabled) {
26
+ color: ${token.colorText};
27
+ background: ${token.colorFillSecondary};
28
+ }
29
+
30
+ &.${prefixCls}-disabled {
31
+ cursor: not-allowed;
32
+ opacity: 0.4;
33
+ }
34
+ `,
35
+ container: css`
36
+ user-select: none;
37
+
38
+ display: inline-flex;
39
+ gap: 4px;
40
+ align-items: center;
41
+
42
+ height: 20px;
43
+ padding-inline: 4px;
44
+ border-radius: ${token.borderRadiusSM}px;
45
+ `,
46
+ text: css`
47
+ min-width: 24px;
48
+ height: 20px;
49
+
50
+ font-size: 12px;
51
+ font-variant-numeric: tabular-nums;
52
+ color: ${token.colorTextSecondary};
53
+ text-align: center;
54
+ `,
55
+ }));
56
+
57
+ interface MessageBranchProps {
58
+ activeBranchIndex: number;
59
+ count: number;
60
+ messageId: string;
61
+ }
62
+
63
+ const MessageBranch = memo<MessageBranchProps>(({ activeBranchIndex, count, messageId }) => {
64
+ const { styles, cx, prefixCls } = useStyles();
65
+ const switchMessageBranch = useChatStore((s) => s.switchMessageBranch);
66
+
67
+ const handlePrevious = () => {
68
+ if (activeBranchIndex > 0) {
69
+ switchMessageBranch(messageId, activeBranchIndex - 1);
70
+ }
71
+ };
72
+
73
+ const handleNext = () => {
74
+ if (activeBranchIndex < count - 1) {
75
+ switchMessageBranch(messageId, activeBranchIndex + 1);
76
+ }
77
+ };
78
+
79
+ const canGoPrevious = activeBranchIndex > 0;
80
+ const canGoNext = activeBranchIndex < count - 1;
81
+
82
+ return (
83
+ <Flexbox className={styles.container} horizontal>
84
+ <div
85
+ className={cx(styles.button, !canGoPrevious && `${prefixCls}-disabled`)}
86
+ onClick={handlePrevious}
87
+ role="button"
88
+ tabIndex={canGoPrevious ? 0 : -1}
89
+ >
90
+ <Icon icon={ChevronLeft} size={16} />
91
+ </div>
92
+ <Center className={styles.text}>
93
+ {activeBranchIndex + 1}/{count}
94
+ </Center>
95
+ <div
96
+ className={cx(styles.button, !canGoNext && `${prefixCls}-disabled`)}
97
+ onClick={handleNext}
98
+ role="button"
99
+ tabIndex={canGoNext ? 0 : -1}
100
+ >
101
+ <Icon icon={ChevronRight} size={16} />
102
+ </div>
103
+ </Flexbox>
104
+ );
105
+ });
106
+
107
+ export default MessageBranch;
@@ -0,0 +1,42 @@
1
+ import { memo } from 'react';
2
+ import { Flexbox } from 'react-layout-kit';
3
+
4
+ import { useChatStore } from '@/store/chat';
5
+ import { messageStateSelectors } from '@/store/chat/selectors';
6
+ import { UIChatMessage } from '@/types/index';
7
+
8
+ import { UserActionsBar } from './ActionsBar';
9
+ import MessageBranch from './MessageBranch';
10
+
11
+ interface ActionsProps {
12
+ data: UIChatMessage;
13
+ disableEditing?: boolean;
14
+ id: string;
15
+ index: number;
16
+ }
17
+
18
+ const Actions = memo<ActionsProps>(({ id, data, index, disableEditing }) => {
19
+ const { branch } = data;
20
+ const [editing] = useChatStore((s) => [messageStateSelectors.isMessageEditing(id)(s)]);
21
+
22
+ return (
23
+ !editing && (
24
+ <Flexbox align={'center'} horizontal>
25
+ {!disableEditing && (
26
+ <Flexbox align={'flex-start'} role="menubar">
27
+ <UserActionsBar data={data} id={id} index={index} />
28
+ </Flexbox>
29
+ )}
30
+ {branch && (
31
+ <MessageBranch
32
+ activeBranchIndex={branch.activeBranchIndex}
33
+ count={branch.count}
34
+ messageId={id}
35
+ />
36
+ )}
37
+ </Flexbox>
38
+ )
39
+ );
40
+ });
41
+
42
+ export default Actions;
@@ -22,7 +22,7 @@ import { useUserStore } from '@/store/user';
22
22
  import { userProfileSelectors } from '@/store/user/selectors';
23
23
 
24
24
  import { useDoubleClickEdit } from '../../hooks/useDoubleClickEdit';
25
- import { UserActionsBar } from './Actions';
25
+ import Actions from './Actions';
26
26
  import { UserBelowMessage } from './BelowMessage';
27
27
  import { UserMessageExtra } from './Extra';
28
28
  import { MarkdownRender as UserMarkdownRender } from './MarkdownRender';
@@ -127,60 +127,59 @@ const UserMessage = memo<UserMessageProps>((props) => {
127
127
  );
128
128
 
129
129
  return (
130
- <Flexbox
131
- className={styles.container}
132
- direction={placement === 'left' ? 'horizontal' : 'horizontal-reverse'}
133
- gap={mobile ? 6 : 12}
134
- >
135
- <Avatar
136
- alt={title}
137
- avatar={{ avatar, title }}
138
- loading={loading}
139
- placement={placement}
140
- size={mobile ? 32 : undefined}
141
- style={{ marginTop: 6 }}
142
- />
130
+ <Flexbox className={styles.container} gap={8}>
143
131
  <Flexbox
144
- align={placement === 'left' ? 'flex-start' : 'flex-end'}
145
- className={styles.messageContainer}
132
+ direction={placement === 'left' ? 'horizontal' : 'horizontal-reverse'}
133
+ gap={mobile ? 6 : 12}
146
134
  >
147
- <Title
135
+ <Avatar
136
+ alt={title}
148
137
  avatar={{ avatar, title }}
138
+ loading={loading}
149
139
  placement={placement}
150
- showTitle={false}
151
- time={createdAt}
152
- titleAddon={dmIndicator}
140
+ size={32}
141
+ style={{ marginTop: 6 }}
153
142
  />
154
143
  <Flexbox
155
144
  align={placement === 'left' ? 'flex-start' : 'flex-end'}
156
- className={styles.messageContent}
157
- direction={placement === 'left' ? 'horizontal' : 'horizontal-reverse'}
158
- gap={8}
145
+ className={styles.messageContainer}
159
146
  >
160
- <Flexbox flex={1} style={{ maxWidth: '100%', minWidth: 0 }}>
161
- <MessageContent
162
- editing={editing}
163
- id={id}
164
- markdownProps={markdownProps}
165
- message={content}
166
- messageExtra={<UserMessageExtra content={content} extra={extra} id={id} />}
167
- onDoubleClick={onDoubleClick}
168
- placement={placement}
169
- primary
170
- renderMessage={renderMessage}
171
- variant={variant}
172
- />
173
- </Flexbox>
174
-
175
- {!disableEditing && !editing && (
176
- <Flexbox align={'flex-start'} className={styles.actions} role="menubar">
177
- <UserActionsBar data={props} id={id} index={index} />
147
+ <Title
148
+ avatar={{ avatar, title }}
149
+ placement={placement}
150
+ showTitle={false}
151
+ time={createdAt}
152
+ titleAddon={dmIndicator}
153
+ />
154
+ <Flexbox
155
+ align={placement === 'left' ? 'flex-start' : 'flex-end'}
156
+ className={styles.messageContent}
157
+ direction={placement === 'left' ? 'horizontal' : 'horizontal-reverse'}
158
+ gap={8}
159
+ >
160
+ <Flexbox flex={1} style={{ maxWidth: '100%', minWidth: 0 }}>
161
+ <MessageContent
162
+ editing={editing}
163
+ id={id}
164
+ markdownProps={markdownProps}
165
+ message={content}
166
+ messageExtra={<UserMessageExtra content={content} extra={extra} id={id} />}
167
+ onDoubleClick={onDoubleClick}
168
+ placement={placement}
169
+ primary
170
+ renderMessage={renderMessage}
171
+ variant={variant}
172
+ />
178
173
  </Flexbox>
179
- )}
174
+ </Flexbox>
175
+ <UserBelowMessage content={content} id={id} ragQuery={ragQuery} />
180
176
  </Flexbox>
181
- <UserBelowMessage content={content} id={id} ragQuery={ragQuery} />
177
+ {mobile && variant === 'bubble' && <BorderSpacing borderSpacing={32} />}
178
+ </Flexbox>
179
+
180
+ <Flexbox direction={'horizontal-reverse'}>
181
+ <Actions data={props} disableEditing={disableEditing} id={id} index={index} />
182
182
  </Flexbox>
183
- {mobile && variant === 'bubble' && <BorderSpacing borderSpacing={32} />}
184
183
  </Flexbox>
185
184
  );
186
185
  });
@@ -11,7 +11,7 @@ import {
11
11
  upsertVirtuosoVisibleItem,
12
12
  } from '@/features/Conversation/components/VirtualizedList/VirtuosoContext';
13
13
  import { useChatStore } from '@/store/chat';
14
- import { chatSelectors, messageStateSelectors } from '@/store/chat/selectors';
14
+ import { displayMessageSelectors, messageStateSelectors } from '@/store/chat/selectors';
15
15
 
16
16
  import History from '../components/History';
17
17
  import { InPortalThreadContext } from '../context/InPortalThreadContext';
@@ -56,7 +56,7 @@ const Item = memo<ChatListItemProps>(
56
56
  const { styles, cx } = useStyles();
57
57
  const containerRef = useRef<HTMLDivElement | null>(null);
58
58
 
59
- const item = useChatStore(chatSelectors.getMessageById(id), isEqual);
59
+ const item = useChatStore(displayMessageSelectors.getDisplayMessageById(id), isEqual);
60
60
 
61
61
  const [isMessageLoading] = useChatStore((s) => [messageStateSelectors.isMessageLoading(id)(s)]);
62
62
 
@@ -133,7 +133,7 @@ const Item = memo<ChatListItemProps>(
133
133
  );
134
134
  }
135
135
 
136
- case 'group': {
136
+ case 'assistantGroup': {
137
137
  return (
138
138
  <GroupMessage
139
139
  {...item}
@@ -1,7 +1,7 @@
1
1
  import { memo, useEffect } from 'react';
2
2
 
3
3
  import { useChatStore } from '@/store/chat';
4
- import { chatSelectors, messageStateSelectors } from '@/store/chat/selectors';
4
+ import { displayMessageSelectors, messageStateSelectors } from '@/store/chat/selectors';
5
5
 
6
6
  import BackBottom from './BackBottom';
7
7
 
@@ -12,8 +12,8 @@ interface AutoScrollProps {
12
12
  }
13
13
  const AutoScroll = memo<AutoScrollProps>(({ atBottom, isScrolling, onScrollToBottom }) => {
14
14
  const trackVisibility = useChatStore(messageStateSelectors.isAIGenerating);
15
- const str = useChatStore(chatSelectors.mainAIChatsMessageString);
16
- const reasoningStr = useChatStore(chatSelectors.mainAILatestMessageReasoningContent);
15
+ const str = useChatStore(displayMessageSelectors.mainAIChatsMessageString);
16
+ const reasoningStr = useChatStore(displayMessageSelectors.mainAILatestMessageReasoningContent);
17
17
 
18
18
  useEffect(() => {
19
19
  if (atBottom && trackVisibility && !isScrolling) {
@@ -0,0 +1,55 @@
1
+ import { memo, useEffect, useRef, useState } from 'react';
2
+
3
+ interface AnimatedNumberProps {
4
+ duration?: number;
5
+ formatter?: (value: number) => string;
6
+ value: number;
7
+ }
8
+
9
+ const AnimatedNumber = memo<AnimatedNumberProps>(({ value, duration = 3000, formatter }) => {
10
+ const [displayValue, setDisplayValue] = useState(value);
11
+ const frameRef = useRef<number>(undefined);
12
+ const startTimeRef = useRef<number>(undefined);
13
+ const startValueRef = useRef(value);
14
+
15
+ useEffect(() => {
16
+ const startValue = startValueRef.current;
17
+ const diff = value - startValue;
18
+
19
+ if (diff === 0) return;
20
+
21
+ const animate = (currentTime: number) => {
22
+ if (!startTimeRef.current) {
23
+ startTimeRef.current = currentTime;
24
+ }
25
+
26
+ const elapsed = currentTime - startTimeRef.current;
27
+ const progress = Math.min(elapsed / duration, 1);
28
+
29
+ // 使用 easeOutCubic 缓动函数
30
+ const easeProgress = 1 - (1 - progress) ** 3;
31
+ const current = startValue + diff * easeProgress;
32
+
33
+ setDisplayValue(current);
34
+
35
+ if (progress < 1) {
36
+ frameRef.current = requestAnimationFrame(animate);
37
+ } else {
38
+ startValueRef.current = value;
39
+ startTimeRef.current = undefined;
40
+ }
41
+ };
42
+
43
+ frameRef.current = requestAnimationFrame(animate);
44
+
45
+ return () => {
46
+ if (frameRef.current) {
47
+ cancelAnimationFrame(frameRef.current);
48
+ }
49
+ };
50
+ }, [value, duration]);
51
+
52
+ return formatter ? formatter(displayValue) : displayValue.toString();
53
+ });
54
+
55
+ export default AnimatedNumber;
@@ -13,6 +13,7 @@ import { useGlobalStore } from '@/store/global';
13
13
  import { systemStatusSelectors } from '@/store/global/selectors';
14
14
  import { formatNumber, formatShortenNumber } from '@/utils/format';
15
15
 
16
+ import AnimatedNumber from './AnimatedNumber';
16
17
  import ModelCard from './ModelCard';
17
18
  import TokenProgress, { TokenProgressItem } from './TokenProgress';
18
19
  import { getDetailsToken } from './tokens';
@@ -116,7 +117,6 @@ const TokenDetail = memo<TokenDetailProps>(({ meta, model, provider }) => {
116
117
  ? detailTokens.totalTokens.credit
117
118
  : detailTokens.totalTokens!.token;
118
119
 
119
- const shortTotal = (formatShortenNumber(totalCount) as string).toLowerCase?.();
120
120
  const detailTotal = formatNumber(totalCount);
121
121
 
122
122
  const averagePricing = formatNumber(
@@ -215,7 +215,10 @@ const TokenDetail = memo<TokenDetailProps>(({ meta, model, provider }) => {
215
215
  >
216
216
  <Center gap={2} horizontal style={{ cursor: 'default' }}>
217
217
  <Icon icon={isShowCredit ? BadgeCent : CoinsIcon} />
218
- {shortTotal}
218
+ <AnimatedNumber
219
+ formatter={(value) => (formatShortenNumber(value) as string).toLowerCase?.()}
220
+ value={totalCount}
221
+ />
219
222
  </Center>
220
223
  </Popover>
221
224
  );
@@ -1,16 +1,29 @@
1
1
  'use client';
2
2
 
3
- import { ReactNode, forwardRef, memo, useCallback, useEffect, useRef, useState } from 'react';
3
+ import {
4
+ ReactNode,
5
+ forwardRef,
6
+ memo,
7
+ useCallback,
8
+ useEffect,
9
+ useMemo,
10
+ useRef,
11
+ useState,
12
+ } from 'react';
4
13
  import { Flexbox } from 'react-layout-kit';
5
14
  import { Virtuoso, VirtuosoHandle } from 'react-virtuoso';
6
15
 
7
16
  import WideScreenContainer from '@/features/Conversation/components/WideScreenContainer';
8
17
  import { useChatStore } from '@/store/chat';
9
- import { chatSelectors } from '@/store/chat/selectors';
18
+ import { displayMessageSelectors } from '@/store/chat/selectors';
10
19
 
11
20
  import AutoScroll from '../AutoScroll';
12
21
  import SkeletonList from '../SkeletonList';
13
- import { VirtuosoContext, resetVirtuosoVisibleItems, setVirtuosoGlobalRef } from './VirtuosoContext';
22
+ import {
23
+ VirtuosoContext,
24
+ resetVirtuosoVisibleItems,
25
+ setVirtuosoGlobalRef,
26
+ } from './VirtuosoContext';
14
27
 
15
28
  interface VirtualizedListProps {
16
29
  dataSource: string[];
@@ -32,10 +45,9 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile, dataSource, itemCo
32
45
  const [atBottom, setAtBottom] = useState(true);
33
46
  const [isScrolling, setIsScrolling] = useState(false);
34
47
 
35
- const [id, isFirstLoading, isCurrentChatLoaded] = useChatStore((s) => [
36
- chatSelectors.currentChatKey(s),
37
- chatSelectors.currentChatLoadingState(s),
38
- chatSelectors.isCurrentChatLoaded(s),
48
+ const [isFirstLoading, isCurrentChatLoaded] = useChatStore((s) => [
49
+ displayMessageSelectors.currentChatLoadingState(s),
50
+ displayMessageSelectors.isCurrentDisplayChatLoaded(s),
39
51
  ]);
40
52
 
41
53
  const getFollowOutput = useCallback(() => {
@@ -53,9 +65,8 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile, dataSource, itemCo
53
65
  [atBottom],
54
66
  );
55
67
 
56
- useEffect(() => {
57
- scrollToBottom();
58
- }, [id]);
68
+ const components = useMemo(() => ({ List }), []);
69
+ const computeItemKey = useCallback((index: number, item: string) => item, []);
59
70
 
60
71
  useEffect(() => {
61
72
  setVirtuosoGlobalRef(virtuosoRef);
@@ -71,8 +82,8 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile, dataSource, itemCo
71
82
  };
72
83
  }, []);
73
84
 
74
- // overscan should be 3 times the height of the window
75
- const overscan = typeof window !== 'undefined' ? window.innerHeight * 3 : 0;
85
+ // overscan should be 2 times the height of the window
86
+ const overscan = typeof window !== 'undefined' ? window.innerHeight * 2 : 0;
76
87
 
77
88
  // first time loading or not loaded
78
89
  if (isFirstLoading || !isCurrentChatLoaded) return <SkeletonList mobile={mobile} />;
@@ -81,12 +92,9 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile, dataSource, itemCo
81
92
  <VirtuosoContext value={virtuosoRef}>
82
93
  <Virtuoso
83
94
  atBottomStateChange={setAtBottom}
84
- atBottomThreshold={50 * (mobile ? 2 : 1)}
85
- components={{
86
- List,
87
- }}
88
-
89
- computeItemKey={(_, item) => item}
95
+ atBottomThreshold={200 * (mobile ? 2 : 1)}
96
+ components={components}
97
+ computeItemKey={computeItemKey}
90
98
  data={dataSource}
91
99
  followOutput={getFollowOutput}
92
100
  increaseViewportBy={overscan}
@@ -108,13 +116,14 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile, dataSource, itemCo
108
116
  atBottom={atBottom}
109
117
  isScrolling={isScrolling}
110
118
  onScrollToBottom={(type) => {
119
+ const virtuoso = virtuosoRef.current;
111
120
  switch (type) {
112
121
  case 'auto': {
113
- scrollToBottom();
122
+ virtuoso?.scrollToIndex({ align: 'end', behavior: 'auto', index: 'LAST' });
114
123
  break;
115
124
  }
116
125
  case 'click': {
117
- scrollToBottom('smooth');
126
+ virtuoso?.scrollToIndex({ align: 'end', behavior: 'smooth', index: 'LAST' });
118
127
  break;
119
128
  }
120
129
  }
@@ -15,7 +15,6 @@ import {
15
15
  import { useMemo } from 'react';
16
16
  import { useTranslation } from 'react-i18next';
17
17
 
18
- import { isDeprecatedEdition } from '@/const/version';
19
18
  import { localeOptions } from '@/locales/resources';
20
19
 
21
20
  const translateStyle = css`
@@ -41,18 +40,16 @@ interface ChatListActionsBar {
41
40
 
42
41
  export const useChatListActionsBar = ({
43
42
  hasThread,
44
- }: { hasThread?: boolean } = {}): ChatListActionsBar => {
43
+ isRegenerating,
44
+ }: { hasThread?: boolean; isRegenerating?: boolean } = {}): ChatListActionsBar => {
45
45
  const { t } = useTranslation(['common', 'chat']);
46
46
 
47
- return useMemo(
47
+ return useMemo<ChatListActionsBar>(
48
48
  () => ({
49
49
  branching: {
50
- disable: isDeprecatedEdition || undefined,
51
50
  icon: Split,
52
51
  key: 'branching',
53
- label: !isDeprecatedEdition
54
- ? t('branching', { defaultValue: 'Create Sub Topic' })
55
- : t('branchingDisable'),
52
+ label: t('branching', { defaultValue: 'Create Sub Topic' }),
56
53
  },
57
54
  copy: {
58
55
  icon: Copy,
@@ -61,13 +58,13 @@ export const useChatListActionsBar = ({
61
58
  },
62
59
  del: {
63
60
  danger: true,
64
- disable: hasThread || undefined,
61
+ disabled: hasThread,
65
62
  icon: Trash,
66
63
  key: 'del',
67
64
  label: hasThread ? t('messageAction.deleteDisabledByThreads', { ns: 'chat' }) : t('delete'),
68
65
  },
69
66
  delAndRegenerate: {
70
- disable: hasThread || undefined,
67
+ disabled: hasThread || isRegenerating,
71
68
  icon: ListRestart,
72
69
  key: 'delAndRegenerate',
73
70
  label: t('messageAction.delAndRegenerate', {
@@ -89,6 +86,7 @@ export const useChatListActionsBar = ({
89
86
  label: '导出为 PDF',
90
87
  },
91
88
  regenerate: {
89
+ disabled: isRegenerating,
92
90
  icon: RotateCcw,
93
91
  key: 'regenerate',
94
92
  label: t('regenerate', { defaultValue: 'Regenerate' }),
@@ -114,6 +112,6 @@ export const useChatListActionsBar = ({
114
112
  label: t('tts.action', { ns: 'chat' }),
115
113
  },
116
114
  }),
117
- [hasThread],
115
+ [hasThread, isRegenerating],
118
116
  );
119
117
  };
@@ -3,7 +3,7 @@
3
3
  import { memo } from 'react';
4
4
  import { Flexbox } from 'react-layout-kit';
5
5
 
6
- import ChatInput from '@/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput';
6
+ import ChatInput from '@/app/[variants]/(main)/chat/components/conversation/features/ChatInput';
7
7
  import { useChatGroupStore } from '@/store/chatGroup';
8
8
 
9
9
  import ThreadChatList from './ThreadChatList';