@lobehub/lobehub 2.0.0-next.273 → 2.0.0-next.274
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 +34 -0
- package/changelog/v1.json +9 -0
- package/locales/ar/chat.json +7 -0
- package/locales/ar/models.json +2 -3
- package/locales/ar/plugin.json +22 -1
- package/locales/bg-BG/chat.json +7 -0
- package/locales/bg-BG/models.json +3 -3
- package/locales/bg-BG/plugin.json +22 -1
- package/locales/de-DE/chat.json +7 -0
- package/locales/de-DE/models.json +3 -4
- package/locales/de-DE/plugin.json +22 -1
- package/locales/en-US/chat.json +7 -0
- package/locales/en-US/models.json +5 -5
- package/locales/en-US/plugin.json +22 -1
- package/locales/es-ES/chat.json +7 -0
- package/locales/es-ES/models.json +3 -4
- package/locales/es-ES/plugin.json +22 -1
- package/locales/fa-IR/chat.json +7 -0
- package/locales/fa-IR/models.json +3 -4
- package/locales/fa-IR/plugin.json +22 -1
- package/locales/fr-FR/chat.json +7 -0
- package/locales/fr-FR/models.json +50 -3
- package/locales/fr-FR/plugin.json +22 -1
- package/locales/it-IT/chat.json +7 -0
- package/locales/it-IT/models.json +3 -3
- package/locales/it-IT/plugin.json +22 -1
- package/locales/ja-JP/chat.json +7 -0
- package/locales/ja-JP/models.json +43 -4
- package/locales/ja-JP/plugin.json +22 -1
- package/locales/ko-KR/chat.json +7 -0
- package/locales/ko-KR/models.json +3 -4
- package/locales/ko-KR/plugin.json +22 -1
- package/locales/nl-NL/chat.json +7 -0
- package/locales/nl-NL/models.json +51 -3
- package/locales/nl-NL/plugin.json +22 -1
- package/locales/pl-PL/chat.json +7 -0
- package/locales/pl-PL/models.json +3 -3
- package/locales/pl-PL/plugin.json +22 -1
- package/locales/pt-BR/chat.json +7 -0
- package/locales/pt-BR/models.json +3 -4
- package/locales/pt-BR/plugin.json +22 -1
- package/locales/ru-RU/chat.json +7 -0
- package/locales/ru-RU/models.json +3 -4
- package/locales/ru-RU/plugin.json +22 -1
- package/locales/tr-TR/chat.json +7 -0
- package/locales/tr-TR/models.json +3 -4
- package/locales/tr-TR/plugin.json +22 -1
- package/locales/vi-VN/chat.json +7 -0
- package/locales/vi-VN/models.json +3 -3
- package/locales/vi-VN/plugin.json +22 -1
- package/locales/zh-CN/chat.json +7 -0
- package/locales/zh-CN/models.json +54 -4
- package/locales/zh-CN/plugin.json +22 -1
- package/locales/zh-TW/chat.json +7 -0
- package/locales/zh-TW/models.json +43 -4
- package/locales/zh-TW/plugin.json +22 -1
- package/package.json +1 -1
- package/packages/builtin-tool-agent-builder/package.json +1 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/GetAvailableModels/index.tsx +66 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/InstallPlugin/index.tsx +63 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/SearchMarketTools/index.tsx +64 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/UpdateConfig/index.tsx +94 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/UpdatePrompt/index.tsx +96 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/index.ts +29 -0
- package/packages/builtin-tool-agent-builder/src/client/index.ts +13 -0
- package/packages/builtin-tool-agent-builder/src/executor.ts +132 -0
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/ExecuteCode/index.tsx +5 -14
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/RunCommand/index.tsx +5 -13
- package/packages/builtin-tool-group-agent-builder/package.json +7 -1
- package/packages/builtin-tool-group-agent-builder/src/ExecutionRuntime/index.ts +331 -87
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/BatchCreateAgents/index.tsx +110 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/CreateAgent/index.tsx +72 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/InviteAgent/index.tsx +57 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/RemoveAgent/index.tsx +57 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/SearchAgent/index.tsx +66 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/UpdateAgentPrompt/index.tsx +120 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/UpdateGroup/index.tsx +87 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/UpdateGroupPrompt/index.tsx +99 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/index.ts +52 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Render/BatchCreateAgents.tsx +103 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Render/UpdateAgentPrompt/index.tsx +36 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Render/UpdateGroupPrompt/index.tsx +36 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Render/index.ts +16 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Streaming/BatchCreateAgents/index.tsx +88 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Streaming/UpdateAgentPrompt/index.tsx +37 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Streaming/UpdateGroupPrompt/index.tsx +35 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Streaming/index.ts +22 -0
- package/packages/builtin-tool-group-agent-builder/src/client/index.ts +26 -0
- package/packages/builtin-tool-group-agent-builder/src/executor.ts +284 -0
- package/packages/builtin-tool-group-agent-builder/src/index.ts +1 -14
- package/packages/builtin-tool-group-agent-builder/src/manifest.ts +160 -15
- package/packages/builtin-tool-group-agent-builder/src/systemRole.ts +232 -46
- package/packages/builtin-tool-group-agent-builder/src/types.ts +191 -41
- package/packages/builtin-tool-group-management/src/client/Inspector/Broadcast/index.tsx +2 -2
- package/packages/builtin-tool-group-management/src/manifest.ts +1 -1
- package/packages/builtin-tool-gtd/src/client/Inspector/ClearTodos/index.tsx +5 -11
- package/packages/builtin-tool-gtd/src/client/Inspector/CompleteTodos/index.tsx +3 -9
- package/packages/builtin-tool-gtd/src/client/Inspector/CreatePlan/index.tsx +6 -15
- package/packages/builtin-tool-gtd/src/client/Inspector/CreateTodos/index.tsx +3 -9
- package/packages/builtin-tool-gtd/src/client/Inspector/ExecTask/index.tsx +6 -17
- package/packages/builtin-tool-gtd/src/client/Inspector/RemoveTodos/index.tsx +3 -9
- package/packages/builtin-tool-gtd/src/client/Inspector/UpdatePlan/index.tsx +3 -9
- package/packages/builtin-tool-gtd/src/client/Inspector/UpdateTodos/index.tsx +3 -9
- package/packages/builtin-tool-knowledge-base/src/client/Inspector/ReadKnowledge/index.tsx +4 -16
- package/packages/builtin-tool-knowledge-base/src/client/Inspector/SearchKnowledgeBase/index.tsx +5 -16
- package/packages/builtin-tool-local-system/src/client/Inspector/EditLocalFile/index.tsx +4 -12
- package/packages/builtin-tool-local-system/src/client/Inspector/GlobLocalFiles/index.tsx +5 -13
- package/packages/builtin-tool-local-system/src/client/Inspector/GrepContent/index.tsx +5 -16
- package/packages/builtin-tool-local-system/src/client/Inspector/ListLocalFiles/index.tsx +5 -16
- package/packages/builtin-tool-local-system/src/client/Inspector/ReadLocalFile/index.tsx +5 -16
- package/packages/builtin-tool-local-system/src/client/Inspector/RenameLocalFile/index.tsx +5 -11
- package/packages/builtin-tool-local-system/src/client/Inspector/RunCommand/index.tsx +5 -13
- package/packages/builtin-tool-local-system/src/client/Inspector/SearchLocalFiles/index.tsx +5 -16
- package/packages/builtin-tool-local-system/src/client/Inspector/WriteLocalFile/index.tsx +6 -15
- package/packages/builtin-tool-notebook/src/client/Inspector/CreateDocument/index.tsx +7 -15
- package/packages/builtin-tool-page-agent/src/client/Inspector/EditTitle/index.tsx +5 -14
- package/packages/builtin-tool-page-agent/src/client/Inspector/GetPageContent/index.tsx +7 -8
- package/packages/builtin-tool-page-agent/src/client/Inspector/InitPage/index.tsx +4 -10
- package/packages/builtin-tool-page-agent/src/client/Inspector/ModifyNodes/index.tsx +3 -9
- package/packages/builtin-tool-page-agent/src/client/Inspector/ReplaceText/index.tsx +5 -11
- package/packages/builtin-tool-web-browsing/src/client/Inspector/CrawlMultiPages/index.tsx +6 -15
- package/packages/builtin-tool-web-browsing/src/client/Inspector/CrawlSinglePage/index.tsx +6 -15
- package/packages/builtin-tool-web-browsing/src/client/Inspector/Search/index.tsx +4 -15
- package/packages/database/src/models/chatGroup.ts +1 -1
- package/packages/model-bank/src/aiModels/aihubmix.ts +2 -1
- package/packages/model-bank/src/aiModels/google.ts +2 -1
- package/packages/model-bank/src/aiModels/infiniai.ts +9 -6
- package/packages/model-bank/src/aiModels/minimax.ts +9 -5
- package/packages/model-bank/src/aiModels/ollamacloud.ts +4 -2
- package/packages/model-bank/src/aiModels/vertexai.ts +2 -1
- package/packages/types/src/agentGroup/index.ts +8 -0
- package/patches/@upstash__qstash.patch +13 -1
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Header/Nav.tsx +1 -1
- package/src/app/[variants]/(main)/agent/cron/[cronId]/index.tsx +4 -3
- package/src/app/[variants]/(main)/agent/profile/features/ProfileEditor/index.tsx +1 -1
- package/src/app/[variants]/(main)/agent/profile/features/store/action.ts +18 -21
- package/src/app/[variants]/(main)/group/_layout/GroupIdSync.tsx +6 -1
- package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/AgentProfilePopup.tsx +29 -21
- package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/GroupMember.tsx +1 -0
- package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/GroupMemberItem.tsx +35 -18
- package/src/app/[variants]/(main)/group/_layout/Sidebar/Header/AddTopicButon.tsx +2 -10
- package/src/app/[variants]/(main)/group/_layout/Sidebar/Header/Nav.tsx +10 -2
- package/src/app/[variants]/(main)/group/_layout/Sidebar/Header/index.tsx +1 -2
- package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/AgentBuilderProvider.tsx +1 -0
- package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/TopicSelector.tsx +15 -9
- package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/index.tsx +12 -6
- package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor/AgentHeader.tsx → GroupProfile/GroupHeader.tsx} +22 -29
- package/src/app/[variants]/(main)/group/profile/features/GroupProfile/index.tsx +96 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/AgentBuilderToggle.tsx +3 -4
- package/src/app/[variants]/(main)/group/profile/features/Header/AutoSaveHint.tsx +11 -7
- package/src/app/[variants]/(main)/group/profile/features/Header/ChromeTabs/index.tsx +147 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/index.tsx +104 -13
- package/src/app/[variants]/(main)/group/profile/features/MemberProfile/AgentHeader.tsx +222 -0
- package/src/app/[variants]/(main)/group/profile/features/MemberProfile/index.tsx +155 -0
- package/src/app/[variants]/(main)/group/profile/features/ProfileHydration.tsx +63 -5
- package/src/app/[variants]/(main)/group/profile/index.tsx +34 -37
- package/src/app/[variants]/(mobile)/(home)/_layout/SessionHydration.tsx +1 -1
- package/src/app/[variants]/(mobile)/(home)/features/SessionListContent/List/Item/index.tsx +1 -1
- package/src/features/AgentBuilder/index.tsx +16 -1
- package/src/features/Conversation/Messages/AssistantGroup/Tool/Inspector/StatusIndicator.tsx +3 -2
- package/src/features/EditorCanvas/EditorCanvas.test.tsx +206 -0
- package/src/features/EditorCanvas/EditorDataMode.tsx +53 -19
- package/src/features/EditorModal/index.tsx +2 -2
- package/src/features/NavPanel/components/SessionHydration.tsx +1 -1
- package/src/features/ShareModal/ShareImage/ChatList/index.tsx +1 -1
- package/src/features/ShareModal/SharePdf/index.tsx +1 -1
- package/src/hooks/useBidirectionalQuerySync.ts +112 -0
- package/src/locales/default/chat.ts +10 -0
- package/src/locales/default/plugin.ts +22 -1
- package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +45 -45
- package/src/server/modules/KeyVaultsEncrypt/index.ts +6 -6
- package/src/server/modules/S3/index.ts +1 -1
- package/src/server/routers/lambda/agent.ts +24 -0
- package/src/server/routers/lambda/agentGroup.ts +39 -0
- package/src/services/agent.ts +22 -0
- package/src/services/chatGroup/index.ts +14 -0
- package/src/store/agent/selectors/selectors.ts +3 -0
- package/src/store/agentGroup/initialState.ts +6 -0
- package/src/store/agentGroup/selectors/byId.ts +3 -1
- package/src/store/agentGroup/selectors/current.ts +2 -2
- package/src/store/agentGroup/slices/lifecycle.ts +18 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/fixtures/mockStore.ts +1 -1
- package/src/store/chat/slices/aiAgent/actions/__tests__/agentGroup.test.ts +4 -1
- package/src/store/chat/slices/aiAgent/actions/agentGroup.ts +1 -1
- package/src/store/chat/slices/aiChat/actions/__tests__/conversationLifecycle.test.ts +65 -0
- package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +2 -1
- package/src/store/chat/slices/builtinTool/actions/__tests__/search.test.ts +1 -1
- package/src/store/chat/slices/builtinTool/actions/index.ts +1 -6
- package/src/store/chat/slices/message/action.test.ts +5 -5
- package/src/store/chat/slices/message/actions/publicApi.ts +5 -5
- package/src/store/chat/slices/message/initialState.ts +0 -5
- package/src/store/chat/slices/message/selectors/displayMessage.test.ts +4 -4
- package/src/store/chat/slices/plugin/action.test.ts +54 -19
- package/src/store/chat/slices/plugin/actions/pluginTypes.ts +15 -21
- package/src/store/chat/slices/topic/action.test.ts +74 -24
- package/src/store/chat/slices/topic/action.ts +21 -13
- package/src/store/chat/slices/topic/selectors.test.ts +1 -1
- package/src/store/global/initialState.ts +10 -0
- package/src/store/global/selectors/systemStatus.ts +5 -0
- package/src/store/groupProfile/action.ts +168 -0
- package/src/store/groupProfile/index.ts +16 -0
- package/src/{app/[variants]/(main)/group/profile/features/store → store/groupProfile}/initialState.ts +17 -0
- package/src/store/groupProfile/selectors.ts +13 -0
- package/src/store/tool/slices/builtin/executors/index.ts +4 -0
- package/src/styles/text.ts +16 -0
- package/src/tools/inspectors.ts +13 -0
- package/src/tools/renders.ts +3 -0
- package/src/tools/streamings.ts +8 -0
- package/src/app/[variants]/(main)/group/profile/features/EditorCanvas/TypoBar.tsx +0 -129
- package/src/app/[variants]/(main)/group/profile/features/EditorCanvas/index.tsx +0 -138
- package/src/app/[variants]/(main)/group/profile/features/EditorCanvas/useSlashItems.tsx +0 -139
- package/src/app/[variants]/(main)/group/profile/features/ProfileEditor/index.tsx +0 -82
- package/src/app/[variants]/(main)/group/profile/features/ProfileProvider.tsx +0 -20
- package/src/app/[variants]/(main)/group/profile/features/StoreUpdater.tsx +0 -24
- package/src/app/[variants]/(main)/group/profile/features/store/action.ts +0 -163
- package/src/app/[variants]/(main)/group/profile/features/store/index.ts +0 -23
- package/src/app/[variants]/(main)/group/profile/features/store/selectors.ts +0 -7
- package/src/features/EditorModal/EditorCanvas.tsx +0 -84
- package/src/features/EditorModal/Typobar.tsx +0 -139
- package/src/store/chat/slices/builtinTool/actions/agentBuilder.ts +0 -192
- package/src/store/chat/slices/builtinTool/actions/groupAgentBuilder.ts +0 -242
- package/src/tools/executionRuntimes.ts +0 -14
- /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/AgentTool.tsx +0 -0
- /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/MentionDropdown.tsx +0 -0
- /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/index.tsx +0 -0
- /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/types.ts +0 -0
- /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/useMentionItems.tsx +0 -0
package/src/services/agent.ts
CHANGED
|
@@ -51,6 +51,15 @@ export interface CreateAgentResult {
|
|
|
51
51
|
sessionId: string;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
export interface CreateAgentOnlyParams {
|
|
55
|
+
config?: PartialDeep<AgentItem>;
|
|
56
|
+
groupId: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface CreateAgentOnlyResult {
|
|
60
|
+
agentId: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
54
63
|
class AgentService {
|
|
55
64
|
/**
|
|
56
65
|
* Check if an agent with the given marketIdentifier already exists
|
|
@@ -80,6 +89,19 @@ class AgentService {
|
|
|
80
89
|
});
|
|
81
90
|
};
|
|
82
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Create a virtual agent without session.
|
|
94
|
+
* Used for Group Agent Builder to create virtual agents for groups.
|
|
95
|
+
*/
|
|
96
|
+
createAgentOnly = async (params: CreateAgentOnlyParams): Promise<CreateAgentOnlyResult> => {
|
|
97
|
+
const normalizedConfig = normalizeMarketAgentModel(params.config);
|
|
98
|
+
|
|
99
|
+
return lambdaClient.agent.createAgentOnly.mutate({
|
|
100
|
+
config: normalizedConfig as any,
|
|
101
|
+
groupId: params.groupId,
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
|
|
83
105
|
createAgentKnowledgeBase = async (
|
|
84
106
|
agentId: string,
|
|
85
107
|
knowledgeBaseId: string,
|
|
@@ -85,6 +85,20 @@ class ChatGroupService {
|
|
|
85
85
|
return lambdaClient.group.addAgentsToGroup.mutate({ agentIds, groupId });
|
|
86
86
|
};
|
|
87
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Batch create virtual agents and add them to an existing group.
|
|
90
|
+
* This is more efficient than calling createAgentOnly multiple times.
|
|
91
|
+
*/
|
|
92
|
+
batchCreateAgentsInGroup = (
|
|
93
|
+
groupId: string,
|
|
94
|
+
agents: GroupMemberConfig[],
|
|
95
|
+
) => {
|
|
96
|
+
return lambdaClient.group.batchCreateAgentsInGroup.mutate({
|
|
97
|
+
agents: agents as Partial<AgentItem>[],
|
|
98
|
+
groupId,
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
|
|
88
102
|
removeAgentsFromGroup = (groupId: string, agentIds: string[]) => {
|
|
89
103
|
return lambdaClient.group.removeAgentsFromGroup.mutate({ agentIds, groupId });
|
|
90
104
|
};
|
|
@@ -260,6 +260,8 @@ const currentAgentLocalSystemConfig = (s: AgentStoreState): LocalSystemConfig |
|
|
|
260
260
|
const currentAgentWorkingDirectory = (s: AgentStoreState): string | undefined =>
|
|
261
261
|
currentAgentLocalSystemConfig(s)?.workingDirectory;
|
|
262
262
|
|
|
263
|
+
const isCurrentAgentExternal = (s: AgentStoreState): boolean => !currentAgentData(s)?.virtual;
|
|
264
|
+
|
|
263
265
|
export const agentSelectors = {
|
|
264
266
|
currentAgentAvatar,
|
|
265
267
|
currentAgentBackgroundColor,
|
|
@@ -293,6 +295,7 @@ export const agentSelectors = {
|
|
|
293
295
|
inboxAgentModel,
|
|
294
296
|
isAgentConfigLoading,
|
|
295
297
|
isAgentModeEnabled,
|
|
298
|
+
isCurrentAgentExternal,
|
|
296
299
|
openingMessage,
|
|
297
300
|
openingQuestions,
|
|
298
301
|
};
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import type { AgentGroupDetail } from '@lobechat/types';
|
|
2
|
+
import type { ParsedQuery } from 'query-string';
|
|
2
3
|
|
|
3
4
|
import type { ChatGroupItem } from '@/database/schemas/chatGroup';
|
|
4
5
|
|
|
6
|
+
export interface QueryRouter {
|
|
7
|
+
push: (url: string, options?: { query?: ParsedQuery }) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
5
10
|
export interface ChatGroupState {
|
|
6
11
|
activeGroupId?: string;
|
|
7
12
|
activeThreadAgentId: string;
|
|
8
13
|
groupMap: Record<string, AgentGroupDetail>;
|
|
9
14
|
groups: ChatGroupItem[];
|
|
10
15
|
groupsInit: boolean;
|
|
16
|
+
router?: QueryRouter;
|
|
11
17
|
showGroupSetting: boolean;
|
|
12
18
|
/**
|
|
13
19
|
* Content being streamed for system prompt update (for GroupAgentBuilder)
|
|
@@ -19,6 +19,8 @@ const groupConfig = (groupId: string) => (s: ChatGroupStore) => {
|
|
|
19
19
|
const groupMeta = (groupId: string) => (s: ChatGroupStore) => {
|
|
20
20
|
const group = groupById(groupId)(s);
|
|
21
21
|
return merge(DEFAULT_CHAT_GROUP_META_CONFIG, {
|
|
22
|
+
avatar: group?.avatar || undefined,
|
|
23
|
+
backgroundColor: group?.backgroundColor || undefined,
|
|
22
24
|
description: group?.description || '',
|
|
23
25
|
title: group?.title || '',
|
|
24
26
|
});
|
|
@@ -26,7 +28,7 @@ const groupMeta = (groupId: string) => (s: ChatGroupStore) => {
|
|
|
26
28
|
|
|
27
29
|
const groupAgents =
|
|
28
30
|
(groupId: string) =>
|
|
29
|
-
(s: ChatGroupStore):
|
|
31
|
+
(s: ChatGroupStore): AgentGroupMember[] => {
|
|
30
32
|
const group = groupById(groupId)(s);
|
|
31
33
|
return group?.agents || [];
|
|
32
34
|
};
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
DEFAULT_CHAT_GROUP_CHAT_CONFIG,
|
|
4
4
|
DEFAULT_CHAT_GROUP_META_CONFIG,
|
|
5
5
|
} from '@lobechat/const';
|
|
6
|
-
import type { AgentGroupDetail, AgentGroupMember
|
|
6
|
+
import type { AgentGroupDetail, AgentGroupMember } from '@lobechat/types';
|
|
7
7
|
|
|
8
8
|
import type { ChatGroupState } from '../initialState';
|
|
9
9
|
import type { ChatGroupStore } from '../store';
|
|
@@ -36,7 +36,7 @@ const currentGroupMeta = (s: ChatGroupStore) => {
|
|
|
36
36
|
return groupId ? agentGroupByIdSelectors.groupMeta(groupId)(s) : DEFAULT_CHAT_GROUP_META_CONFIG;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
const currentGroupAgents = (s: ChatGroupStore):
|
|
39
|
+
const currentGroupAgents = (s: ChatGroupStore): AgentGroupMember[] => {
|
|
40
40
|
const groupId = activeGroupId(s);
|
|
41
41
|
return groupId ? agentGroupByIdSelectors.groupAgents(groupId)(s) : [];
|
|
42
42
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { NewChatGroup } from '@lobechat/types';
|
|
2
|
+
import urlJoin from 'url-join';
|
|
2
3
|
import { type StateCreator } from 'zustand/vanilla';
|
|
3
4
|
|
|
4
5
|
import { chatGroupService } from '@/services/chatGroup';
|
|
5
6
|
import { type ChatGroupStore } from '@/store/agentGroup/store';
|
|
7
|
+
import { useChatStore } from '@/store/chat';
|
|
6
8
|
import { getSessionStoreState } from '@/store/session';
|
|
7
9
|
|
|
8
10
|
export interface ChatGroupLifecycleAction {
|
|
@@ -11,6 +13,11 @@ export interface ChatGroupLifecycleAction {
|
|
|
11
13
|
agentIds?: string[],
|
|
12
14
|
silent?: boolean,
|
|
13
15
|
) => Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Switch to a new topic in the group
|
|
18
|
+
* Clears activeTopicId and navigates to group root
|
|
19
|
+
*/
|
|
20
|
+
switchToNewTopic: () => void;
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
export const chatGroupLifecycleSlice: StateCreator<
|
|
@@ -48,4 +55,15 @@ export const chatGroupLifecycleSlice: StateCreator<
|
|
|
48
55
|
|
|
49
56
|
return group.id;
|
|
50
57
|
},
|
|
58
|
+
|
|
59
|
+
switchToNewTopic: () => {
|
|
60
|
+
const { activeGroupId, router } = get();
|
|
61
|
+
if (!activeGroupId || !router) return;
|
|
62
|
+
|
|
63
|
+
useChatStore.setState({ activeTopicId: undefined });
|
|
64
|
+
|
|
65
|
+
router.push(urlJoin('/group', activeGroupId), {
|
|
66
|
+
query: { bt: null, tab: null, thread: null, topic: null },
|
|
67
|
+
});
|
|
68
|
+
},
|
|
51
69
|
});
|
|
@@ -556,7 +556,10 @@ describe('agentGroup actions', () => {
|
|
|
556
556
|
});
|
|
557
557
|
});
|
|
558
558
|
|
|
559
|
-
expect(result.current.switchTopic).toHaveBeenCalledWith(TEST_IDS.TOPIC_ID,
|
|
559
|
+
expect(result.current.switchTopic).toHaveBeenCalledWith(TEST_IDS.TOPIC_ID, {
|
|
560
|
+
clearNewKey: true,
|
|
561
|
+
skipRefreshMessage: true,
|
|
562
|
+
});
|
|
560
563
|
});
|
|
561
564
|
|
|
562
565
|
it('should not switch topic when using existing topic', async () => {
|
|
@@ -118,7 +118,7 @@ export const agentGroupSlice: StateCreator<
|
|
|
118
118
|
|
|
119
119
|
// 4. Switch to new topic if created
|
|
120
120
|
if (result.isCreateNewTopic && result.topicId) {
|
|
121
|
-
await get().switchTopic(result.topicId, true);
|
|
121
|
+
await get().switchTopic(result.topicId, { clearNewKey: true, skipRefreshMessage: true });
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
// 5. Create execContext with updated topicId from server response
|
|
@@ -3,6 +3,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
3
3
|
|
|
4
4
|
import { aiChatService } from '@/services/aiChat';
|
|
5
5
|
import * as agentGroupStore from '@/store/agentGroup';
|
|
6
|
+
import { messageMapKey } from '@/store/chat/utils/messageMapKey';
|
|
6
7
|
import { getSessionStoreState } from '@/store/session';
|
|
7
8
|
|
|
8
9
|
import { useChatStore } from '../../../../store';
|
|
@@ -353,5 +354,69 @@ describe('ConversationLifecycle actions', () => {
|
|
|
353
354
|
);
|
|
354
355
|
});
|
|
355
356
|
});
|
|
357
|
+
|
|
358
|
+
describe('new topic creation cleanup', () => {
|
|
359
|
+
it('should clear _new key data when new topic is created', async () => {
|
|
360
|
+
const { result } = renderHook(() => useChatStore());
|
|
361
|
+
const agentId = TEST_IDS.SESSION_ID;
|
|
362
|
+
const newTopicId = 'created-topic-id';
|
|
363
|
+
|
|
364
|
+
// Setup initial state: messages exist in the _new key (no topicId)
|
|
365
|
+
const newKey = messageMapKey({ agentId, topicId: null });
|
|
366
|
+
const existingMessages = [
|
|
367
|
+
createMockMessage({ id: 'old-msg-1', role: 'user' }),
|
|
368
|
+
createMockMessage({ id: 'old-msg-2', role: 'assistant' }),
|
|
369
|
+
];
|
|
370
|
+
|
|
371
|
+
await act(async () => {
|
|
372
|
+
useChatStore.setState({
|
|
373
|
+
activeAgentId: agentId,
|
|
374
|
+
activeTopicId: undefined,
|
|
375
|
+
messagesMap: {
|
|
376
|
+
[newKey]: existingMessages,
|
|
377
|
+
},
|
|
378
|
+
dbMessagesMap: {
|
|
379
|
+
[newKey]: existingMessages,
|
|
380
|
+
},
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
// Verify messages exist in _new key before sending
|
|
385
|
+
expect(useChatStore.getState().messagesMap[newKey]).toHaveLength(2);
|
|
386
|
+
|
|
387
|
+
// Mock server response with new topic creation
|
|
388
|
+
vi.spyOn(aiChatService, 'sendMessageInServer').mockResolvedValue({
|
|
389
|
+
messages: [
|
|
390
|
+
createMockMessage({ id: 'new-user-msg', role: 'user', topicId: newTopicId }),
|
|
391
|
+
createMockMessage({ id: 'new-assistant-msg', role: 'assistant', topicId: newTopicId }),
|
|
392
|
+
],
|
|
393
|
+
topics: { items: [{ id: newTopicId, title: 'New Topic' }], total: 1 },
|
|
394
|
+
topicId: newTopicId,
|
|
395
|
+
isCreateNewTopic: true,
|
|
396
|
+
assistantMessageId: 'new-assistant-msg',
|
|
397
|
+
userMessageId: 'new-user-msg',
|
|
398
|
+
} as any);
|
|
399
|
+
|
|
400
|
+
// Mock switchTopic to verify it's called correctly
|
|
401
|
+
const switchTopicSpy = vi.spyOn(result.current, 'switchTopic');
|
|
402
|
+
|
|
403
|
+
await act(async () => {
|
|
404
|
+
await result.current.sendMessage({
|
|
405
|
+
message: TEST_CONTENT.USER_MESSAGE,
|
|
406
|
+
context: { agentId, topicId: null, threadId: null },
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
// switchTopic should be called with the new topicId and clearNewKey option
|
|
411
|
+
expect(switchTopicSpy).toHaveBeenCalledWith(newTopicId, {
|
|
412
|
+
clearNewKey: true,
|
|
413
|
+
skipRefreshMessage: true,
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// After new topic creation, the _new key should be cleared
|
|
417
|
+
const messagesInNewKey = useChatStore.getState().messagesMap[newKey];
|
|
418
|
+
expect(messagesInNewKey ?? []).toHaveLength(0);
|
|
419
|
+
});
|
|
420
|
+
});
|
|
356
421
|
});
|
|
357
422
|
});
|
|
@@ -286,7 +286,8 @@ export const conversationLifecycle: StateCreator<
|
|
|
286
286
|
});
|
|
287
287
|
|
|
288
288
|
if (data.isCreateNewTopic && data.topicId) {
|
|
289
|
-
|
|
289
|
+
// clearNewKey: true ensures the _new key data is cleared after topic creation
|
|
290
|
+
await get().switchTopic(data.topicId, { clearNewKey: true, skipRefreshMessage: true });
|
|
290
291
|
}
|
|
291
292
|
} catch (e) {
|
|
292
293
|
console.error(e);
|
|
@@ -43,7 +43,7 @@ describe('search actions', () => {
|
|
|
43
43
|
invokeBuiltinTool: vi.fn(),
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
// Default mock for dbMessageSelectors - returns undefined to use
|
|
46
|
+
// Default mock for dbMessageSelectors - returns undefined to use activeAgentId/activeTopicId
|
|
47
47
|
vi.spyOn(dbMessageSelectors, 'getDbMessageById').mockImplementation(() => () => undefined);
|
|
48
48
|
});
|
|
49
49
|
|
|
@@ -2,13 +2,10 @@ import { type StateCreator } from 'zustand/vanilla';
|
|
|
2
2
|
|
|
3
3
|
import { type ChatStore } from '@/store/chat/store';
|
|
4
4
|
|
|
5
|
-
import { type AgentBuilderAction, agentBuilderSlice } from './agentBuilder';
|
|
6
|
-
import { type GroupAgentBuilderAction, groupAgentBuilderSlice } from './groupAgentBuilder';
|
|
7
5
|
import { type ChatCodeInterpreterAction, codeInterpreterSlice } from './interpreter';
|
|
8
6
|
import { type SearchAction, searchSlice } from './search';
|
|
9
7
|
|
|
10
|
-
export interface ChatBuiltinToolAction
|
|
11
|
-
extends SearchAction, ChatCodeInterpreterAction, AgentBuilderAction, GroupAgentBuilderAction {}
|
|
8
|
+
export interface ChatBuiltinToolAction extends SearchAction, ChatCodeInterpreterAction {}
|
|
12
9
|
|
|
13
10
|
export const chatToolSlice: StateCreator<
|
|
14
11
|
ChatStore,
|
|
@@ -18,6 +15,4 @@ export const chatToolSlice: StateCreator<
|
|
|
18
15
|
> = (...params) => ({
|
|
19
16
|
...searchSlice(...params),
|
|
20
17
|
...codeInterpreterSlice(...params),
|
|
21
|
-
...agentBuilderSlice(...params),
|
|
22
|
-
...groupAgentBuilderSlice(...params),
|
|
23
18
|
});
|
|
@@ -75,7 +75,7 @@ afterEach(() => {
|
|
|
75
75
|
|
|
76
76
|
describe('chatMessage actions', () => {
|
|
77
77
|
describe('addAIMessage', () => {
|
|
78
|
-
it('should return early if
|
|
78
|
+
it('should return early if activeAgentId is undefined', async () => {
|
|
79
79
|
useChatStore.setState({ activeAgentId: undefined });
|
|
80
80
|
const { result } = renderHook(() => useChatStore());
|
|
81
81
|
const updateMessageInputSpy = vi.spyOn(result.current, 'updateMessageInput');
|
|
@@ -117,7 +117,7 @@ describe('chatMessage actions', () => {
|
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
describe('addUserMessage', () => {
|
|
120
|
-
it('should return early if
|
|
120
|
+
it('should return early if activeAgentId is undefined', async () => {
|
|
121
121
|
useChatStore.setState({ activeAgentId: undefined });
|
|
122
122
|
const { result } = renderHook(() => useChatStore());
|
|
123
123
|
const updateMessageInputSpy = vi.spyOn(result.current, 'updateMessageInput');
|
|
@@ -739,7 +739,7 @@ describe('chatMessage actions', () => {
|
|
|
739
739
|
useChatStore.setState({ refreshMessages: realRefreshMessages });
|
|
740
740
|
|
|
741
741
|
const { result } = renderHook(() => useChatStore());
|
|
742
|
-
const
|
|
742
|
+
const activeAgentId = useChatStore.getState().activeAgentId;
|
|
743
743
|
const activeTopicId = useChatStore.getState().activeTopicId;
|
|
744
744
|
|
|
745
745
|
// 在这里,我们不需要再次模拟 mutate,因为它已经在顶部被模拟了
|
|
@@ -750,13 +750,13 @@ describe('chatMessage actions', () => {
|
|
|
750
750
|
// 确保 mutate 调用了正确的参数(session 和 group 两次)
|
|
751
751
|
expect(mutate).toHaveBeenCalledWith([
|
|
752
752
|
'SWR_USE_FETCH_MESSAGES',
|
|
753
|
-
|
|
753
|
+
activeAgentId,
|
|
754
754
|
activeTopicId,
|
|
755
755
|
'session',
|
|
756
756
|
]);
|
|
757
757
|
expect(mutate).toHaveBeenCalledWith([
|
|
758
758
|
'SWR_USE_FETCH_MESSAGES',
|
|
759
|
-
|
|
759
|
+
activeAgentId,
|
|
760
760
|
activeTopicId,
|
|
761
761
|
'group',
|
|
762
762
|
]);
|
|
@@ -235,16 +235,16 @@ export const messagePublicApi: StateCreator<
|
|
|
235
235
|
},
|
|
236
236
|
|
|
237
237
|
clearMessage: async () => {
|
|
238
|
-
const {
|
|
238
|
+
const { activeAgentId, activeTopicId, activeGroupId, refreshTopic, switchTopic } = get();
|
|
239
239
|
|
|
240
240
|
// For group sessions, we need to clear group messages using groupId
|
|
241
|
-
// For regular sessions, we clear session messages using
|
|
241
|
+
// For regular sessions, we clear session messages using agentId
|
|
242
242
|
if (activeGroupId) {
|
|
243
243
|
// For group chat, activeGroupId is the groupId
|
|
244
244
|
await messageService.removeMessagesByGroup(activeGroupId, activeTopicId);
|
|
245
245
|
} else {
|
|
246
|
-
// For regular session,
|
|
247
|
-
await messageService.removeMessagesByAssistant(
|
|
246
|
+
// For regular session, activeAgentId is the agentId
|
|
247
|
+
await messageService.removeMessagesByAssistant(activeAgentId, activeTopicId);
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
if (activeTopicId) {
|
|
@@ -256,7 +256,7 @@ export const messagePublicApi: StateCreator<
|
|
|
256
256
|
get().replaceMessages([]);
|
|
257
257
|
|
|
258
258
|
// after remove topic , go back to default topic
|
|
259
|
-
switchTopic();
|
|
259
|
+
switchTopic(null);
|
|
260
260
|
},
|
|
261
261
|
|
|
262
262
|
clearAllMessages: async () => {
|
|
@@ -4,10 +4,6 @@ import { type ChatGroupAgentItem } from '@/database/schemas/chatGroup';
|
|
|
4
4
|
|
|
5
5
|
export interface ChatMessageState {
|
|
6
6
|
activeAgentId: string;
|
|
7
|
-
/**
|
|
8
|
-
* @deprecated
|
|
9
|
-
*/
|
|
10
|
-
activeId: string;
|
|
11
7
|
/**
|
|
12
8
|
* Raw messages from database (flat structure)
|
|
13
9
|
*/
|
|
@@ -37,7 +33,6 @@ export interface ChatMessageState {
|
|
|
37
33
|
|
|
38
34
|
export const initialMessageState: ChatMessageState = {
|
|
39
35
|
activeAgentId: '',
|
|
40
|
-
activeId: 'inbox',
|
|
41
36
|
dbMessagesMap: {},
|
|
42
37
|
groupAgentMaps: {},
|
|
43
38
|
isCreatingMessage: false,
|
|
@@ -288,7 +288,7 @@ describe('displayMessageSelectors', () => {
|
|
|
288
288
|
});
|
|
289
289
|
|
|
290
290
|
describe('currentDisplayChatKey', () => {
|
|
291
|
-
it('should generate correct key with
|
|
291
|
+
it('should generate correct key with activeAgentId only', () => {
|
|
292
292
|
const state: Partial<ChatStore> = {
|
|
293
293
|
activeAgentId: 'testId',
|
|
294
294
|
activeTopicId: undefined,
|
|
@@ -297,7 +297,7 @@ describe('displayMessageSelectors', () => {
|
|
|
297
297
|
expect(result).toBe(messageMapKey({ agentId: 'testId', topicId: undefined }));
|
|
298
298
|
});
|
|
299
299
|
|
|
300
|
-
it('should generate correct key with both
|
|
300
|
+
it('should generate correct key with both activeAgentId and activeTopicId', () => {
|
|
301
301
|
const state: Partial<ChatStore> = {
|
|
302
302
|
activeAgentId: 'testId',
|
|
303
303
|
activeTopicId: 'topicId',
|
|
@@ -306,7 +306,7 @@ describe('displayMessageSelectors', () => {
|
|
|
306
306
|
expect(result).toBe(messageMapKey({ agentId: 'testId', topicId: 'topicId' }));
|
|
307
307
|
});
|
|
308
308
|
|
|
309
|
-
it('should generate key with undefined
|
|
309
|
+
it('should generate key with undefined activeAgentId', () => {
|
|
310
310
|
const state: Partial<ChatStore> = {
|
|
311
311
|
activeAgentId: undefined,
|
|
312
312
|
activeTopicId: 'topicId',
|
|
@@ -315,7 +315,7 @@ describe('displayMessageSelectors', () => {
|
|
|
315
315
|
expect(result).toBe(messageMapKey({ agentId: undefined as any, topicId: 'topicId' }));
|
|
316
316
|
});
|
|
317
317
|
|
|
318
|
-
it('should generate key with empty string
|
|
318
|
+
it('should generate key with empty string activeAgentId', () => {
|
|
319
319
|
const state: Partial<ChatStore> = {
|
|
320
320
|
activeAgentId: '',
|
|
321
321
|
activeTopicId: undefined,
|
|
@@ -381,18 +381,27 @@ describe('ChatPluginAction', () => {
|
|
|
381
381
|
});
|
|
382
382
|
|
|
383
383
|
describe('invokeBuiltinTool', () => {
|
|
384
|
-
it('should invoke
|
|
384
|
+
it('should invoke Tool Store executor with parsed arguments', async () => {
|
|
385
385
|
const payload = {
|
|
386
|
+
identifier: 'test-tool',
|
|
386
387
|
apiName: 'mockBuiltinAction',
|
|
387
388
|
arguments: JSON.stringify({ input: 'test', value: 123 }),
|
|
388
389
|
} as ChatToolPayload;
|
|
389
390
|
|
|
390
391
|
const messageId = 'message-id';
|
|
391
|
-
const
|
|
392
|
+
const mockInvokeBuiltinTool = vi.fn().mockResolvedValue({
|
|
393
|
+
content: 'result',
|
|
394
|
+
success: true,
|
|
395
|
+
});
|
|
392
396
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
397
|
+
// Mock hasExecutor to return true
|
|
398
|
+
const hasExecutorModule = await import('@/store/tool/slices/builtin/executors');
|
|
399
|
+
vi.spyOn(hasExecutorModule, 'hasExecutor').mockReturnValue(true);
|
|
400
|
+
|
|
401
|
+
// Mock Tool Store's invokeBuiltinTool
|
|
402
|
+
vi.spyOn(useToolStore.getState(), 'invokeBuiltinTool').mockImplementation(
|
|
403
|
+
mockInvokeBuiltinTool,
|
|
404
|
+
);
|
|
396
405
|
|
|
397
406
|
const { result } = renderHook(() => useChatStore());
|
|
398
407
|
|
|
@@ -400,52 +409,70 @@ describe('ChatPluginAction', () => {
|
|
|
400
409
|
await result.current.invokeBuiltinTool(messageId, payload);
|
|
401
410
|
});
|
|
402
411
|
|
|
403
|
-
// Verify that
|
|
404
|
-
expect(
|
|
412
|
+
// Verify that Tool Store's invokeBuiltinTool was called with correct arguments
|
|
413
|
+
expect(mockInvokeBuiltinTool).toHaveBeenCalledWith(
|
|
414
|
+
'test-tool',
|
|
415
|
+
'mockBuiltinAction',
|
|
416
|
+
{ input: 'test', value: 123 },
|
|
417
|
+
expect.objectContaining({
|
|
418
|
+
messageId,
|
|
419
|
+
}),
|
|
420
|
+
);
|
|
405
421
|
});
|
|
406
422
|
|
|
407
|
-
it('should not
|
|
423
|
+
it('should not throw error if executor does not exist', async () => {
|
|
408
424
|
const payload = {
|
|
425
|
+
identifier: 'non-existent-tool',
|
|
409
426
|
apiName: 'nonExistentAction',
|
|
410
427
|
arguments: JSON.stringify({ key: 'value' }),
|
|
411
428
|
} as ChatToolPayload;
|
|
412
429
|
|
|
413
430
|
const messageId = 'message-id';
|
|
414
431
|
|
|
432
|
+
// Mock hasExecutor to return false
|
|
433
|
+
const hasExecutorModule = await import('@/store/tool/slices/builtin/executors');
|
|
434
|
+
vi.spyOn(hasExecutorModule, 'hasExecutor').mockReturnValue(false);
|
|
435
|
+
|
|
436
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
437
|
+
|
|
415
438
|
const { result } = renderHook(() => useChatStore());
|
|
416
439
|
|
|
417
440
|
await act(async () => {
|
|
418
441
|
await result.current.invokeBuiltinTool(messageId, payload);
|
|
419
442
|
});
|
|
420
443
|
|
|
421
|
-
// Should
|
|
444
|
+
// Should log error but not throw
|
|
445
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('No executor found'));
|
|
446
|
+
|
|
447
|
+
consoleErrorSpy.mockRestore();
|
|
422
448
|
});
|
|
423
449
|
|
|
424
|
-
it('should
|
|
450
|
+
it('should return error result if arguments cannot be parsed', async () => {
|
|
425
451
|
const payload = {
|
|
452
|
+
identifier: 'test-tool',
|
|
426
453
|
apiName: 'mockBuiltinAction',
|
|
427
454
|
arguments: 'invalid json',
|
|
428
455
|
} as ChatToolPayload;
|
|
429
456
|
|
|
430
457
|
const messageId = 'message-id';
|
|
431
|
-
const mockActionFn = vi.fn().mockResolvedValue(undefined);
|
|
432
|
-
|
|
433
|
-
useChatStore.setState({
|
|
434
|
-
mockBuiltinAction: mockActionFn,
|
|
435
|
-
} as any);
|
|
436
458
|
|
|
437
459
|
const { result } = renderHook(() => useChatStore());
|
|
438
460
|
|
|
461
|
+
let returnValue: any;
|
|
439
462
|
await act(async () => {
|
|
440
|
-
await result.current.invokeBuiltinTool(messageId, payload);
|
|
463
|
+
returnValue = await result.current.invokeBuiltinTool(messageId, payload);
|
|
441
464
|
});
|
|
442
465
|
|
|
443
|
-
// Should
|
|
444
|
-
expect(
|
|
466
|
+
// Should return error result for invalid JSON
|
|
467
|
+
expect(returnValue).toEqual({ error: 'Invalid arguments', success: false });
|
|
445
468
|
});
|
|
446
469
|
|
|
447
470
|
describe('registerAfterCompletion with Tool Store executor', () => {
|
|
448
471
|
it('should create registerAfterCompletion when root execAgentRuntime operation exists', async () => {
|
|
472
|
+
// Mock hasExecutor to return true
|
|
473
|
+
const hasExecutorModule = await import('@/store/tool/slices/builtin/executors');
|
|
474
|
+
vi.spyOn(hasExecutorModule, 'hasExecutor').mockReturnValue(true);
|
|
475
|
+
|
|
449
476
|
// Setup: Create operation hierarchy
|
|
450
477
|
// execAgentRuntime -> toolCalling -> executeToolCall
|
|
451
478
|
const { result } = renderHook(() => useChatStore());
|
|
@@ -527,6 +554,10 @@ describe('ChatPluginAction', () => {
|
|
|
527
554
|
});
|
|
528
555
|
|
|
529
556
|
it('should not pass registerAfterCompletion when no root operation exists', async () => {
|
|
557
|
+
// Mock hasExecutor to return true
|
|
558
|
+
const hasExecutorModule = await import('@/store/tool/slices/builtin/executors');
|
|
559
|
+
vi.spyOn(hasExecutorModule, 'hasExecutor').mockReturnValue(true);
|
|
560
|
+
|
|
530
561
|
const { result } = renderHook(() => useChatStore());
|
|
531
562
|
const messageId = 'tool-message-id';
|
|
532
563
|
|
|
@@ -558,6 +589,10 @@ describe('ChatPluginAction', () => {
|
|
|
558
589
|
});
|
|
559
590
|
|
|
560
591
|
it('should find root operation through multiple levels of hierarchy', async () => {
|
|
592
|
+
// Mock hasExecutor to return true
|
|
593
|
+
const hasExecutorModule = await import('@/store/tool/slices/builtin/executors');
|
|
594
|
+
vi.spyOn(hasExecutorModule, 'hasExecutor').mockReturnValue(true);
|
|
595
|
+
|
|
561
596
|
const { result } = renderHook(() => useChatStore());
|
|
562
597
|
|
|
563
598
|
let execAgentRuntimeOpId: string;
|
|
@@ -1147,7 +1182,7 @@ describe('ChatPluginAction', () => {
|
|
|
1147
1182
|
});
|
|
1148
1183
|
});
|
|
1149
1184
|
|
|
1150
|
-
it('should fallback to
|
|
1185
|
+
it('should fallback to activeAgentId/activeTopicId when context not provided', async () => {
|
|
1151
1186
|
const { result } = renderHook(() => useChatStore());
|
|
1152
1187
|
const messageId = 'message-id';
|
|
1153
1188
|
const pluginState = { key: 'value' };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* eslint-disable sort-keys-fix/sort-keys-fix, typescript-sort-keys/interface */
|
|
2
2
|
import { CloudSandboxIdentifier, type ExportFileState } from '@lobechat/builtin-tool-cloud-sandbox';
|
|
3
|
-
import { GroupAgentBuilderIdentifier } from '@lobechat/builtin-tool-group-agent-builder';
|
|
4
3
|
import { type ChatToolPayload, type RuntimeStepContext } from '@lobechat/types';
|
|
5
4
|
import { PluginErrorType } from '@lobehub/chat-plugin-sdk';
|
|
6
5
|
import debug from 'debug';
|
|
@@ -125,9 +124,17 @@ export const pluginTypes: StateCreator<
|
|
|
125
124
|
|
|
126
125
|
// Get agent ID, group ID, and topic ID from operation context
|
|
127
126
|
const agentId = operation?.context?.agentId;
|
|
128
|
-
|
|
127
|
+
let groupId = operation?.context?.groupId;
|
|
129
128
|
const topicId = operation?.context?.topicId;
|
|
130
129
|
|
|
130
|
+
// For group-agent-builder tools, inject activeGroupId from store if not in context
|
|
131
|
+
// This is needed because AgentBuilderProvider uses a separate scope for messages
|
|
132
|
+
// but still needs groupId for tool execution
|
|
133
|
+
if (!groupId && payload.identifier === 'lobe-group-agent-builder') {
|
|
134
|
+
const { getChatGroupStoreState } = await import('@/store/agentGroup');
|
|
135
|
+
groupId = getChatGroupStoreState().activeGroupId;
|
|
136
|
+
}
|
|
137
|
+
|
|
131
138
|
// Get group orchestration callbacks if available (for group management tools)
|
|
132
139
|
const groupOrchestration = get().getGroupOrchestrationCallbacks?.();
|
|
133
140
|
|
|
@@ -209,25 +216,12 @@ export const pluginTypes: StateCreator<
|
|
|
209
216
|
return result;
|
|
210
217
|
}
|
|
211
218
|
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
// run tool api call (fallback for AgentBuilder and other legacy tools)
|
|
219
|
-
// @ts-ignore
|
|
220
|
-
const { [payload.apiName]: action } = get();
|
|
221
|
-
if (!action) {
|
|
222
|
-
console.error(`[invokeBuiltinTool] plugin Action not found: ${payload.apiName}`);
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
const content = safeParseJSON(payload.arguments);
|
|
227
|
-
|
|
228
|
-
if (!content) return;
|
|
229
|
-
|
|
230
|
-
return await action(id, content);
|
|
219
|
+
// All builtin tools should be handled by the executor registry above
|
|
220
|
+
// If we reach here, it means the tool is not registered
|
|
221
|
+
console.error(
|
|
222
|
+
`[invokeBuiltinTool] No executor found for: ${payload.identifier}/${payload.apiName}`,
|
|
223
|
+
);
|
|
224
|
+
return;
|
|
231
225
|
},
|
|
232
226
|
|
|
233
227
|
invokeCloudCodeInterpreterTool: async (id, payload) => {
|