@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
@@ -165,18 +165,74 @@ export class FlatListBuilder {
165
165
  childMessages,
166
166
  this.childrenMap,
167
167
  );
168
- const userWithBranches = this.createUserMessageWithBranches(message);
168
+ const activeBranchIndex = childMessages.indexOf(activeBranchId);
169
+ const userWithBranches = this.createUserMessageWithBranches(
170
+ message,
171
+ childMessages.length,
172
+ activeBranchIndex,
173
+ );
169
174
  flatList.push(userWithBranches);
170
175
  processedIds.add(message.id);
171
176
 
172
- // Continue with active branch and process its message
177
+ // Continue with active branch - check if it's an assistantGroup
173
178
  const activeBranchMsg = this.messageMap.get(activeBranchId);
174
179
  if (activeBranchMsg) {
175
- flatList.push(activeBranchMsg);
176
- processedIds.add(activeBranchId);
177
-
178
- // Continue with active branch's children
179
- this.buildFlatListRecursive(activeBranchId, flatList, processedIds, allMessages);
180
+ // Check if active branch is assistant with tools (should be assistantGroup)
181
+ if (
182
+ activeBranchMsg.role === 'assistant' &&
183
+ activeBranchMsg.tools &&
184
+ activeBranchMsg.tools.length > 0
185
+ ) {
186
+ // Collect the entire assistant group chain
187
+ const assistantChain: Message[] = [];
188
+ const allToolMessages: Message[] = [];
189
+ this.messageCollector.collectAssistantChain(
190
+ activeBranchMsg,
191
+ allMessages,
192
+ assistantChain,
193
+ allToolMessages,
194
+ processedIds,
195
+ );
196
+
197
+ // Create assistantGroup virtual message
198
+ const groupMessage = this.createAssistantGroupMessage(
199
+ assistantChain[0],
200
+ assistantChain,
201
+ allToolMessages,
202
+ );
203
+ flatList.push(groupMessage);
204
+
205
+ // Mark all as processed
206
+ assistantChain.forEach((m) => processedIds.add(m.id));
207
+ allToolMessages.forEach((m) => processedIds.add(m.id));
208
+
209
+ // Continue after the assistant chain
210
+ const lastAssistant = assistantChain.at(-1);
211
+ const toolIds = new Set(allToolMessages.map((t) => t.id));
212
+
213
+ const lastAssistantNonToolChildren = lastAssistant
214
+ ? this.childrenMap.get(lastAssistant.id)?.filter((childId) => !toolIds.has(childId))
215
+ : undefined;
216
+
217
+ if (
218
+ lastAssistantNonToolChildren &&
219
+ lastAssistantNonToolChildren.length > 0 &&
220
+ lastAssistant
221
+ ) {
222
+ this.buildFlatListRecursive(lastAssistant.id, flatList, processedIds, allMessages);
223
+ } else {
224
+ for (const toolMsg of allToolMessages) {
225
+ this.buildFlatListRecursive(toolMsg.id, flatList, processedIds, allMessages);
226
+ }
227
+ }
228
+ } else {
229
+ // Regular message (not assistantGroup)
230
+ flatList.push(activeBranchMsg);
231
+ processedIds.add(activeBranchId);
232
+
233
+ // Continue with active branch's children
234
+ this.buildFlatListRecursive(activeBranchId, flatList, processedIds, allMessages);
235
+ }
180
236
  }
181
237
  continue;
182
238
  }
