@lobehub/lobehub 2.0.0-next.72 → 2.0.0-next.73
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.
- package/CHANGELOG.md +25 -0
- package/changelog/v1.json +9 -0
- package/next.config.ts +5 -5
- package/package.json +1 -1
- package/scripts/prebuild.mts +1 -1
- package/src/app/(backend)/trpc/desktop/[trpc]/route.ts +6 -6
- package/src/app/[variants]/(main)/(mobile)/me/(home)/__tests__/UserBanner.test.tsx +7 -4
- package/src/app/[variants]/(main)/(mobile)/me/(home)/__tests__/useCategory.test.tsx +4 -4
- package/src/app/[variants]/(main)/(mobile)/me/(home)/features/UserBanner.tsx +5 -6
- package/src/app/[variants]/(main)/(mobile)/me/(home)/features/useCategory.tsx +5 -8
- package/src/app/[variants]/(main)/(mobile)/me/(home)/index.tsx +25 -0
- package/src/app/[variants]/(main)/(mobile)/me/(home)/layout.tsx +13 -16
- package/src/app/[variants]/(main)/(mobile)/me/profile/features/Category.tsx +6 -6
- package/src/app/[variants]/(main)/(mobile)/me/profile/features/Header.tsx +3 -3
- package/src/app/[variants]/(main)/(mobile)/me/profile/index.tsx +16 -0
- package/src/app/[variants]/(main)/(mobile)/me/profile/layout.tsx +9 -11
- package/src/app/[variants]/(main)/(mobile)/me/settings/features/Header.tsx +3 -3
- package/src/app/[variants]/(main)/(mobile)/me/settings/features/useCategory.tsx +3 -4
- package/src/app/[variants]/(main)/(mobile)/me/settings/index.tsx +16 -0
- package/src/app/[variants]/(main)/(mobile)/me/settings/layout.tsx +15 -13
- package/src/app/[variants]/(main)/changelog/_layout/Desktop/index.tsx +6 -5
- package/src/app/[variants]/(main)/changelog/_layout/Mobile/Header.tsx +3 -3
- package/src/app/[variants]/(main)/changelog/_layout/Mobile/index.tsx +5 -5
- package/src/app/[variants]/(main)/changelog/features/Post.tsx +7 -4
- package/src/app/[variants]/(main)/changelog/index.tsx +55 -0
- package/src/app/[variants]/(main)/chat/_layout/Desktop/index.tsx +6 -7
- package/src/app/[variants]/(main)/chat/_layout/Mobile.tsx +3 -3
- package/src/app/[variants]/(main)/chat/components/WorkspaceLayout.tsx +1 -14
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatHydration/index.tsx +2 -2
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatInput/Desktop/MessageFromUrl.tsx +11 -13
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatInput/Desktop/index.tsx +0 -1
- package/src/app/[variants]/(main)/chat/components/conversation/features/ThreadHydration.tsx +2 -2
- package/src/app/[variants]/(main)/chat/components/topic/features/Topic/TopicListContent/TopicItem/TopicContent.tsx +20 -11
- package/src/app/[variants]/(main)/chat/features/PageTitle/index.tsx +1 -2
- package/src/app/[variants]/(main)/chat/index.tsx +29 -0
- package/src/app/[variants]/(main)/chat/session/features/SessionHydration.tsx +8 -6
- package/src/app/[variants]/(main)/chat/session/features/SessionListContent/Inbox/index.tsx +2 -4
- package/src/app/[variants]/(main)/chat/session/features/SessionListContent/List/index.tsx +1 -1
- package/src/app/[variants]/(main)/chat/session/layout/Mobile/SessionHeader.tsx +3 -3
- package/src/app/[variants]/(main)/chat/settings/_layout/Desktop/Header.tsx +3 -3
- package/src/app/[variants]/(main)/chat/settings/_layout/Mobile/Header.tsx +3 -3
- package/src/app/[variants]/(main)/chat/settings/features/PublishResultModal/index.tsx +3 -3
- package/src/app/[variants]/(main)/chat/{components/SettingsPage.tsx → settings/index.tsx} +6 -35
- package/src/app/[variants]/(main)/components/Link.tsx +21 -0
- package/src/app/[variants]/(main)/discover/(detail)/_layout/{Desktop.tsx → Desktop/index.tsx} +15 -7
- package/src/app/[variants]/(main)/discover/(detail)/_layout/Mobile/index.tsx +3 -3
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/Capabilities/Block.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/Overview/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/Related/index.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/SystemRole/index.tsx +3 -3
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/Versions/index.tsx +4 -4
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Header.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Sidebar/ActionButton/AddAgent.tsx +3 -3
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Sidebar/ActionButton/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Sidebar/Related/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Sidebar/TocList/index.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/StatusPage/index.tsx +3 -3
- package/src/app/[variants]/(main)/discover/(detail)/assistant/{AssistantDetailPage.tsx → index.tsx} +18 -11
- package/src/app/[variants]/(main)/discover/(detail)/features/Breadcrumb.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/mcp/{[slug]/features → features}/Details/Related/index.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(detail)/mcp/{[slug]/features → features}/Details/Versions/index.tsx +5 -5
- package/src/app/[variants]/(main)/discover/(detail)/mcp/{[slug]/features → features}/Details/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/mcp/{[slug]/features → features}/Sidebar/Related/index.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(detail)/mcp/{[slug]/features → features}/Sidebar/ServerConfig.tsx +4 -4
- package/src/app/[variants]/(main)/discover/(detail)/mcp/{[slug]/features → features}/Sidebar/TocList/index.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(detail)/mcp/{McpDetailPage.tsx → index.tsx} +15 -7
- package/src/app/[variants]/(main)/discover/(detail)/mcp/loading.tsx +1 -0
- package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Details/Overview/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Details/Parameter/ParameterItem.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Details/Related/index.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Details/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Header.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Sidebar/ActionButton/ChatWithModel.tsx +3 -3
- package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Sidebar/ActionButton/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Sidebar/Related/index.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Sidebar/RelatedProviders/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/model/{ModelDetailPage.tsx → index.tsx} +17 -10
- package/src/app/[variants]/(main)/discover/(detail)/model/loading.tsx +1 -0
- package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Details/Related/index.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Details/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Sidebar/ActionButton/ProviderConfig.tsx +5 -4
- package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Sidebar/ActionButton/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Sidebar/Related/index.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Sidebar/RelatedModels/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(detail)/provider/{ProviderDetailPage.tsx → index.tsx} +17 -10
- package/src/app/[variants]/(main)/discover/(detail)/provider/loading.tsx +1 -0
- package/src/app/[variants]/(main)/discover/(list)/(home)/{HomePage.tsx → index.tsx} +14 -0
- package/src/app/[variants]/(main)/discover/(list)/_layout/Desktop/Nav.tsx +2 -3
- package/src/app/[variants]/(main)/discover/(list)/_layout/Desktop/index.tsx +4 -3
- package/src/app/[variants]/(main)/discover/(list)/_layout/Mobile/Nav.tsx +3 -4
- package/src/app/[variants]/(main)/discover/(list)/_layout/Mobile/index.tsx +4 -3
- package/src/app/[variants]/(main)/discover/(list)/assistant/_layout/Desktop.tsx +3 -4
- package/src/app/[variants]/(main)/discover/(list)/assistant/_layout/Mobile.tsx +3 -3
- package/src/app/[variants]/(main)/discover/(list)/assistant/features/List/Item.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(list)/assistant/{AssistantPage.tsx → index.tsx} +18 -4
- package/src/app/[variants]/(main)/discover/(list)/features/SortButton/index.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(list)/mcp/_layout/Desktop.tsx +3 -3
- package/src/app/[variants]/(main)/discover/(list)/mcp/_layout/Mobile.tsx +3 -3
- package/src/app/[variants]/(main)/discover/(list)/mcp/features/List/Item.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(list)/mcp/{McpPage.tsx → index.tsx} +9 -2
- package/src/app/[variants]/(main)/discover/(list)/model/_layout/Desktop.tsx +3 -3
- package/src/app/[variants]/(main)/discover/(list)/model/_layout/Mobile.tsx +3 -3
- package/src/app/[variants]/(main)/discover/(list)/model/features/List/Item.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(list)/model/{ModelPage.tsx → index.tsx} +9 -2
- package/src/app/[variants]/(main)/discover/(list)/provider/features/List/Item.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(list)/provider/{Client.tsx → index.tsx} +9 -2
- package/src/app/[variants]/(main)/discover/_layout/Desktop/index.tsx +4 -4
- package/src/app/[variants]/(main)/discover/_layout/Mobile/index.tsx +3 -3
- package/src/app/[variants]/(main)/discover/components/Title.tsx +1 -1
- package/src/app/[variants]/(main)/discover/features/Search.tsx +2 -2
- package/src/app/[variants]/(main)/discover/features/useNav.tsx +11 -12
- package/src/app/[variants]/(main)/hooks/useActiveTabKey.ts +40 -0
- package/src/app/[variants]/(main)/hooks/usePathname.ts +10 -0
- package/src/app/[variants]/(main)/hooks/useQuery.ts +12 -0
- package/src/app/[variants]/(main)/hooks/useRouter.ts +22 -0
- package/src/app/[variants]/(main)/hooks/useSearchParams.ts +11 -0
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/ModelSelect/index.tsx +5 -5
- package/src/app/[variants]/(main)/image/@topic/features/Topics/TopicUrlSync.tsx +1 -1
- package/src/app/[variants]/(main)/image/ComingSoon.tsx +15 -0
- package/src/app/[variants]/(main)/image/_layout/Desktop/index.tsx +5 -2
- package/src/app/[variants]/(main)/image/_layout/DesktopWrapper.tsx +15 -0
- package/src/app/[variants]/(main)/image/_layout/Mobile/index.tsx +3 -1
- package/src/app/[variants]/(main)/image/features/ImageWorkspace/index.tsx +1 -2
- package/src/app/[variants]/(main)/image/index.tsx +18 -0
- package/src/app/[variants]/(main)/knowledge/_layout/Desktop.tsx +17 -0
- package/src/app/[variants]/(main)/knowledge/_layout/Mobile.tsx +17 -0
- package/src/app/[variants]/(main)/knowledge/components/KnowledgeBaseItem/index.tsx +1 -1
- package/src/app/[variants]/(main)/knowledge/components/modal/ModalPageClient.tsx +4 -4
- package/src/app/[variants]/(main)/knowledge/routes/KnowledgeBaseDetail/index.tsx +5 -8
- package/src/app/[variants]/(main)/knowledge/routes/KnowledgeBaseDetail/menu/Head.tsx +1 -1
- package/src/app/[variants]/(main)/knowledge/routes/KnowledgeHome/menu/CategoryMenu.tsx +2 -2
- package/src/app/[variants]/(main)/knowledge/routes/KnowledgeHome/menu/KnowledgeBase.tsx +1 -1
- package/src/app/[variants]/(main)/{_layout/Desktop → layouts/desktop}/DesktopLayoutContainer.tsx +3 -2
- package/src/app/[variants]/(main)/{_layout/Desktop → layouts/desktop}/SideBar/BottomActions.tsx +4 -4
- package/src/app/[variants]/(main)/{_layout/Desktop → layouts/desktop}/SideBar/TopActions.test.tsx +9 -9
- package/src/app/[variants]/(main)/layouts/desktop/SideBar/TopActions.tsx +117 -0
- package/src/app/[variants]/(main)/{_layout/Desktop → layouts/desktop}/index.tsx +9 -4
- package/src/app/[variants]/(main)/layouts/index.tsx +11 -0
- package/src/app/[variants]/(main)/{_layout/Mobile → layouts/mobile}/NavBar.tsx +5 -5
- package/src/app/[variants]/(main)/{_layout/Mobile → layouts/mobile}/index.tsx +10 -7
- package/src/app/[variants]/(main)/profile/(home)/desktop.tsx +26 -0
- package/src/app/[variants]/(main)/profile/(home)/index.tsx +26 -0
- package/src/app/[variants]/(main)/profile/@category/features/CategoryContent.tsx +5 -7
- package/src/app/[variants]/(main)/profile/_layout/Desktop/index.tsx +3 -2
- package/src/app/[variants]/(main)/profile/_layout/DesktopWrapper.tsx +14 -0
- package/src/app/[variants]/(main)/profile/_layout/Mobile/Header.tsx +3 -3
- package/src/app/[variants]/(main)/profile/_layout/Mobile/index.tsx +4 -3
- package/src/app/[variants]/(main)/profile/apikey/index.tsx +18 -0
- package/src/app/[variants]/(main)/profile/hooks/useCategory.tsx +6 -6
- package/src/app/[variants]/(main)/profile/security/index.tsx +29 -0
- package/src/app/[variants]/(main)/profile/stats/features/AssistantsRank.tsx +4 -4
- package/src/app/[variants]/(main)/profile/stats/features/TopicsRank.tsx +4 -4
- package/src/app/[variants]/(main)/profile/stats/index.tsx +20 -0
- package/src/app/[variants]/(main)/profile/usage/features/UsageTable.tsx +7 -9
- package/src/app/[variants]/(main)/profile/usage/index.tsx +13 -0
- package/src/app/[variants]/(main)/settings/_layout/Desktop/Header.tsx +2 -2
- package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +2 -2
- package/src/app/[variants]/(main)/settings/_layout/DesktopWrapper.tsx +23 -0
- package/src/app/[variants]/(main)/settings/_layout/Mobile/Header.tsx +8 -7
- package/src/app/[variants]/(main)/settings/_layout/Mobile/index.tsx +2 -5
- package/src/app/[variants]/(main)/settings/_layout/MobileWrapper.tsx +23 -0
- package/src/app/[variants]/(main)/settings/agent/AgentMenu/Menu.tsx +2 -4
- package/src/app/[variants]/(main)/settings/agent/index.tsx +2 -4
- package/src/app/[variants]/(main)/settings/provider/(list)/index.tsx +2 -3
- package/src/app/[variants]/(main)/settings/provider/ProviderMenu/All.tsx +2 -2
- package/src/app/[variants]/(main)/settings/provider/ProviderMenu/Item.tsx +38 -37
- package/src/app/[variants]/(main)/settings/provider/_layout/Mobile.tsx +2 -2
- package/src/app/[variants]/(main)/settings/provider/features/CreateNewProvider/index.tsx +3 -3
- package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/UpdateProviderInfo/SettingModal.tsx +3 -3
- package/src/app/[variants]/DesktopRouter.tsx +40 -0
- package/src/app/[variants]/MobileRouter.tsx +41 -0
- package/src/app/[variants]/desktopRouter.config.tsx +381 -0
- package/src/app/[variants]/layout.tsx +1 -3
- package/src/app/[variants]/loaders/routeParams.ts +45 -0
- package/src/app/[variants]/loading/Server/Redirect.tsx +1 -1
- package/src/app/[variants]/mobileRouter.config.tsx +412 -0
- package/src/app/[variants]/page.tsx +16 -6
- package/src/app/desktop/devtools/page.tsx +1 -1
- package/src/app/desktop/layout.tsx +1 -1
- package/src/components/BootErrorBoundary/index.tsx +129 -0
- package/src/components/mdx/constants.ts +1 -0
- package/src/features/ChangelogModal/index.tsx +3 -3
- package/src/features/KnowledgeManager/FileExplorer/index.tsx +4 -4
- package/src/features/KnowledgeManager/Header/FilesSearchBar.tsx +1 -1
- package/src/features/User/UserPanel/PanelContent.tsx +4 -3
- package/src/features/User/UserPanel/useMenu.tsx +20 -14
- package/src/features/User/__tests__/PanelContent.test.tsx +13 -7
- package/src/hooks/useDiscoverTab.ts +2 -2
- package/src/hooks/useInterceptingRoutes.test.ts +23 -26
- package/src/hooks/useInterceptingRoutes.ts +5 -4
- package/src/hooks/usePinnedAgentState.ts +6 -6
- package/src/hooks/useQuery.ts +5 -0
- package/src/hooks/useQueryParam.ts +322 -0
- package/src/hooks/useQueryRoute.test.ts +2 -12
- package/src/hooks/useQueryRoute.ts +5 -5
- package/src/hooks/useShowMobileWorkspace.ts +1 -1
- package/src/hooks/useSwitchSession.ts +4 -3
- package/src/layout/GlobalProvider/ImportSettings.tsx +22 -9
- package/src/layout/GlobalProvider/StoreInitialization.tsx +9 -1
- package/src/proxy.ts +13 -1
- package/src/services/message/index.ts +11 -2
- package/src/store/chat/agents/createAgentExecutors.ts +31 -16
- package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +218 -0
- package/src/store/chat/slices/aiChat/actions/conversationControl.ts +4 -0
- package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +9 -3
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +142 -61
- package/src/store/chat/slices/builtinTool/actions/__tests__/search.test.ts +204 -10
- package/src/store/chat/slices/builtinTool/actions/search.ts +51 -26
- package/src/store/chat/slices/message/action.test.ts +182 -33
- package/src/store/chat/slices/message/actions/optimisticUpdate.ts +79 -36
- package/src/store/chat/slices/message/actions/query.ts +7 -5
- package/src/store/chat/slices/message/selectors/dbMessage.ts +11 -4
- package/src/store/chat/slices/plugin/action.test.ts +257 -54
- package/src/store/chat/slices/plugin/actions/optimisticUpdate.ts +63 -26
- package/src/store/chat/slices/plugin/actions/pluginTypes.ts +52 -19
- package/src/store/chat/slices/plugin/actions/publicApi.ts +6 -1
- package/src/store/chat/slices/plugin/actions/workflow.ts +17 -6
- package/src/store/chat/slices/thread/action.ts +2 -0
- package/src/store/global/action.test.ts +3 -3
- package/src/store/global/actions/workspacePane.ts +2 -1
- package/src/store/global/initialState.ts +10 -2
- package/src/store/user/slices/common/action.ts +4 -0
- package/src/app/[variants]/(main)/(mobile)/me/(home)/loading.tsx +0 -38
- package/src/app/[variants]/(main)/(mobile)/me/(home)/page.tsx +0 -40
- package/src/app/[variants]/(main)/(mobile)/me/profile/loading.tsx +0 -5
- package/src/app/[variants]/(main)/(mobile)/me/profile/page.tsx +0 -30
- package/src/app/[variants]/(main)/(mobile)/me/settings/loading.tsx +0 -5
- package/src/app/[variants]/(main)/(mobile)/me/settings/page.tsx +0 -30
- package/src/app/[variants]/(main)/_layout/Desktop/SideBar/TopActions.tsx +0 -106
- package/src/app/[variants]/(main)/changelog/layout.tsx +0 -10
- package/src/app/[variants]/(main)/changelog/modal/page.tsx +0 -23
- package/src/app/[variants]/(main)/changelog/page.tsx +0 -78
- package/src/app/[variants]/(main)/chat/ChatRouter.tsx +0 -83
- package/src/app/[variants]/(main)/chat/_layout/ChatLayout.tsx +0 -22
- package/src/app/[variants]/(main)/chat/components/MainChatPage.tsx +0 -25
- package/src/app/[variants]/(main)/chat/error.tsx +0 -3
- package/src/app/[variants]/(main)/chat/layout.tsx +0 -10
- package/src/app/[variants]/(main)/chat/loading.tsx +0 -3
- package/src/app/[variants]/(main)/chat/not-found.tsx +0 -1
- package/src/app/[variants]/(main)/chat/page.tsx +0 -12
- package/src/app/[variants]/(main)/chat/settings/error.tsx +0 -3
- package/src/app/[variants]/(main)/chat/settings/loading.tsx +0 -3
- package/src/app/[variants]/(main)/chat/settings/not-found.tsx +0 -1
- package/src/app/[variants]/(main)/discover/(detail)/_layout/DetailLayout.tsx +0 -22
- package/src/app/[variants]/(main)/discover/(detail)/assistant/[...slugs]/Client.tsx +0 -51
- package/src/app/[variants]/(main)/discover/(detail)/mcp/[slug]/Client.tsx +0 -43
- package/src/app/[variants]/(main)/discover/(detail)/mcp/[slug]/loading.tsx +0 -1
- package/src/app/[variants]/(main)/discover/(detail)/model/[...slugs]/Client.tsx +0 -40
- package/src/app/[variants]/(main)/discover/(detail)/model/[...slugs]/loading.tsx +0 -1
- package/src/app/[variants]/(main)/discover/(detail)/provider/[...slugs]/Client.tsx +0 -40
- package/src/app/[variants]/(main)/discover/(detail)/provider/[...slugs]/loading.tsx +0 -1
- package/src/app/[variants]/(main)/discover/(list)/_layout/ListLayout.tsx +0 -22
- package/src/app/[variants]/(main)/discover/(list)/assistant/AssistantLayout.tsx +0 -21
- package/src/app/[variants]/(main)/discover/(list)/mcp/Client.tsx +0 -44
- package/src/app/[variants]/(main)/discover/(list)/mcp/McpLayout.tsx +0 -21
- package/src/app/[variants]/(main)/discover/(list)/model/Client.tsx +0 -44
- package/src/app/[variants]/(main)/discover/(list)/model/ModelLayout.tsx +0 -21
- package/src/app/[variants]/(main)/discover/(list)/provider/ProviderPage.tsx +0 -43
- package/src/app/[variants]/(main)/discover/DiscoverRouter.tsx +0 -170
- package/src/app/[variants]/(main)/discover/[[...path]]/page.tsx +0 -12
- package/src/app/[variants]/(main)/discover/_layout/DiscoverLayout.tsx +0 -22
- package/src/app/[variants]/(main)/discover/error.tsx +0 -3
- package/src/app/[variants]/(main)/discover/not-found.tsx +0 -1
- package/src/app/[variants]/(main)/error.tsx +0 -3
- package/src/app/[variants]/(main)/image/layout.tsx +0 -15
- package/src/app/[variants]/(main)/image/page.tsx +0 -45
- package/src/app/[variants]/(main)/knowledge/KnowledgeRouter.tsx +0 -74
- package/src/app/[variants]/(main)/knowledge/[[...path]]/page.tsx +0 -12
- package/src/app/[variants]/(main)/knowledge/components/modal/page.tsx +0 -13
- package/src/app/[variants]/(main)/knowledge/layout.tsx +0 -12
- package/src/app/[variants]/(main)/layout.tsx +0 -10
- package/src/app/[variants]/(main)/not-found.tsx +0 -1
- package/src/app/[variants]/(main)/profile/apikey/page.tsx +0 -32
- package/src/app/[variants]/(main)/profile/error.tsx +0 -3
- package/src/app/[variants]/(main)/profile/layout.tsx +0 -11
- package/src/app/[variants]/(main)/profile/loading.tsx +0 -3
- package/src/app/[variants]/(main)/profile/not-found.tsx +0 -1
- package/src/app/[variants]/(main)/profile/security/page.tsx +0 -28
- package/src/app/[variants]/(main)/profile/stats/page.tsx +0 -23
- package/src/app/[variants]/(main)/profile/usage/page.tsx +0 -23
- package/src/app/[variants]/@modal/(.)changelog/modal/features/Cover.tsx +0 -48
- package/src/app/[variants]/@modal/(.)changelog/modal/features/Hero.tsx +0 -29
- package/src/app/[variants]/@modal/(.)changelog/modal/features/Post.tsx +0 -57
- package/src/app/[variants]/@modal/(.)changelog/modal/features/PublishedTime.tsx +0 -50
- package/src/app/[variants]/@modal/(.)changelog/modal/features/ReadDetail.tsx +0 -72
- package/src/app/[variants]/@modal/(.)changelog/modal/features/VersionTag.tsx +0 -26
- package/src/app/[variants]/@modal/(.)changelog/modal/layout.tsx +0 -41
- package/src/app/[variants]/@modal/(.)changelog/modal/loading.tsx +0 -10
- package/src/app/[variants]/@modal/(.)changelog/modal/page.tsx +0 -38
- package/src/app/[variants]/@modal/_layout/ModalLayout.tsx +0 -63
- package/src/app/[variants]/@modal/_layout/SettingModalLayout.tsx +0 -71
- package/src/app/[variants]/@modal/default.tsx +0 -3
- package/src/app/[variants]/@modal/error.tsx +0 -3
- package/src/app/[variants]/@modal/layout.tsx +0 -7
- package/src/app/[variants]/@modal/loading.tsx +0 -5
- /package/src/app/[variants]/{@modal/(.)changelog/modal → (main)/changelog}/features/Pagination.tsx +0 -0
- /package/src/app/[variants]/{@modal/(.)changelog/modal → (main)/changelog}/features/UpdateChangelogStatus.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/DetailProvider.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/Capabilities/Knowledge.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/Capabilities/KnowledgeItem.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/Capabilities/PluginItem.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/Capabilities/Plugins.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/Capabilities/index.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/Nav.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/Overview/TagList.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Details/SystemRole/TagList.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Sidebar/Related/Item.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Sidebar/Summary/index.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/features → features}/Sidebar/index.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/assistant/{[...slugs]/loading.tsx → loading.tsx} +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/mcp/{[slug]/features → features}/Sidebar/ActionButton/index.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/mcp/{[slug]/features → features}/Sidebar/ConnectionTypeAlert.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/mcp/{[slug]/features → features}/Sidebar/Related/Item.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/mcp/{[slug]/features → features}/Sidebar/index.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/DetailProvider.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Details/Nav.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Details/Overview/ProviderList/index.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Details/Parameter/index.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Sidebar/Related/Item.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Sidebar/RelatedProviders/Item.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/model/{[...slugs]/features → features}/Sidebar/index.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/DetailProvider.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Details/Guide/index.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Details/Nav.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Details/Overview/ModelList/index.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Details/Overview/index.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Header.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Sidebar/Related/Item.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Sidebar/RelatedModels/Item.tsx +0 -0
- /package/src/app/[variants]/(main)/discover/(detail)/provider/{[...slugs]/features → features}/Sidebar/index.tsx +0 -0
- /package/src/app/[variants]/(main)/labs/{page.tsx → index.tsx} +0 -0
- /package/src/app/[variants]/(main)/{_layout/Desktop → layouts/desktop}/RegisterHotkeys.tsx +0 -0
- /package/src/app/[variants]/(main)/{_layout/Desktop → layouts/desktop}/SideBar/Avatar.test.tsx +0 -0
- /package/src/app/[variants]/(main)/{_layout/Desktop → layouts/desktop}/SideBar/Avatar.tsx +0 -0
- /package/src/app/[variants]/(main)/{_layout/Desktop → layouts/desktop}/SideBar/PinList/index.tsx +0 -0
- /package/src/app/[variants]/(main)/{_layout/Desktop → layouts/desktop}/SideBar/index.tsx +0 -0
|
@@ -4,7 +4,7 @@ import { nanoid } from '@lobechat/utils';
|
|
|
4
4
|
import { StateCreator } from 'zustand/vanilla';
|
|
5
5
|
|
|
6
6
|
import { searchService } from '@/services/search';
|
|
7
|
-
import {
|
|
7
|
+
import { dbMessageSelectors } from '@/store/chat/selectors';
|
|
8
8
|
import { ChatStore } from '@/store/chat/store';
|
|
9
9
|
import { WebBrowsingExecutionRuntime } from '@/tools/web-browsing/ExecutionRuntime';
|
|
10
10
|
|
|
@@ -45,15 +45,20 @@ export const searchSlice: StateCreator<
|
|
|
45
45
|
crawlMultiPages: async (id, params, aiSummary = true) => {
|
|
46
46
|
const { optimisticUpdateMessageContent } = get();
|
|
47
47
|
get().toggleSearchLoading(id, true);
|
|
48
|
+
|
|
49
|
+
// Get message to extract sessionId/topicId
|
|
50
|
+
const message = dbMessageSelectors.getDbMessageById(id)(get());
|
|
51
|
+
const context = { sessionId: message?.sessionId, topicId: message?.topicId };
|
|
52
|
+
|
|
48
53
|
try {
|
|
49
54
|
const { content, success, error, state } = await runtime.crawlMultiPages(params);
|
|
50
55
|
|
|
51
|
-
await optimisticUpdateMessageContent(id, content);
|
|
56
|
+
await optimisticUpdateMessageContent(id, content, undefined, context);
|
|
52
57
|
|
|
53
58
|
if (success) {
|
|
54
|
-
await get().optimisticUpdatePluginState(id, state);
|
|
59
|
+
await get().optimisticUpdatePluginState(id, state, context);
|
|
55
60
|
} else {
|
|
56
|
-
await get().optimisticUpdatePluginError(id, error);
|
|
61
|
+
await get().optimisticUpdatePluginError(id, error, context);
|
|
57
62
|
}
|
|
58
63
|
get().toggleSearchLoading(id, false);
|
|
59
64
|
|
|
@@ -67,7 +72,7 @@ export const searchSlice: StateCreator<
|
|
|
67
72
|
const content = [{ errorMessage: err.message, errorType: err.name }];
|
|
68
73
|
|
|
69
74
|
const xmlContent = crawlResultsPrompt(content);
|
|
70
|
-
await optimisticUpdateMessageContent(id, xmlContent);
|
|
75
|
+
await optimisticUpdateMessageContent(id, xmlContent, undefined, context);
|
|
71
76
|
}
|
|
72
77
|
},
|
|
73
78
|
|
|
@@ -78,10 +83,13 @@ export const searchSlice: StateCreator<
|
|
|
78
83
|
},
|
|
79
84
|
|
|
80
85
|
saveSearchResult: async (id) => {
|
|
81
|
-
const message =
|
|
86
|
+
const message = dbMessageSelectors.getDbMessageById(id)(get());
|
|
82
87
|
if (!message || !message.plugin) return;
|
|
83
88
|
|
|
84
89
|
const { optimisticAddToolToAssistantMessage, optimisticCreateMessage, openToolUI } = get();
|
|
90
|
+
|
|
91
|
+
const context = { sessionId: message.sessionId, topicId: message.topicId };
|
|
92
|
+
|
|
85
93
|
// 1. 创建一个新的 tool call message
|
|
86
94
|
const newToolCallId = `tool_call_${nanoid()}`;
|
|
87
95
|
|
|
@@ -92,23 +100,30 @@ export const searchSlice: StateCreator<
|
|
|
92
100
|
plugin: message.plugin,
|
|
93
101
|
pluginState: message.pluginState,
|
|
94
102
|
role: 'tool',
|
|
95
|
-
sessionId: get().activeId,
|
|
103
|
+
sessionId: message.sessionId ?? get().activeId,
|
|
96
104
|
tool_call_id: newToolCallId,
|
|
97
|
-
topicId: get().activeTopicId,
|
|
105
|
+
topicId: message.topicId !== undefined ? message.topicId : get().activeTopicId,
|
|
98
106
|
};
|
|
99
107
|
|
|
100
108
|
const addToolItem = async () => {
|
|
101
109
|
if (!message.parentId || !message.plugin) return;
|
|
102
110
|
|
|
103
|
-
await optimisticAddToolToAssistantMessage(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
111
|
+
await optimisticAddToolToAssistantMessage(
|
|
112
|
+
message.parentId,
|
|
113
|
+
{
|
|
114
|
+
id: newToolCallId,
|
|
115
|
+
...message.plugin,
|
|
116
|
+
},
|
|
117
|
+
context,
|
|
118
|
+
);
|
|
107
119
|
};
|
|
108
120
|
|
|
109
121
|
const [result] = await Promise.all([
|
|
110
122
|
// 1. 添加 tool message
|
|
111
|
-
optimisticCreateMessage(toolMessage
|
|
123
|
+
optimisticCreateMessage(toolMessage, {
|
|
124
|
+
sessionId: toolMessage.sessionId,
|
|
125
|
+
topicId: toolMessage.topicId,
|
|
126
|
+
}),
|
|
112
127
|
// 2. 将这条 tool call message 插入到 ai 消息的 tools 中
|
|
113
128
|
addToolItem(),
|
|
114
129
|
]);
|
|
@@ -121,31 +136,41 @@ export const searchSlice: StateCreator<
|
|
|
121
136
|
search: async (id, params, aiSummary = true) => {
|
|
122
137
|
get().toggleSearchLoading(id, true);
|
|
123
138
|
|
|
139
|
+
// Get message to extract sessionId/topicId
|
|
140
|
+
const message = dbMessageSelectors.getDbMessageById(id)(get());
|
|
141
|
+
const context = { sessionId: message?.sessionId, topicId: message?.topicId };
|
|
142
|
+
|
|
124
143
|
const { content, success, error, state } = await runtime.search(params);
|
|
125
144
|
|
|
126
145
|
if (success) {
|
|
127
|
-
await get().optimisticUpdatePluginState(id, state);
|
|
146
|
+
await get().optimisticUpdatePluginState(id, state, context);
|
|
128
147
|
} else {
|
|
129
148
|
if ((error as Error).message === SEARCH_SEARXNG_NOT_CONFIG) {
|
|
130
|
-
await get().optimisticUpdateMessagePluginError(
|
|
131
|
-
|
|
132
|
-
|
|
149
|
+
await get().optimisticUpdateMessagePluginError(
|
|
150
|
+
id,
|
|
151
|
+
{
|
|
152
|
+
body: { provider: 'searxng' },
|
|
153
|
+
message: 'SearXNG is not configured',
|
|
154
|
+
type: 'PluginSettingsInvalid',
|
|
133
155
|
},
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
});
|
|
156
|
+
context,
|
|
157
|
+
);
|
|
137
158
|
} else {
|
|
138
|
-
await get().optimisticUpdateMessagePluginError(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
159
|
+
await get().optimisticUpdateMessagePluginError(
|
|
160
|
+
id,
|
|
161
|
+
{
|
|
162
|
+
body: error,
|
|
163
|
+
message: (error as Error).message,
|
|
164
|
+
type: 'PluginServerError',
|
|
165
|
+
},
|
|
166
|
+
context,
|
|
167
|
+
);
|
|
143
168
|
}
|
|
144
169
|
}
|
|
145
170
|
|
|
146
171
|
get().toggleSearchLoading(id, false);
|
|
147
172
|
|
|
148
|
-
await get().optimisticUpdateMessageContent(id, content);
|
|
173
|
+
await get().optimisticUpdateMessageContent(id, content, undefined, context);
|
|
149
174
|
|
|
150
175
|
// 如果 aiSummary 为 true,则会自动触发总结
|
|
151
176
|
return aiSummary;
|
|
@@ -22,11 +22,14 @@ vi.mock('@/services/message', () => ({
|
|
|
22
22
|
messageService: {
|
|
23
23
|
getMessages: vi.fn(),
|
|
24
24
|
updateMessageError: vi.fn(),
|
|
25
|
-
removeMessage: vi.fn(),
|
|
25
|
+
removeMessage: vi.fn(() => Promise.resolve({ success: true, messages: [] })),
|
|
26
26
|
removeMessagesByAssistant: vi.fn(),
|
|
27
|
-
removeMessages: vi.fn(() => Promise.resolve()),
|
|
27
|
+
removeMessages: vi.fn(() => Promise.resolve({ success: true, messages: [] })),
|
|
28
28
|
createMessage: vi.fn(() => Promise.resolve({ id: 'new-message-id', messages: [] })),
|
|
29
|
-
updateMessage: vi.fn(),
|
|
29
|
+
updateMessage: vi.fn(() => Promise.resolve({ success: true, messages: [] })),
|
|
30
|
+
updateMessageMetadata: vi.fn(() => Promise.resolve({ success: true, messages: [] })),
|
|
31
|
+
updateMessagePluginError: vi.fn(() => Promise.resolve({ success: true, messages: [] })),
|
|
32
|
+
updateMessageRAG: vi.fn(() => Promise.resolve({ success: true, messages: [] })),
|
|
30
33
|
removeAllMessages: vi.fn(() => Promise.resolve()),
|
|
31
34
|
},
|
|
32
35
|
}));
|
|
@@ -224,7 +227,10 @@ describe('chatMessage actions', () => {
|
|
|
224
227
|
});
|
|
225
228
|
|
|
226
229
|
expect(deleteSpy).toHaveBeenCalledWith(messageId);
|
|
227
|
-
expect(replaceMessagesSpy).toHaveBeenCalledWith(mockMessages
|
|
230
|
+
expect(replaceMessagesSpy).toHaveBeenCalledWith(mockMessages, {
|
|
231
|
+
sessionId: 'session-id',
|
|
232
|
+
topicId: undefined,
|
|
233
|
+
});
|
|
228
234
|
});
|
|
229
235
|
|
|
230
236
|
it('deleteMessage should remove the message only', async () => {
|
|
@@ -266,7 +272,10 @@ describe('chatMessage actions', () => {
|
|
|
266
272
|
sessionId: 'session-id',
|
|
267
273
|
topicId: undefined,
|
|
268
274
|
});
|
|
269
|
-
expect(replaceMessagesSpy).toHaveBeenCalledWith(mockMessages
|
|
275
|
+
expect(replaceMessagesSpy).toHaveBeenCalledWith(mockMessages, {
|
|
276
|
+
sessionId: 'session-id',
|
|
277
|
+
topicId: undefined,
|
|
278
|
+
});
|
|
270
279
|
});
|
|
271
280
|
|
|
272
281
|
it('deleteMessage should remove assistantGroup message with all children', async () => {
|
|
@@ -317,7 +326,10 @@ describe('chatMessage actions', () => {
|
|
|
317
326
|
sessionId: 'session-id',
|
|
318
327
|
topicId: undefined,
|
|
319
328
|
});
|
|
320
|
-
expect(replaceMessagesSpy).toHaveBeenCalledWith(mockMessages
|
|
329
|
+
expect(replaceMessagesSpy).toHaveBeenCalledWith(mockMessages, {
|
|
330
|
+
sessionId: 'session-id',
|
|
331
|
+
topicId: undefined,
|
|
332
|
+
});
|
|
321
333
|
});
|
|
322
334
|
|
|
323
335
|
it('deleteMessage should remove group message with children that have tool calls', async () => {
|
|
@@ -381,7 +393,10 @@ describe('chatMessage actions', () => {
|
|
|
381
393
|
topicId: undefined,
|
|
382
394
|
},
|
|
383
395
|
);
|
|
384
|
-
expect(replaceMessagesSpy).toHaveBeenCalledWith(mockMessages
|
|
396
|
+
expect(replaceMessagesSpy).toHaveBeenCalledWith(mockMessages, {
|
|
397
|
+
sessionId: 'session-id',
|
|
398
|
+
topicId: undefined,
|
|
399
|
+
});
|
|
385
400
|
});
|
|
386
401
|
});
|
|
387
402
|
|
|
@@ -417,51 +432,84 @@ describe('chatMessage actions', () => {
|
|
|
417
432
|
|
|
418
433
|
describe('deleteToolMessage', () => {
|
|
419
434
|
it('deleteMessage should remove a message by id', async () => {
|
|
420
|
-
const { result } = renderHook(() => useChatStore());
|
|
421
435
|
const messageId = 'message-id';
|
|
422
|
-
const
|
|
423
|
-
const
|
|
436
|
+
const sessionId = 'session-id';
|
|
437
|
+
const topicId = null;
|
|
424
438
|
|
|
439
|
+
const rawMessages = [
|
|
440
|
+
{
|
|
441
|
+
id: messageId,
|
|
442
|
+
role: 'assistant',
|
|
443
|
+
tools: [{ id: 'tool1' }, { id: 'tool2' }],
|
|
444
|
+
} as UIChatMessage,
|
|
445
|
+
{
|
|
446
|
+
id: '2',
|
|
447
|
+
parentId: messageId,
|
|
448
|
+
tool_call_id: 'tool1',
|
|
449
|
+
role: 'tool',
|
|
450
|
+
} as UIChatMessage,
|
|
451
|
+
{ id: '3', tool_call_id: 'tool2', role: 'tool' } as UIChatMessage,
|
|
452
|
+
];
|
|
453
|
+
|
|
454
|
+
const key = messageMapKey(sessionId, topicId);
|
|
425
455
|
act(() => {
|
|
426
|
-
const rawMessages = [
|
|
427
|
-
{
|
|
428
|
-
id: messageId,
|
|
429
|
-
role: 'assistant',
|
|
430
|
-
tools: [{ id: 'tool1' }, { id: 'tool2' }],
|
|
431
|
-
} as UIChatMessage,
|
|
432
|
-
{
|
|
433
|
-
id: '2',
|
|
434
|
-
parentId: messageId,
|
|
435
|
-
tool_call_id: 'tool1',
|
|
436
|
-
role: 'tool',
|
|
437
|
-
} as UIChatMessage,
|
|
438
|
-
{ id: '3', tool_call_id: 'tool2', role: 'tool' } as UIChatMessage,
|
|
439
|
-
];
|
|
440
|
-
|
|
441
456
|
useChatStore.setState({
|
|
442
|
-
activeId:
|
|
443
|
-
activeTopicId:
|
|
457
|
+
activeId: sessionId,
|
|
458
|
+
activeTopicId: topicId as unknown as string,
|
|
444
459
|
dbMessagesMap: {
|
|
445
|
-
[
|
|
460
|
+
[key]: rawMessages,
|
|
446
461
|
},
|
|
447
462
|
messagesMap: {
|
|
448
|
-
[
|
|
463
|
+
[key]: rawMessages,
|
|
449
464
|
},
|
|
450
465
|
});
|
|
451
466
|
});
|
|
467
|
+
|
|
468
|
+
const { result } = renderHook(() => useChatStore());
|
|
469
|
+
|
|
470
|
+
// Mock removeMessage to return the remaining messages after deletion
|
|
471
|
+
// Note: tool1 is also removed from the assistant message's tools to reflect the concurrent update
|
|
472
|
+
const remainingAfterDelete = [
|
|
473
|
+
{
|
|
474
|
+
id: messageId,
|
|
475
|
+
role: 'assistant',
|
|
476
|
+
tools: [{ id: 'tool2' }],
|
|
477
|
+
} as UIChatMessage,
|
|
478
|
+
{ id: '3', tool_call_id: 'tool2', role: 'tool' } as UIChatMessage,
|
|
479
|
+
];
|
|
480
|
+
|
|
481
|
+
// Mock updateMessage to return updated messages after tool removal
|
|
482
|
+
const updatedMessages = [
|
|
483
|
+
{
|
|
484
|
+
id: messageId,
|
|
485
|
+
role: 'assistant',
|
|
486
|
+
tools: [{ id: 'tool2' }],
|
|
487
|
+
} as UIChatMessage,
|
|
488
|
+
{ id: '3', tool_call_id: 'tool2', role: 'tool' } as UIChatMessage,
|
|
489
|
+
];
|
|
490
|
+
|
|
491
|
+
const refreshToolsSpy = vi.spyOn(result.current, 'internal_refreshToUpdateMessageTools');
|
|
492
|
+
const updateMessageSpy = vi
|
|
493
|
+
.spyOn(messageService, 'updateMessage')
|
|
494
|
+
.mockResolvedValue({ success: true, messages: updatedMessages });
|
|
495
|
+
const removeMessageSpy = vi
|
|
496
|
+
.spyOn(messageService, 'removeMessage')
|
|
497
|
+
.mockResolvedValue({ success: true, messages: remainingAfterDelete });
|
|
498
|
+
|
|
452
499
|
await act(async () => {
|
|
453
500
|
await result.current.deleteToolMessage('2');
|
|
454
501
|
});
|
|
455
502
|
|
|
456
503
|
expect(removeMessageSpy).toHaveBeenCalled();
|
|
504
|
+
expect(refreshToolsSpy).toHaveBeenCalledWith('message-id', undefined);
|
|
457
505
|
expect(updateMessageSpy).toHaveBeenCalledWith(
|
|
458
506
|
'message-id',
|
|
459
507
|
{
|
|
460
508
|
tools: [{ id: 'tool2' }],
|
|
461
509
|
},
|
|
462
510
|
{
|
|
463
|
-
sessionId
|
|
464
|
-
topicId
|
|
511
|
+
sessionId,
|
|
512
|
+
topicId,
|
|
465
513
|
},
|
|
466
514
|
);
|
|
467
515
|
});
|
|
@@ -647,16 +695,23 @@ describe('chatMessage actions', () => {
|
|
|
647
695
|
});
|
|
648
696
|
});
|
|
649
697
|
|
|
650
|
-
it('should
|
|
698
|
+
it('should replace messages after updating content', async () => {
|
|
651
699
|
const { result } = renderHook(() => useChatStore());
|
|
652
700
|
const messageId = 'message-id';
|
|
653
701
|
const newContent = 'Updated content';
|
|
702
|
+
const replaceMessagesSpy = vi.spyOn(result.current, 'replaceMessages');
|
|
654
703
|
|
|
655
704
|
await act(async () => {
|
|
656
705
|
await result.current.optimisticUpdateMessageContent(messageId, newContent);
|
|
657
706
|
});
|
|
658
707
|
|
|
659
|
-
expect(
|
|
708
|
+
expect(replaceMessagesSpy).toHaveBeenCalledWith(
|
|
709
|
+
[],
|
|
710
|
+
expect.objectContaining({
|
|
711
|
+
sessionId: 'session-id',
|
|
712
|
+
topicId: 'topic-id',
|
|
713
|
+
}),
|
|
714
|
+
);
|
|
660
715
|
});
|
|
661
716
|
});
|
|
662
717
|
|
|
@@ -802,4 +857,98 @@ describe('chatMessage actions', () => {
|
|
|
802
857
|
});
|
|
803
858
|
});
|
|
804
859
|
});
|
|
860
|
+
|
|
861
|
+
describe('OptimisticUpdateContext isolation', () => {
|
|
862
|
+
beforeEach(() => {
|
|
863
|
+
vi.clearAllMocks();
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
it('optimisticUpdateMessageContent should use context sessionId/topicId', async () => {
|
|
867
|
+
const { result } = renderHook(() => useChatStore());
|
|
868
|
+
const messageId = 'message-id';
|
|
869
|
+
const content = 'Updated content';
|
|
870
|
+
const contextSessionId = 'context-session-id';
|
|
871
|
+
const contextTopicId = 'context-topic-id';
|
|
872
|
+
|
|
873
|
+
const updateMessageSpy = vi.spyOn(messageService, 'updateMessage');
|
|
874
|
+
|
|
875
|
+
await act(async () => {
|
|
876
|
+
await result.current.optimisticUpdateMessageContent(messageId, content, undefined, {
|
|
877
|
+
sessionId: contextSessionId,
|
|
878
|
+
topicId: contextTopicId,
|
|
879
|
+
});
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
expect(updateMessageSpy).toHaveBeenCalledWith(
|
|
883
|
+
messageId,
|
|
884
|
+
{ content, tools: undefined },
|
|
885
|
+
{ sessionId: contextSessionId, topicId: contextTopicId },
|
|
886
|
+
);
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
it('optimisticUpdateMessageError should use context sessionId/topicId', async () => {
|
|
890
|
+
const { result } = renderHook(() => useChatStore());
|
|
891
|
+
const messageId = 'message-id';
|
|
892
|
+
const error = { message: 'Error occurred', type: 'error' as any };
|
|
893
|
+
const contextSessionId = 'context-session';
|
|
894
|
+
const contextTopicId = 'context-topic';
|
|
895
|
+
|
|
896
|
+
const updateMessageSpy = vi.spyOn(messageService, 'updateMessage');
|
|
897
|
+
|
|
898
|
+
await act(async () => {
|
|
899
|
+
await result.current.optimisticUpdateMessageError(messageId, error, {
|
|
900
|
+
sessionId: contextSessionId,
|
|
901
|
+
topicId: contextTopicId,
|
|
902
|
+
});
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
expect(updateMessageSpy).toHaveBeenCalledWith(
|
|
906
|
+
messageId,
|
|
907
|
+
{ error },
|
|
908
|
+
{ sessionId: contextSessionId, topicId: contextTopicId },
|
|
909
|
+
);
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
it('optimisticDeleteMessage should use context sessionId/topicId', async () => {
|
|
913
|
+
const { result } = renderHook(() => useChatStore());
|
|
914
|
+
const messageId = 'message-id';
|
|
915
|
+
const contextSessionId = 'context-session';
|
|
916
|
+
const contextTopicId = 'context-topic';
|
|
917
|
+
|
|
918
|
+
const removeMessageSpy = vi.spyOn(messageService, 'removeMessage');
|
|
919
|
+
|
|
920
|
+
await act(async () => {
|
|
921
|
+
await result.current.optimisticDeleteMessage(messageId, {
|
|
922
|
+
sessionId: contextSessionId,
|
|
923
|
+
topicId: contextTopicId,
|
|
924
|
+
});
|
|
925
|
+
});
|
|
926
|
+
|
|
927
|
+
expect(removeMessageSpy).toHaveBeenCalledWith(messageId, {
|
|
928
|
+
sessionId: contextSessionId,
|
|
929
|
+
topicId: contextTopicId,
|
|
930
|
+
});
|
|
931
|
+
});
|
|
932
|
+
|
|
933
|
+
it('optimisticDeleteMessages should use context sessionId/topicId', async () => {
|
|
934
|
+
const { result } = renderHook(() => useChatStore());
|
|
935
|
+
const ids = ['id-1', 'id-2'];
|
|
936
|
+
const contextSessionId = 'context-session';
|
|
937
|
+
const contextTopicId = 'context-topic';
|
|
938
|
+
|
|
939
|
+
const removeMessagesSpy = vi.spyOn(messageService, 'removeMessages');
|
|
940
|
+
|
|
941
|
+
await act(async () => {
|
|
942
|
+
await result.current.optimisticDeleteMessages(ids, {
|
|
943
|
+
sessionId: contextSessionId,
|
|
944
|
+
topicId: contextTopicId,
|
|
945
|
+
});
|
|
946
|
+
});
|
|
947
|
+
|
|
948
|
+
expect(removeMessagesSpy).toHaveBeenCalledWith(ids, {
|
|
949
|
+
sessionId: contextSessionId,
|
|
950
|
+
topicId: contextTopicId,
|
|
951
|
+
});
|
|
952
|
+
});
|
|
953
|
+
});
|
|
805
954
|
});
|
|
@@ -17,6 +17,14 @@ import { StateCreator } from 'zustand/vanilla';
|
|
|
17
17
|
import { messageService } from '@/services/message';
|
|
18
18
|
import { ChatStore } from '@/store/chat/store';
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Context for optimistic updates to specify session/topic isolation
|
|
22
|
+
*/
|
|
23
|
+
export interface OptimisticUpdateContext {
|
|
24
|
+
sessionId?: string;
|
|
25
|
+
topicId?: string | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
20
28
|
/**
|
|
21
29
|
* Optimistic update operations
|
|
22
30
|
* All methods follow the pattern: update frontend first, then persist to database
|
|
@@ -28,7 +36,13 @@ export interface MessageOptimisticUpdateAction {
|
|
|
28
36
|
*/
|
|
29
37
|
optimisticCreateMessage: (
|
|
30
38
|
params: CreateMessageParams,
|
|
31
|
-
context?: {
|
|
39
|
+
context?: {
|
|
40
|
+
groupMessageId?: string;
|
|
41
|
+
sessionId?: string;
|
|
42
|
+
skipRefresh?: boolean;
|
|
43
|
+
tempMessageId?: string;
|
|
44
|
+
topicId?: string | null;
|
|
45
|
+
},
|
|
32
46
|
) => Promise<{ id: string; messages: UIChatMessage[] } | undefined>;
|
|
33
47
|
|
|
34
48
|
/**
|
|
@@ -40,8 +54,8 @@ export interface MessageOptimisticUpdateAction {
|
|
|
40
54
|
/**
|
|
41
55
|
* delete the message content with optimistic update
|
|
42
56
|
*/
|
|
43
|
-
optimisticDeleteMessage: (id: string) => Promise<void>;
|
|
44
|
-
optimisticDeleteMessages: (ids: string[]) => Promise<void>;
|
|
57
|
+
optimisticDeleteMessage: (id: string, context?: OptimisticUpdateContext) => Promise<void>;
|
|
58
|
+
optimisticDeleteMessages: (ids: string[], context?: OptimisticUpdateContext) => Promise<void>;
|
|
45
59
|
|
|
46
60
|
/**
|
|
47
61
|
* update the message content with optimistic update
|
|
@@ -59,12 +73,17 @@ export interface MessageOptimisticUpdateAction {
|
|
|
59
73
|
search?: GroundingSearch;
|
|
60
74
|
toolCalls?: MessageToolCall[];
|
|
61
75
|
},
|
|
76
|
+
context?: OptimisticUpdateContext,
|
|
62
77
|
) => Promise<void>;
|
|
63
78
|
|
|
64
79
|
/**
|
|
65
80
|
* update the message error with optimistic update
|
|
66
81
|
*/
|
|
67
|
-
optimisticUpdateMessageError: (
|
|
82
|
+
optimisticUpdateMessageError: (
|
|
83
|
+
id: string,
|
|
84
|
+
error: ChatMessageError | null,
|
|
85
|
+
context?: OptimisticUpdateContext,
|
|
86
|
+
) => Promise<void>;
|
|
68
87
|
|
|
69
88
|
/**
|
|
70
89
|
* update the message metadata with optimistic update
|
|
@@ -72,6 +91,7 @@ export interface MessageOptimisticUpdateAction {
|
|
|
72
91
|
optimisticUpdateMessageMetadata: (
|
|
73
92
|
id: string,
|
|
74
93
|
metadata: Partial<MessageMetadata>,
|
|
94
|
+
context?: OptimisticUpdateContext,
|
|
75
95
|
) => Promise<void>;
|
|
76
96
|
|
|
77
97
|
/**
|
|
@@ -80,12 +100,17 @@ export interface MessageOptimisticUpdateAction {
|
|
|
80
100
|
optimisticUpdateMessagePluginError: (
|
|
81
101
|
id: string,
|
|
82
102
|
error: ChatMessagePluginError | null,
|
|
103
|
+
context?: OptimisticUpdateContext,
|
|
83
104
|
) => Promise<void>;
|
|
84
105
|
|
|
85
106
|
/**
|
|
86
107
|
* update message RAG with optimistic update
|
|
87
108
|
*/
|
|
88
|
-
optimisticUpdateMessageRAG: (
|
|
109
|
+
optimisticUpdateMessageRAG: (
|
|
110
|
+
id: string,
|
|
111
|
+
input: UpdateMessageRAGParams,
|
|
112
|
+
context?: OptimisticUpdateContext,
|
|
113
|
+
) => Promise<void>;
|
|
89
114
|
}
|
|
90
115
|
|
|
91
116
|
export const messageOptimisticUpdate: StateCreator<
|
|
@@ -113,7 +138,9 @@ export const messageOptimisticUpdate: StateCreator<
|
|
|
113
138
|
|
|
114
139
|
if (!context?.skipRefresh) {
|
|
115
140
|
// Use the messages returned from createMessage (already grouped)
|
|
116
|
-
|
|
141
|
+
const sessionId = context?.sessionId ?? get().activeId;
|
|
142
|
+
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
143
|
+
replaceMessages(result.messages, { sessionId, topicId });
|
|
117
144
|
}
|
|
118
145
|
|
|
119
146
|
internal_toggleMessageLoading(false, tempId);
|
|
@@ -144,29 +171,33 @@ export const messageOptimisticUpdate: StateCreator<
|
|
|
144
171
|
return tempId;
|
|
145
172
|
},
|
|
146
173
|
|
|
147
|
-
optimisticDeleteMessage: async (id: string) => {
|
|
174
|
+
optimisticDeleteMessage: async (id: string, context) => {
|
|
148
175
|
get().internal_dispatchMessage({ id, type: 'deleteMessage' });
|
|
176
|
+
const sessionId = context?.sessionId ?? get().activeId;
|
|
177
|
+
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
149
178
|
const result = await messageService.removeMessage(id, {
|
|
150
|
-
sessionId
|
|
151
|
-
topicId
|
|
179
|
+
sessionId,
|
|
180
|
+
topicId,
|
|
152
181
|
});
|
|
153
182
|
if (result?.success && result.messages) {
|
|
154
|
-
get().replaceMessages(result.messages);
|
|
183
|
+
get().replaceMessages(result.messages, { sessionId, topicId });
|
|
155
184
|
}
|
|
156
185
|
},
|
|
157
186
|
|
|
158
|
-
optimisticDeleteMessages: async (ids) => {
|
|
187
|
+
optimisticDeleteMessages: async (ids, context) => {
|
|
159
188
|
get().internal_dispatchMessage({ ids, type: 'deleteMessages' });
|
|
189
|
+
const sessionId = context?.sessionId ?? get().activeId;
|
|
190
|
+
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
160
191
|
const result = await messageService.removeMessages(ids, {
|
|
161
|
-
sessionId
|
|
162
|
-
topicId
|
|
192
|
+
sessionId,
|
|
193
|
+
topicId,
|
|
163
194
|
});
|
|
164
195
|
if (result?.success && result.messages) {
|
|
165
|
-
get().replaceMessages(result.messages);
|
|
196
|
+
get().replaceMessages(result.messages, { sessionId, topicId });
|
|
166
197
|
}
|
|
167
198
|
},
|
|
168
199
|
|
|
169
|
-
optimisticUpdateMessageContent: async (id, content, extra) => {
|
|
200
|
+
optimisticUpdateMessageContent: async (id, content, extra, context) => {
|
|
170
201
|
const {
|
|
171
202
|
internal_dispatchMessage,
|
|
172
203
|
refreshMessages,
|
|
@@ -191,6 +222,9 @@ export const messageOptimisticUpdate: StateCreator<
|
|
|
191
222
|
});
|
|
192
223
|
}
|
|
193
224
|
|
|
225
|
+
const sessionId = context?.sessionId ?? get().activeId;
|
|
226
|
+
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
227
|
+
|
|
194
228
|
const result = await messageService.updateMessage(
|
|
195
229
|
id,
|
|
196
230
|
{
|
|
@@ -203,31 +237,33 @@ export const messageOptimisticUpdate: StateCreator<
|
|
|
203
237
|
search: extra?.search,
|
|
204
238
|
tools: extra?.toolCalls ? internal_transformToolCalls(extra?.toolCalls) : undefined,
|
|
205
239
|
},
|
|
206
|
-
{ sessionId
|
|
240
|
+
{ sessionId, topicId },
|
|
207
241
|
);
|
|
208
242
|
|
|
209
243
|
if (result && result.success && result.messages) {
|
|
210
|
-
replaceMessages(result.messages, {
|
|
244
|
+
replaceMessages(result.messages, {
|
|
245
|
+
action: 'optimisticUpdateMessageContent',
|
|
246
|
+
sessionId,
|
|
247
|
+
topicId,
|
|
248
|
+
});
|
|
211
249
|
} else {
|
|
212
250
|
await refreshMessages();
|
|
213
251
|
}
|
|
214
252
|
},
|
|
215
253
|
|
|
216
|
-
optimisticUpdateMessageError: async (id, error) => {
|
|
254
|
+
optimisticUpdateMessageError: async (id, error, context) => {
|
|
217
255
|
get().internal_dispatchMessage({ id, type: 'updateMessage', value: { error } });
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
{ sessionId: get().activeId, topicId: get().activeTopicId },
|
|
222
|
-
);
|
|
256
|
+
const sessionId = context?.sessionId ?? get().activeId;
|
|
257
|
+
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
258
|
+
const result = await messageService.updateMessage(id, { error }, { sessionId, topicId });
|
|
223
259
|
if (result?.success && result.messages) {
|
|
224
|
-
get().replaceMessages(result.messages);
|
|
260
|
+
get().replaceMessages(result.messages, { sessionId, topicId });
|
|
225
261
|
} else {
|
|
226
262
|
await get().refreshMessages();
|
|
227
263
|
}
|
|
228
264
|
},
|
|
229
265
|
|
|
230
|
-
optimisticUpdateMessageMetadata: async (id, metadata) => {
|
|
266
|
+
optimisticUpdateMessageMetadata: async (id, metadata, context) => {
|
|
231
267
|
const { internal_dispatchMessage, refreshMessages, replaceMessages } = get();
|
|
232
268
|
|
|
233
269
|
// Optimistic update: update the frontend immediately
|
|
@@ -237,36 +273,43 @@ export const messageOptimisticUpdate: StateCreator<
|
|
|
237
273
|
value: metadata,
|
|
238
274
|
});
|
|
239
275
|
|
|
276
|
+
const sessionId = context?.sessionId ?? get().activeId;
|
|
277
|
+
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
278
|
+
|
|
240
279
|
// Persist to database
|
|
241
280
|
const result = await messageService.updateMessageMetadata(id, metadata, {
|
|
242
|
-
sessionId
|
|
243
|
-
topicId
|
|
281
|
+
sessionId,
|
|
282
|
+
topicId,
|
|
244
283
|
});
|
|
245
284
|
|
|
246
285
|
if (result?.success && result.messages) {
|
|
247
|
-
replaceMessages(result.messages);
|
|
286
|
+
replaceMessages(result.messages, { sessionId, topicId });
|
|
248
287
|
} else {
|
|
249
288
|
await refreshMessages();
|
|
250
289
|
}
|
|
251
290
|
},
|
|
252
291
|
|
|
253
|
-
optimisticUpdateMessagePluginError: async (id, error) => {
|
|
292
|
+
optimisticUpdateMessagePluginError: async (id, error, context) => {
|
|
293
|
+
const sessionId = context?.sessionId ?? get().activeId;
|
|
294
|
+
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
254
295
|
const result = await messageService.updateMessagePluginError(id, error, {
|
|
255
|
-
sessionId
|
|
256
|
-
topicId
|
|
296
|
+
sessionId,
|
|
297
|
+
topicId,
|
|
257
298
|
});
|
|
258
299
|
if (result?.success && result.messages) {
|
|
259
|
-
get().replaceMessages(result.messages);
|
|
300
|
+
get().replaceMessages(result.messages, { sessionId, topicId });
|
|
260
301
|
}
|
|
261
302
|
},
|
|
262
303
|
|
|
263
|
-
optimisticUpdateMessageRAG: async (id, data) => {
|
|
304
|
+
optimisticUpdateMessageRAG: async (id, data, context) => {
|
|
305
|
+
const sessionId = context?.sessionId ?? get().activeId;
|
|
306
|
+
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
264
307
|
const result = await messageService.updateMessageRAG(id, data, {
|
|
265
|
-
sessionId
|
|
266
|
-
topicId
|
|
308
|
+
sessionId,
|
|
309
|
+
topicId,
|
|
267
310
|
});
|
|
268
311
|
if (result?.success && result.messages) {
|
|
269
|
-
get().replaceMessages(result.messages);
|
|
312
|
+
get().replaceMessages(result.messages, { sessionId, topicId });
|
|
270
313
|
}
|
|
271
314
|
},
|
|
272
315
|
});
|