@@ -364,58 +420,80 @@ export class FlatListBuilder {
364
420
  assistant.tools?.map((tool) => {
365
421
  const toolMsg = toolMap.get(tool.id);
366
422
  if (toolMsg) {
423
+ const result: any = {
424
+ content: toolMsg.content || '',
425
+ id: toolMsg.id,
426
+ };
427
+ if (toolMsg.error) result.error = toolMsg.error;
428
+ if (toolMsg.pluginState) result.state = toolMsg.pluginState;
429
+
367
430
  return {
368
431
  ...tool,
369
- result: {
370
- content: toolMsg.content || '',
371
- error: toolMsg.error,
372
- id: toolMsg.id,
373
- state: toolMsg.pluginState,
374
- },
432
+ result,
375
433
  result_msg_id: toolMsg.id,
376
434
  };
377
435
  }
378
436
  return tool;
379
437
  }) || [];
380
438
 
381
- const { usage: msgUsage, performance: msgPerformance } =
439
+ // Prefer top-level usage/performance fields, fall back to metadata
440
+ const { usage: metaUsage, performance: metaPerformance } =
382
441
  this.messageTransformer.splitMetadata(assistant.metadata);
442
+ const msgUsage = assistant.usage || metaUsage;
443
+ const msgPerformance = assistant.performance || metaPerformance;
383
444
 
384
- children.push({
445
+ const childBlock: AssistantContentBlock = {
385
446
  content: assistant.content || '',
386
- error: assistant.error,
387
447
  id: assistant.id,
388
- imageList:
389
- assistant.imageList && assistant.imageList.length > 0 ? assistant.imageList : undefined,
390
- performance: msgPerformance,
391
- reasoning: assistant.reasoning || undefined,
392
- tools: toolsWithResults.length > 0 ? toolsWithResults : undefined,
393
- usage: msgUsage,
394
- });
448
+ } as AssistantContentBlock;
449
+
450
+ if (assistant.error) childBlock.error = assistant.error;
451
+ if (assistant.imageList && assistant.imageList.length > 0)
452
+ childBlock.imageList = assistant.imageList;
453
+ if (msgPerformance) childBlock.performance = msgPerformance;
454
+ if (assistant.reasoning) childBlock.reasoning = assistant.reasoning;
455
+ if (toolsWithResults.length > 0) childBlock.tools = toolsWithResults;
456
+ if (msgUsage) childBlock.usage = msgUsage;
457
+
458
+ children.push(childBlock);
395
459
  }
396
460
 
397
461
  const aggregated = this.messageTransformer.aggregateMetadata(children);
398
462
 
399
- return {
463
+ const result: Message = {
400
464
  ...firstAssistant,
401
465
  children,
402
466
  content: '',
403
- imageList: undefined,
404
- metadata: undefined,
405
- performance: aggregated.performance,
406
- reasoning: undefined,
407
467
  role: 'assistantGroup' as any,
408
- tools: undefined,
409
- usage: aggregated.usage,
410
468
  };
469
+
470
+ // Remove fields that should not be in assistantGroup
471
+ delete result.imageList;
472
+ delete result.metadata;
473
+ delete result.reasoning;
474
+ delete result.tools;
475
+
476
+ // Add aggregated fields if they exist
477
+ if (aggregated.performance) result.performance = aggregated.performance;
478
+ if (aggregated.usage) result.usage = aggregated.usage;
479
+
480
+ return result;
411
481
  }
412
482
 
413
483
  /**
414
484
  * Create user message with branch metadata
415
485
  */
416
- private createUserMessageWithBranches(user: Message): Message {
417
- // Just return the original user message with its metadata.activeBranchId
418
- // No need to add extra.branches
419
- return { ...user };
486
+ private createUserMessageWithBranches(
487
+ user: Message,
488
+ count: number,
489
+ activeBranchIndex: number,
490
+ ): Message {
491
+ return {
492
+ ...user,
493
+ branch: {
494
+ activeBranchIndex,
495
+ count,
496
+ },
497
+ } as Message;
420
498
  }
421
499
  }
@@ -41,22 +41,10 @@ export type FlatMessageRole =
41
41
  */
42
42
  export type FlatMessage = UIChatMessage;
43
43
 
44
- /**
45
- * Branch metadata attached to user messages
46
- */
47
- export interface BranchMetadata {
48
- /** Active branch message ID */
49
- activeId: string;
50
- /** All branch message IDs */
51
- branchIds: string[];
52
- }
53
-
54
44
  /**
55
45
  * Virtual message extra fields for flat list
56
46
  */
57
47
  export interface FlatMessageExtra {
58
- /** Branch information for user messages with multiple children */
59
- branches?: BranchMetadata;
60
48
  /** Optional description for groups */
61
49
  description?: string;
62
50
  /** Group mode for messageGroup and compare virtual messages */
@@ -16,21 +16,10 @@ export type {
16
16
  CompareNode,
17
17
  ContextNode,
18
18
  MessageNode,
19
- } from './types/contextTree';
19
+ } from './contextTree';
20
20
 
21
21
  // Flat Message List Types
22
- export type {
23
- BranchMetadata,
24
- FlatMessage,
25
- FlatMessageExtra,
26
- FlatMessageRole,
27
- } from './types/flatMessageList';
22
+ export type { FlatMessage, FlatMessageExtra, FlatMessageRole } from './flatMessageList';
28
23
 
29
24
  // Shared Types
30
- export type {
31
- HelperMaps,
32
- IdNode,
33
- Message,
34
- MessageGroupMetadata,
35
- ParseResult,
36
- } from './types/shared';
25
+ export type { HelperMaps, IdNode, Message, MessageGroupMetadata, ParseResult } from './shared';
@@ -40,7 +40,6 @@ import {
40
40
  } from '../schemas';
41
41
  import { LobeChatDatabase } from '../type';
42
42
  import { genEndDateWhere, genRangeWhere, genStartDateWhere, genWhere } from '../utils/genWhere';
43
- import { groupAssistantMessages } from '../utils/groupMessages';
44
43
  import { idGenerator } from '../utils/idGenerator';
45
44
 
46
45
  export class MessageModel {
@@ -227,8 +226,8 @@ export class MessageModel {
227
226
  })),
228
227
 
229
228
  extra: {
230
- fromModel: model,
231
- fromProvider: provider,
229
+ model: model,
230
+ provider: provider,
232
231
  translate,
233
232
  tts: ttsId
234
233
  ? {
@@ -269,9 +268,7 @@ export class MessageModel {
269
268
  },
270
269
  );
271
270
 
272
- // Group assistant messages with their tool results
273
- const { groupAssistantMessages: useGroup = false } = options;
274
- return useGroup ? groupAssistantMessages(mappedMessages) : mappedMessages;
271
+ return mappedMessages;
275
272
  };
276
273
 
277
274
  findById = async (id: string) => {
@@ -464,8 +461,8 @@ export class MessageModel {
464
461
 
465
462
  create = async (
466
463
  {
467
- fromModel,
468
- fromProvider,
464
+ model: fromModel,
465
+ provider: fromProvider,
469
466
  files,
470
467
  plugin,
471
468
  pluginState,
@@ -771,17 +768,19 @@ export class MessageModel {
771
768
  sessionId?: string | null,
772
769
  topicId?: string | null,
773
770
  groupId?: string | null,
774
- ) =>
775
- this.db
776
- .delete(messages)
777
- .where(
778
- and(
779
- eq(messages.userId, this.userId),
780
- this.matchSession(sessionId),
781
- this.matchTopic(topicId),
782
- this.matchGroup(groupId),
783
- ),
784
- );
771
+ ) => {
772
+ const conditions = [eq(messages.userId, this.userId), this.matchSession(sessionId)];
773
+
774
+ // For deletion: only filter by topicId/groupId if explicitly provided
775
+ if (topicId !== undefined && topicId !== null) {
776
+ conditions.push(eq(messages.topicId, topicId));
777
+ }
778
+ if (groupId !== undefined && groupId !== null) {
779
+ conditions.push(eq(messages.groupId, groupId));
780
+ }
781
+
782
+ return this.db.delete(messages).where(and(...conditions));
783
+ };
785
784
 
786
785
  deleteAllMessages = async () => {
787
786
  return this.db.delete(messages).where(eq(messages.userId, this.userId));
@@ -9,6 +9,7 @@ export interface SendNewMessage {
9
9
  content: string;
10
10
  // if message has attached with files, then add files to message and the agent
11
11
  files?: string[];
12
+ parentId?: string;
12
13
  }
13
14
 
14
15
  export interface SendMessageServerParams {
@@ -41,6 +42,7 @@ export const AiSendMessageServerSchema = z.object({
41
42
  newUserMessage: z.object({
42
43
  content: z.string(),
43
44
  files: z.array(z.string()).optional(),
45
+ parentId: z.string().optional(),
44
46
  }),
45
47
  sessionId: z.string().optional(),
46
48
  threadId: z.string().optional(),
@@ -28,8 +28,8 @@ export interface ImportMessage {
28
28
 
29
29
  // 扩展字段
30
30
  extra?: {
31
- fromModel?: string;
32
- fromProvider?: string;
31
+ model?: string;
32
+ provider?: string;
33
33
  // 翻译
34
34
  translate?: ChatTranslate | false | null;
35
35
  // TTS
@@ -13,7 +13,13 @@ import { ChatMessageExtra } from './extra';
13
13
  import { ChatFileChunk } from './rag';
14
14
  import { ChatVideoItem } from './video';
15
15
 
16
- export type UIMessageRoleType = 'user' | 'system' | 'assistant' | 'tool' | 'supervisor' | 'group';
16
+ export type UIMessageRoleType =
17
+ | 'user'
18
+ | 'system'
19
+ | 'assistant'
20
+ | 'tool'
21
+ | 'supervisor'
22
+ | 'assistantGroup';
17
23
 
18
24
  export interface ChatFileItem {
19
25
  content?: string;
@@ -34,10 +40,20 @@ export interface AssistantContentBlock {
34
40
  tools?: ChatToolPayloadWithResult[];
35
41
  usage?: ModelUsage;
36
42
  }
43
+ interface UIMessageBranch {
44
+ /** Index of the active branch (0-based) */
45
+ activeBranchIndex: number;
46
+ /** Total number of branches */
47
+ count: number;
48
+ }
37
49
 
38
50
  export interface UIChatMessage {
39
51
  // Group chat fields (alphabetically before other fields)
40
52
  agentId?: string | 'supervisor';
53
+ /**
54
+ * Branch information for user messages with multiple children
55
+ */
56
+ branch?: UIMessageBranch;
41
57
  /**
42
58
  * children messages for grouped display
43
59
  * Used to group tool messages under their parent assistant message
@@ -7,8 +7,8 @@ export interface ChatTTS {
7
7
  }
8
8
 
9
9
  export interface ChatMessageExtra {
10
- fromModel?: string;
11
- fromProvider?: string;
10
+ model?: string;
11
+ provider?: string;
12
12
  // 翻译
13
13
  translate?: ChatTranslate | false | null;
14
14
  // TTS
@@ -16,8 +16,8 @@ export interface CreateMessageParams
16
16
  error?: ChatMessageError | null;
17
17
  fileChunks?: MessageSemanticSearchChunk[];
18
18
  files?: string[];
19
- fromModel?: string;
20
- fromProvider?: string;
19
+ model?: string;
20
+ provider?: string;
21
21
  groupId?: string;
22
22
  role: CreateMessageRoleType;
23
23
  sessionId: string;
@@ -35,10 +35,6 @@ export const UserGuideSchema = z.object({
35
35
  export type UserGuide = z.infer<typeof UserGuideSchema>;
36
36
 
37
37
  export const UserLabSchema = z.object({
38
- /**
39
- * enable assistant message grouping in chat display
40
- */
41
- enableAssistantMessageGroup: z.boolean().optional(),
42
38
  /**
43
39
  * enable multi-agent group chat mode
44
40
  */
@@ -1,15 +1,7 @@
1
+ import { estimateTokenCount } from 'tokenx';
2
+
1
3
  export const encodeAsync = async (str: string): Promise<number> => {
2
4
  if (str.length === 0) return 0;
3
5
 
4
- // use gpt-tokenizer under 10000 str
5
- // use approximation way if large then 10000
6
- if (str.length <= 10_000) {
7
- const { clientEncodeAsync } = await import('./client');
8
-
9
- return await clientEncodeAsync(str);
10
- } else {
11
- const { estimatedEncodeAsync } = await import('./estimated');
12
-
13
- return await estimatedEncodeAsync(str);
14
- }
6
+ return estimateTokenCount(str);
15
7
  };
@@ -0,0 +1,83 @@
1
+ 'use client';
2
+
3
+ import { memo, useEffect } from 'react';
4
+ import { useMediaQuery } from 'react-responsive';
5
+ import { MemoryRouter, Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom';
6
+
7
+ import MainChatPage from './components/MainChatPage';
8
+ import SettingsPage from './components/SettingsPage';
9
+
10
+ // Get initial path from URL
11
+ const getInitialPath = () => {
12
+ if (typeof window === 'undefined') return '/';
13
+ const fullPath = window.location.pathname;
14
+ const searchParams = window.location.search;
15
+ const chatIndex = fullPath.indexOf('/chat');
16
+
17
+ if (chatIndex !== -1) {
18
+ const pathAfterChat = fullPath.slice(chatIndex + '/chat'.length) || '/';
19
+ return pathAfterChat + searchParams;
20
+ }
21
+ return '/';
22
+ };
23
+
24
+ // Helper component to sync URL with MemoryRouter
25
+ const UrlSynchronizer = () => {
26
+ const location = useLocation();
27
+ const navigate = useNavigate();
28
+
29
+ // Sync initial URL
30
+ useEffect(() => {
31
+ const fullPath = window.location.pathname;
32
+ const searchParams = window.location.search;
33
+ const chatIndex = fullPath.indexOf('/chat');
34
+
35
+ if (chatIndex !== -1) {
36
+ const pathAfterChat = fullPath.slice(chatIndex + '/chat'.length) || '/';
37
+ const targetPath = pathAfterChat + searchParams;
38
+
39
+ if (location.pathname + location.search !== targetPath) {
40
+ navigate(targetPath, { replace: true });
41
+ }
42
+ }
43
+ }, []);
44
+
45
+ // Update browser URL when location changes
46
+ useEffect(() => {
47
+ const normalizedPath = location.pathname === '/' ? '' : location.pathname;
48
+ const newUrl = `/chat${normalizedPath}${location.search}`;
49
+ if (window.location.pathname + window.location.search !== newUrl) {
50
+ window.history.replaceState({}, '', newUrl);
51
+ }
52
+ }, [location.pathname, location.search]);
53
+
54
+ return null;
55
+ };
56
+
57
+ const ChatRouter = memo(() => {
58
+ const mobile = useMediaQuery({ maxWidth: 768 });
59
+ const routes = (
60
+ <Routes>
61
+ <Route element={<MainChatPage mobile={true} />} path="/" />
62
+ <Route element={<SettingsPage mobile={true} />} path="/settings" />
63
+ <Route element={<Navigate replace to="/" />} path="*" />
64
+ </Routes>
65
+ );
66
+
67
+ return (
68
+ <MemoryRouter initialEntries={[getInitialPath()]} initialIndex={0}>
69
+ <UrlSynchronizer />
70
+ {mobile ? (
71
+ // Mobile Layout
72
+ routes
73
+ ) : (
74
+ // Desktop Layout
75
+ <MainChatPage mobile={false} />
76
+ )}
77
+ </MemoryRouter>
78
+ );
79
+ });
80
+
81
+ ChatRouter.displayName = 'ChatRouter';
82
+
83
+ export default ChatRouter;
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+
3
+ import { PropsWithChildren, memo } from 'react';
4
+
5
+ import Desktop from './Desktop';
6
+ import Mobile from './Mobile';
7
+
8
+ interface ChatLayoutProps extends PropsWithChildren {
9
+ mobile?: boolean;
10
+ }
11
+
12
+ const ChatLayout = memo<ChatLayoutProps>(({ children, mobile }) => {
13
+ if (mobile) {
14
+ return <Mobile>{children}</Mobile>;
15
+ }
16
+
17
+ return <Desktop>{children}</Desktop>;
18
+ });
19
+
20
+ ChatLayout.displayName = 'ChatLayout';
21
+
22
+ export default ChatLayout;
@@ -3,7 +3,7 @@
3
3
  import { DraggablePanel, DraggablePanelContainer, type DraggablePanelProps } from '@lobehub/ui';
4
4
  import { createStyles, useResponsive, useThemeMode } from 'antd-style';
5
5
  import isEqual from 'fast-deep-equal';
6
- import { PropsWithChildren, memo, useEffect, useMemo, useState } from 'react';
6
+ import { memo, useEffect, useMemo, useState } from 'react';
7
7
 
8
8
  import { withSuspense } from '@/components/withSuspense';
9
9
  import { FOLDER_WIDTH } from '@/const/layoutTokens';
@@ -12,6 +12,7 @@ import { usePinnedAgentState } from '@/hooks/usePinnedAgentState';
12
12
  import { useGlobalStore } from '@/store/global';
13
13
  import { systemStatusSelectors } from '@/store/global/selectors';
14
14
 
15
+ import SessionPanelContent from '../../components/SessionPanel';
15
16
  import { TOOGLE_PANEL_BUTTON_ID } from '../../features/TogglePanelButton';
16
17
 
17
18
  export const useStyles = createStyles(({ css, token }) => ({
@@ -33,7 +34,7 @@ export const useStyles = createStyles(({ css, token }) => ({
33
34
  `,
34
35
  }));
35
36
 
36
- const SessionPanel = memo<PropsWithChildren>(({ children }) => {
37
+ const SessionPanel = memo(() => {
37
38
  const isSingleMode = useIsSingleMode();
38
39
 
39
40
  const { md = true } = useResponsive();
@@ -75,11 +76,15 @@ const SessionPanel = memo<PropsWithChildren>(({ children }) => {
75
76
 
76
77
  const { appearance } = useThemeMode();
77
78
 
78
- const SessionPanel = useMemo(() => {
79
+ const PanelContent = useMemo(() => {
79
80
  if (isSingleMode) {
80
- // 在单一模式下,仍然渲染 children 以确保 SessionHydration 等逻辑组件正常工作
81
+ // 在单一模式下,仍然渲染 SessionPanelContent 以确保 SessionHydration 等逻辑组件正常工作
81
82
  // 但使用隐藏样式而不是 return null
82
- return <div style={{ display: 'none' }}>{children}</div>;
83
+ return (
84
+ <div style={{ display: 'none' }}>
85
+ <SessionPanelContent mobile={false} />
86
+ </div>
87
+ );
83
88
  }
84
89
 
85
90
  return (
@@ -98,13 +103,13 @@ const SessionPanel = memo<PropsWithChildren>(({ children }) => {
98
103
  size={{ height: '100%', width: sessionsWidth }}
99
104
  >
100
105
  <DraggablePanelContainer style={{ flex: 'none', height: '100%', minWidth: FOLDER_WIDTH }}>
101
- {children}
106
+ <SessionPanelContent mobile={false} />
102
107
  </DraggablePanelContainer>
103
108
  </DraggablePanel>
104
109
  );
105
110
  }, [sessionsWidth, md, isPinned, sessionExpandable, tmpWidth, appearance, isSingleMode]);
106
111
 
107
- return SessionPanel;
112
+ return PanelContent;
108
113
  });
109
114
 
110
115
  export default withSuspense(SessionPanel);
@@ -9,7 +9,7 @@ import RegisterHotkeys from './RegisterHotkeys';
9
9
  import SessionPanel from './SessionPanel';
10
10
  import Workspace from './Workspace';
11
11
 
12
- const Layout = ({ children, session }: LayoutProps) => {
12
+ const Layout = ({ children }: LayoutProps) => {
13
13
  return (
14
14
  <>
15
15
  <Flexbox
@@ -18,7 +18,7 @@ const Layout = ({ children, session }: LayoutProps) => {
18
18
  style={{ maxWidth: '100%', overflow: 'hidden', position: 'relative' }}
19
19
  width={'100%'}
20
20
  >
21
- <SessionPanel>{session}</SessionPanel>
21
+ <SessionPanel />
22
22
  <Workspace>{children}</Workspace>
23
23
  </Flexbox>
24
24
  {/* ↓ cloud slot ↓ */}
@@ -0,0 +1,24 @@
1
+ 'use client';
2
+
3
+ import { PropsWithChildren, createContext, useContext } from 'react';
4
+
5
+ interface FeatureFlags {
6
+ hideDocs?: boolean;
7
+ showChangelog?: boolean;
8
+ }
9
+
10
+ const FeatureFlagsContext = createContext<FeatureFlags>({});
11
+
12
+ export const useFeatureFlags = () => useContext(FeatureFlagsContext);
13
+
14
+ export const FeatureFlagsProvider = ({
15
+ children,
16
+ hideDocs,
17
+ showChangelog,
18
+ }: PropsWithChildren<FeatureFlags>) => {
19
+ return (
20
+ <FeatureFlagsContext.Provider value={{ hideDocs, showChangelog }}>
21
+ {children}
22
+ </FeatureFlagsContext.Provider>
23
+ );
24
+ };
@@ -7,6 +7,7 @@ import { Flexbox } from 'react-layout-kit';
7
7
  import { withSuspense } from '@/components/withSuspense';
8
8
  import { useShowMobileWorkspace } from '@/hooks/useShowMobileWorkspace';
9
9
 
10
+ import SessionPanelContent from '../components/SessionPanel';
10
11
  import { LayoutProps } from './type';
11
12
 
12
13
  const useStyles = createStyles(({ css, token }) => ({
@@ -17,7 +18,7 @@ const useStyles = createStyles(({ css, token }) => ({
17
18
  `,
18
19
  }));
19
20
 
20
- const Layout = memo<LayoutProps>(({ children, session }) => {
21
+ const Layout = memo<LayoutProps>(({ children }) => {
21
22
  const showMobileWorkspace = useShowMobileWorkspace();
22
23
  const { styles } = useStyles();
23
24
 
@@ -29,7 +30,7 @@ const Layout = memo<LayoutProps>(({ children, session }) => {
29
30
  style={showMobileWorkspace ? { display: 'none' } : undefined}
30
31
  width="100%"
31
32
  >
32
- {session}
33
+ <SessionPanelContent mobile />
33
34
  </Flexbox>
34
35
  <Flexbox
35
36
  className={styles.main}
@@ -2,5 +2,4 @@ import { ReactNode } from 'react';
2
2
 
3
3
  export interface LayoutProps {
4
4
  children: ReactNode;
5
- session: ReactNode;
6
5
  }