@lobehub/lobehub 2.0.0-next.295 → 2.0.0-next.297

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/locales/en-US/plugin.json +4 -0
  4. package/locales/zh-CN/plugin.json +4 -0
  5. package/package.json +2 -2
  6. package/packages/agent-runtime/src/core/__tests__/runtime.test.ts +5 -5
  7. package/packages/agent-runtime/src/utils/stepContextComputer.test.ts +5 -5
  8. package/packages/builtin-tool-gtd/src/client/Inspector/index.ts +0 -4
  9. package/packages/builtin-tool-gtd/src/client/Intervention/AddTodo.tsx +1 -1
  10. package/packages/builtin-tool-gtd/src/client/Render/TodoList/index.tsx +39 -10
  11. package/packages/builtin-tool-gtd/src/client/Render/index.ts +0 -2
  12. package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/TodoItemRow.tsx +26 -12
  13. package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/store/actions.ts +5 -5
  14. package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/store/store.test.ts +14 -8
  15. package/packages/builtin-tool-gtd/src/executor/index.test.ts +48 -227
  16. package/packages/builtin-tool-gtd/src/executor/index.ts +15 -158
  17. package/packages/builtin-tool-gtd/src/manifest.ts +12 -42
  18. package/packages/builtin-tool-gtd/src/systemRole.ts +14 -8
  19. package/packages/builtin-tool-gtd/src/types.ts +47 -41
  20. package/packages/builtin-tool-memory/package.json +8 -0
  21. package/packages/builtin-tool-memory/src/client/Inspector/AddContextMemory/index.tsx +60 -0
  22. package/packages/builtin-tool-memory/src/client/Inspector/AddExperienceMemory/index.tsx +60 -0
  23. package/packages/builtin-tool-memory/src/client/Inspector/AddIdentityMemory/index.tsx +60 -0
  24. package/packages/builtin-tool-memory/src/client/Inspector/AddPreferenceMemory/index.tsx +60 -0
  25. package/packages/builtin-tool-memory/src/client/Inspector/RemoveIdentityMemory/index.tsx +60 -0
  26. package/packages/builtin-tool-memory/src/client/Inspector/SearchUserMemory/index.tsx +67 -0
  27. package/packages/builtin-tool-memory/src/client/Inspector/UpdateIdentityMemory/index.tsx +60 -0
  28. package/packages/builtin-tool-memory/src/client/Inspector/index.ts +35 -0
  29. package/packages/builtin-tool-memory/src/client/Intervention/AddExperienceMemory/index.tsx +17 -0
  30. package/packages/builtin-tool-memory/src/client/Intervention/index.ts +13 -0
  31. package/packages/builtin-tool-memory/src/client/Render/AddExperienceMemory/index.tsx +17 -0
  32. package/packages/builtin-tool-memory/src/client/Render/SearchUserMemory/index.tsx +217 -0
  33. package/packages/builtin-tool-memory/src/client/Render/index.ts +15 -0
  34. package/packages/builtin-tool-memory/src/client/Streaming/AddExperienceMemory/index.tsx +17 -0
  35. package/packages/builtin-tool-memory/src/client/Streaming/index.ts +18 -0
  36. package/packages/builtin-tool-memory/src/client/components/ExperienceMemoryCard.tsx +231 -0
  37. package/packages/builtin-tool-memory/src/client/components/index.ts +1 -0
  38. package/packages/builtin-tool-memory/src/client/index.ts +27 -0
  39. package/packages/builtin-tool-memory/src/executor/index.ts +9 -1
  40. package/packages/builtin-tool-memory/src/types.ts +61 -0
  41. package/packages/context-engine/src/providers/GTDTodoInjector.ts +15 -7
  42. package/packages/conversation-flow/src/__tests__/fixtures/outputs/assistantGroup/tools-with-branches.json +4 -0
  43. package/packages/conversation-flow/src/transformation/FlatListBuilder.ts +1 -0
  44. package/packages/prompts/src/prompts/gtd/index.test.ts +32 -16
  45. package/packages/prompts/src/prompts/gtd/index.ts +9 -5
  46. package/packages/types/package.json +1 -1
  47. package/packages/types/src/discover/assistants.ts +4 -0
  48. package/packages/types/src/discover/groupAgents.ts +196 -0
  49. package/packages/types/src/discover/index.ts +5 -1
  50. package/packages/types/src/stepContext.ts +4 -1
  51. package/src/app/[variants]/(main)/community/(detail)/assistant/features/Details/Versions/index.tsx +2 -2
  52. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/DetailProvider.tsx +19 -0
  53. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Members/index.tsx +137 -0
  54. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Nav.tsx +88 -0
  55. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Overview/index.tsx +213 -0
  56. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Related/index.tsx +85 -0
  57. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/SystemRole/TagList.tsx +20 -0
  58. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/SystemRole/index.tsx +71 -0
  59. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Versions/index.tsx +119 -0
  60. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/index.tsx +51 -0
  61. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Header.tsx +253 -0
  62. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/AddGroupAgent.tsx +222 -0
  63. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/index.tsx +34 -0
  64. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/Summary/index.tsx +42 -0
  65. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/index.tsx +41 -0
  66. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/StatusPage/index.tsx +104 -0
  67. package/src/app/[variants]/(main)/community/(detail)/group_agent/index.tsx +103 -0
  68. package/src/app/[variants]/(main)/community/(detail)/group_agent/loading.tsx +1 -0
  69. package/src/app/[variants]/(main)/community/(detail)/user/features/DetailProvider.tsx +7 -1
  70. package/src/app/[variants]/(main)/community/(detail)/user/features/UserContent.tsx +2 -0
  71. package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupCard.tsx +186 -0
  72. package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupList.tsx +59 -0
  73. package/src/app/[variants]/(main)/community/(detail)/user/index.tsx +3 -1
  74. package/src/app/[variants]/(main)/community/(list)/assistant/features/List/Item.tsx +26 -8
  75. package/src/app/[variants]/(main)/community/(list)/assistant/index.tsx +1 -0
  76. package/src/app/[variants]/(main)/community/features/Search.tsx +1 -1
  77. package/src/app/[variants]/(main)/group/profile/features/GroupProfile/index.tsx +2 -0
  78. package/src/app/[variants]/(main)/group/profile/features/Header/AgentPublishButton/PublishResultModal.tsx +2 -1
  79. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/GroupForkConfirmModal.tsx +60 -0
  80. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/GroupPublishResultModal.tsx +62 -0
  81. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/PublishButton.tsx +122 -0
  82. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/index.tsx +46 -0
  83. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/types.ts +12 -0
  84. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/useMarketGroupPublish.ts +211 -0
  85. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/utils.ts +22 -0
  86. package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +4 -2
  87. package/src/app/[variants]/(main)/resource/library/_layout/Header/LibraryHead.tsx +30 -35
  88. package/src/app/[variants]/(main)/resource/library/_layout/Header/index.tsx +9 -11
  89. package/src/app/[variants]/router/desktopRouter.config.tsx +7 -0
  90. package/src/features/Conversation/Messages/AssistantGroup/Tool/Actions/index.tsx +11 -17
  91. package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/LoadingPlaceholder/index.tsx +13 -3
  92. package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/CustomRender.tsx +43 -0
  93. package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/FallbacktArgumentRender.tsx +59 -0
  94. package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/index.tsx +46 -0
  95. package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/index.tsx +13 -19
  96. package/src/features/Conversation/Messages/AssistantGroup/Tool/index.tsx +17 -17
  97. package/src/features/Conversation/Messages/Tool/Tool/index.tsx +10 -9
  98. package/src/features/Conversation/TodoProgress/index.tsx +56 -23
  99. package/src/features/PluginsUI/Render/MCPType/index.tsx +1 -1
  100. package/src/features/ResourceManager/components/Explorer/Header/index.tsx +57 -4
  101. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +6 -4
  102. package/src/features/ResourceManager/components/Explorer/ListView/index.tsx +16 -5
  103. package/src/features/ResourceManager/components/LibraryHierarchy/styles.ts +5 -4
  104. package/src/hooks/useActiveTabKey.ts +1 -2
  105. package/src/locales/default/plugin.ts +1 -0
  106. package/src/locales/default/setting.ts +12 -0
  107. package/src/server/routers/lambda/market/agentGroup.ts +296 -0
  108. package/src/server/routers/lambda/market/index.ts +134 -4
  109. package/src/server/services/discover/index.ts +123 -7
  110. package/src/services/discover.ts +55 -0
  111. package/src/store/chat/slices/message/selectors/dbMessage.test.ts +11 -11
  112. package/src/store/discover/slices/groupAgent/action.ts +80 -0
  113. package/src/store/discover/store.ts +3 -0
  114. package/src/store/file/slices/resource/action.ts +4 -2
  115. package/src/tools/inspectors.ts +2 -0
  116. package/src/tools/interventions.ts +2 -0
  117. package/src/tools/renders.ts +3 -1
  118. package/src/tools/streamings.ts +2 -0
  119. package/packages/builtin-tool-gtd/src/client/Inspector/CompleteTodos/index.tsx +0 -52
  120. package/packages/builtin-tool-gtd/src/client/Inspector/RemoveTodos/index.tsx +0 -52
  121. package/src/features/Conversation/Messages/AssistantGroup/Tool/Render/CustomRender.tsx +0 -113
  122. package/src/features/Conversation/Messages/Tool/Tool/Render.tsx +0 -47
  123. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/AbortResponse.tsx +0 -0
  124. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Arguments/index.tsx +0 -0
  125. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/ErrorResponse.tsx +0 -0
  126. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/ApprovalActions.tsx +0 -0
  127. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/Fallback.tsx +0 -0
  128. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/KeyValueEditor.tsx +0 -0
  129. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/ModeSelector.tsx +0 -0
  130. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/index.tsx +0 -0
  131. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/PluginSettings.tsx +0 -0
  132. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/RejectedResponse.tsx +0 -0
@@ -17,6 +17,7 @@ import {
17
17
  } from '@/types/discover';
18
18
 
19
19
  import { agentRouter } from './agent';
20
+ import { agentGroupRouter } from './agentGroup';
20
21
  import { oidcRouter } from './oidc';
21
22
  import { socialRouter } from './social';
22
23
  import { userRouter } from './user';
@@ -44,6 +45,9 @@ export const marketRouter = router({
44
45
  // ============================== Agent Management (authenticated) ==============================
45
46
  agent: agentRouter,
46
47
 
48
+ // ============================== Agent Group Management (authenticated) ==============================
49
+ agentGroup: agentGroupRouter,
50
+
47
51
  // ============================== Assistant Market ==============================
48
52
  getAssistantCategories: marketProcedure
49
53
  .input(
@@ -120,6 +124,7 @@ export const marketRouter = router({
120
124
  .object({
121
125
  category: z.string().optional(),
122
126
  connectionType: z.nativeEnum(McpConnectionType).optional(),
127
+ includeAgentGroup: z.boolean().optional(),
123
128
  locale: z.string().optional(),
124
129
  order: z.enum(['asc', 'desc']).optional(),
125
130
  ownerId: z.string().optional(),
@@ -145,6 +150,95 @@ export const marketRouter = router({
145
150
  }
146
151
  }),
147
152
 
153
+ // ============================== Group Agent Market (Discovery) ==============================
154
+ getGroupAgentCategories: marketProcedure
155
+ .input(
156
+ z
157
+ .object({
158
+ locale: z.string().optional(),
159
+ q: z.string().optional(),
160
+ })
161
+ .optional(),
162
+ )
163
+ .query(async ({ input, ctx }) => {
164
+ log('getGroupAgentCategories input: %O', input);
165
+
166
+ try {
167
+ return await ctx.discoverService.getGroupAgentCategories(input);
168
+ } catch (error) {
169
+ log('Error fetching group agent categories: %O', error);
170
+ throw new TRPCError({
171
+ code: 'INTERNAL_SERVER_ERROR',
172
+ message: 'Failed to fetch group agent categories',
173
+ });
174
+ }
175
+ }),
176
+
177
+ getGroupAgentDetail: marketProcedure
178
+ .input(
179
+ z.object({
180
+ identifier: z.string(),
181
+ locale: z.string().optional(),
182
+ version: z.string().optional(),
183
+ }),
184
+ )
185
+ .query(async ({ input, ctx }) => {
186
+ log('getGroupAgentDetail input: %O', input);
187
+
188
+ try {
189
+ return await ctx.discoverService.getGroupAgentDetail(input);
190
+ } catch (error) {
191
+ log('Error fetching group agent detail: %O', error);
192
+ throw new TRPCError({
193
+ code: 'INTERNAL_SERVER_ERROR',
194
+ message: 'Failed to fetch group agent detail',
195
+ });
196
+ }
197
+ }),
198
+
199
+ getGroupAgentIdentifiers: marketProcedure.query(async ({ ctx }) => {
200
+ log('getGroupAgentIdentifiers called');
201
+
202
+ try {
203
+ return await ctx.discoverService.getGroupAgentIdentifiers();
204
+ } catch (error) {
205
+ log('Error fetching group agent identifiers: %O', error);
206
+ throw new TRPCError({
207
+ code: 'INTERNAL_SERVER_ERROR',
208
+ message: 'Failed to fetch group agent identifiers',
209
+ });
210
+ }
211
+ }),
212
+
213
+ getGroupAgentList: marketProcedure
214
+ .input(
215
+ z
216
+ .object({
217
+ category: z.string().optional(),
218
+ locale: z.string().optional(),
219
+ order: z.enum(['asc', 'desc']).optional(),
220
+ ownerId: z.string().optional(),
221
+ page: z.number().optional(),
222
+ pageSize: z.number().optional(),
223
+ q: z.string().optional(),
224
+ sort: z.enum(['createdAt', 'updatedAt', 'name', 'recommended']).optional(),
225
+ })
226
+ .optional(),
227
+ )
228
+ .query(async ({ input, ctx }) => {
229
+ log('getGroupAgentList input: %O', input);
230
+
231
+ try {
232
+ return await ctx.discoverService.getGroupAgentList(input);
233
+ } catch (error) {
234
+ log('Error fetching group agent list: %O', error);
235
+ throw new TRPCError({
236
+ code: 'INTERNAL_SERVER_ERROR',
237
+ message: 'Failed to fetch group agent list',
238
+ });
239
+ }
240
+ }),
241
+
148
242
  getLegacyPluginList: marketProcedure
149
243
  .input(
150
244
  z
@@ -167,7 +261,7 @@ export const marketRouter = router({
167
261
  }),
168
262
 
169
263
  // ============================== MCP Market ==============================
170
- getMcpCategories: marketProcedure
264
+ getMcpCategories: marketProcedure
171
265
  .input(
172
266
  z
173
267
  .object({
@@ -351,7 +445,7 @@ getMcpCategories: marketProcedure
351
445
  }),
352
446
 
353
447
  // ============================== Plugin Market ==============================
354
- getPluginCategories: marketProcedure
448
+ getPluginCategories: marketProcedure
355
449
  .input(
356
450
  z
357
451
  .object({
@@ -439,7 +533,7 @@ getPluginCategories: marketProcedure
439
533
  }),
440
534
 
441
535
  // ============================== Providers ==============================
442
- getProviderDetail: marketProcedure
536
+ getProviderDetail: marketProcedure
443
537
  .input(
444
538
  z.object({
445
539
  identifier: z.string(),
@@ -503,7 +597,7 @@ getProviderDetail: marketProcedure
503
597
  }),
504
598
 
505
599
  // ============================== User Profile ==============================
506
- getUserInfo: marketProcedure
600
+ getUserInfo: marketProcedure
507
601
  .input(
508
602
  z.object({
509
603
  locale: z.string().optional(),
@@ -675,6 +769,42 @@ getUserInfo: marketProcedure
675
769
  }
676
770
  }),
677
771
 
772
+ reportGroupAgentEvent: marketProcedure
773
+ .input(
774
+ z.object({
775
+ event: z.enum(['add', 'chat', 'click']),
776
+ identifier: z.string(),
777
+ source: z.string().optional(),
778
+ }),
779
+ )
780
+ .mutation(async ({ input, ctx }) => {
781
+ log('reportGroupAgentEvent input: %O', input);
782
+
783
+ try {
784
+ await ctx.discoverService.createGroupAgentEvent(input);
785
+ return { success: true };
786
+ } catch (error) {
787
+ console.error('Error reporting Group Agent event: %O', error);
788
+ return { success: false };
789
+ }
790
+ }),
791
+
792
+ reportGroupAgentInstall: marketProcedure
793
+ .input(
794
+ z.object({
795
+ identifier: z.string(),
796
+ }),
797
+ )
798
+ .mutation(async ({ input, ctx }) => {
799
+ log('reportGroupAgentInstall input: %O', input);
800
+ try {
801
+ await ctx.discoverService.increaseGroupAgentInstallCount(input.identifier);
802
+ return { success: true };
803
+ } catch (error) {
804
+ log('Error reporting group agent installation: %O', error);
805
+ return { success: false };
806
+ }
807
+ }),
678
808
 
679
809
  reportMcpEvent: marketProcedure
680
810
  .input(
@@ -33,7 +33,7 @@ import {
33
33
  type ModelQueryParams,
34
34
  ModelSorts,
35
35
  type PluginListResponse,
36
- type PluginQueryParams as PluginQueryParams,
36
+ type PluginQueryParams,
37
37
  PluginSorts,
38
38
  type ProviderListResponse,
39
39
  type ProviderQueryParams,
@@ -718,6 +718,7 @@ export class DiscoverService {
718
718
  q,
719
719
  sort = AssistantSorts.CreatedAt,
720
720
  ownerId,
721
+ includeAgentGroup,
721
722
  } = rest;
722
723
 
723
724
  try {
@@ -740,9 +741,10 @@ export class DiscoverService {
740
741
  }
741
742
  }
742
743
 
743
- // @ts-ignore
744
744
  const data = await this.market.agents.getAgentList({
745
745
  category,
746
+ // includeAgentGroup may not be in SDK type definition yet, using 'as any'
747
+ includeAgentGroup,
746
748
  locale: normalizedLocale,
747
749
  order,
748
750
  ownerId,
@@ -752,7 +754,7 @@ export class DiscoverService {
752
754
  sort: apiSort,
753
755
  status: 'published',
754
756
  visibility: 'public',
755
- });
757
+ } as any);
756
758
 
757
759
  const transformedItems: DiscoverAssistantItem[] = (data.items || []).map((item: any) => {
758
760
  const normalizedAuthor = this.normalizeAuthorField(item.author);
@@ -773,6 +775,7 @@ export class DiscoverService {
773
775
  tags: item.tags || [],
774
776
  title: item.name || item.identifier,
775
777
  tokenUsage: item.tokenUsage || 0,
778
+ type: item.type,
776
779
  userName: normalizedAuthor.userName,
777
780
  };
778
781
  });
@@ -922,7 +925,6 @@ export class DiscoverService {
922
925
  await this.market.plugins.createEvent(params);
923
926
  };
924
927
 
925
-
926
928
  /**
927
929
  * report plugin call result to marketplace
928
930
  */
@@ -1735,14 +1737,18 @@ export class DiscoverService {
1735
1737
 
1736
1738
  try {
1737
1739
  // Call Market SDK to get user info
1738
- const response: UserInfoResponse = await this.market.user.getUserInfo(username, { locale });
1740
+ const response = (await this.market.user.getUserInfo(username, {
1741
+ locale,
1742
+ })) as UserInfoResponse & {
1743
+ agentGroups?: any[];
1744
+ };
1739
1745
 
1740
1746
  if (!response?.user) {
1741
1747
  log('getUserInfo: user not found for username=%s', username);
1742
1748
  return undefined;
1743
1749
  }
1744
1750
 
1745
- const { user, agents } = response;
1751
+ const { user, agents, agentGroups } = response;
1746
1752
 
1747
1753
  // Transform agents to DiscoverAssistantItem format
1748
1754
  const transformedAgents: DiscoverAssistantItem[] = (agents || []).map((agent: any) => ({
@@ -1763,7 +1769,27 @@ export class DiscoverService {
1763
1769
  tokenUsage: agent.tokenUsage || 0,
1764
1770
  }));
1765
1771
 
1772
+ // Transform agentGroups to DiscoverGroupAgentItem format
1773
+ const transformedAgentGroups = (agentGroups || []).map((group: any) => ({
1774
+ author: user.displayName || user.userName || user.namespace || '',
1775
+ avatar: group.avatar || '👥',
1776
+ category: group.category as any,
1777
+ createdAt: group.createdAt,
1778
+ description: group.description || '',
1779
+ homepage: `https://lobehub.com/discover/group_agent/${group.identifier}`,
1780
+ identifier: group.identifier,
1781
+ installCount: group.installCount || 0,
1782
+ isFeatured: group.isFeatured || false,
1783
+ isOfficial: group.isOfficial || false,
1784
+ memberCount: 0, // Will be populated from memberAgents in detail view
1785
+ schemaVersion: 1,
1786
+ tags: group.tags || [],
1787
+ title: group.name || group.identifier,
1788
+ updatedAt: group.updatedAt,
1789
+ }));
1790
+
1766
1791
  const result: DiscoverUserProfile = {
1792
+ agentGroups: transformedAgentGroups,
1767
1793
  agents: transformedAgents,
1768
1794
  user: {
1769
1795
  avatarUrl: user.avatarUrl || null,
@@ -1781,11 +1807,101 @@ export class DiscoverService {
1781
1807
  },
1782
1808
  };
1783
1809
 
1784
- log('getUserInfo: returning user profile with %d agents', result.agents.length);
1810
+ log(
1811
+ 'getUserInfo: returning user profile with %d agents and %d groups',
1812
+ result.agents.length,
1813
+ result.agentGroups?.length || 0,
1814
+ );
1785
1815
  return result;
1786
1816
  } catch (error) {
1787
1817
  log('getUserInfo: error fetching user info: %O', error);
1788
1818
  return undefined;
1789
1819
  }
1790
1820
  };
1821
+
1822
+ // ============================== Group Agent Market Methods ==============================
1823
+
1824
+ getGroupAgentCategories = async (params?: CategoryListQuery) => {
1825
+ try {
1826
+ // TODO: SDK method not yet available, using fallback
1827
+ const response = await (this.market.agentGroups as any).getAgentGroupCategories?.(params);
1828
+ return response || { items: [] };
1829
+ } catch (error) {
1830
+ log('getGroupAgentCategories: error: %O', error);
1831
+ return { items: [] };
1832
+ }
1833
+ };
1834
+
1835
+ getGroupAgentDetail = async (params: {
1836
+ identifier: string;
1837
+ locale?: string;
1838
+ version?: string;
1839
+ }) => {
1840
+ try {
1841
+ const response = await this.market.agentGroups.getAgentGroupDetail(params.identifier, {
1842
+ locale: params.locale,
1843
+ version: params.version ? Number(params.version) : undefined,
1844
+ });
1845
+ return response;
1846
+ } catch (error) {
1847
+ log('getGroupAgentDetail: error: %O', error);
1848
+ throw error;
1849
+ }
1850
+ };
1851
+
1852
+ getGroupAgentIdentifiers = async () => {
1853
+ try {
1854
+ // TODO: SDK method not yet available, using fallback
1855
+ const response = await (this.market.agentGroups as any).getAgentGroupIdentifiers?.();
1856
+ return response || { identifiers: [] };
1857
+ } catch (error) {
1858
+ log('getGroupAgentIdentifiers: error: %O', error);
1859
+ return { identifiers: [] };
1860
+ }
1861
+ };
1862
+
1863
+ getGroupAgentList = async (params?: {
1864
+ category?: string;
1865
+ locale?: string;
1866
+ order?: 'asc' | 'desc';
1867
+ ownerId?: string;
1868
+ page?: number;
1869
+ pageSize?: number;
1870
+ q?: string;
1871
+ sort?: 'createdAt' | 'updatedAt' | 'name' | 'recommended';
1872
+ }) => {
1873
+ try {
1874
+ const response = await this.market.agentGroups.getAgentGroupList({
1875
+ ...params,
1876
+ status: 'published' as any,
1877
+ visibility: 'public' as any,
1878
+ });
1879
+ return response;
1880
+ } catch (error) {
1881
+ log('getGroupAgentList: error: %O', error);
1882
+ return { currentPage: 1, items: [], totalCount: 0, totalPages: 1 };
1883
+ }
1884
+ };
1885
+
1886
+ createGroupAgentEvent = async (params: {
1887
+ event: 'add' | 'chat' | 'click';
1888
+ identifier: string;
1889
+ source?: string;
1890
+ }) => {
1891
+ try {
1892
+ // TODO: SDK method not yet available
1893
+ await (this.market.agentGroups as any).createAgentGroupEvent?.(params);
1894
+ } catch (error) {
1895
+ log('createGroupAgentEvent: error: %O', error);
1896
+ }
1897
+ };
1898
+
1899
+ increaseGroupAgentInstallCount = async (identifier: string) => {
1900
+ try {
1901
+ // TODO: SDK method not yet available
1902
+ await (this.market.agentGroups as any).increaseInstallCount?.(identifier);
1903
+ } catch (error) {
1904
+ log('increaseGroupAgentInstallCount: error: %O', error);
1905
+ }
1906
+ };
1791
1907
  }
@@ -20,6 +20,7 @@ import {
20
20
  type DiscoverPluginDetail,
21
21
  type DiscoverProviderDetail,
22
22
  type DiscoverUserProfile,
23
+ type GroupAgentQueryParams,
23
24
  type IdentifiersResponse,
24
25
  type McpListResponse,
25
26
  type McpQueryParams,
@@ -448,6 +449,60 @@ class DiscoverService {
448
449
  }
449
450
  return null;
450
451
  }
452
+
453
+ // ============================== Group Agent Market ==============================
454
+
455
+ getGroupAgentCategories = async (params: CategoryListQuery = {}): Promise<CategoryItem[]> => {
456
+ const locale = globalHelpers.getCurrentLanguage();
457
+ return lambdaClient.market.getGroupAgentCategories.query({
458
+ ...params,
459
+ locale,
460
+ });
461
+ };
462
+
463
+ getGroupAgentDetail = async (params: {
464
+ identifier: string;
465
+ locale?: string;
466
+ version?: string;
467
+ }): Promise<any> => {
468
+ const locale = globalHelpers.getCurrentLanguage();
469
+ return lambdaClient.market.getGroupAgentDetail.query({
470
+ identifier: params.identifier,
471
+ locale,
472
+ version: params.version,
473
+ });
474
+ };
475
+
476
+ getGroupAgentIdentifiers = async (): Promise<IdentifiersResponse> => {
477
+ return lambdaClient.market.getGroupAgentIdentifiers.query();
478
+ };
479
+
480
+ getGroupAgentList = async (
481
+ params: GroupAgentQueryParams = {},
482
+ ): Promise<any> => {
483
+ const locale = globalHelpers.getCurrentLanguage();
484
+ return lambdaClient.market.getGroupAgentList.query(
485
+ {
486
+ ...params,
487
+ locale,
488
+ page: params.page ? Number(params.page) : 1,
489
+ pageSize: params.pageSize ? Number(params.pageSize) : 20,
490
+ },
491
+ { context: { showNotification: false } },
492
+ );
493
+ };
494
+
495
+ reportGroupAgentEvent = async (params: {
496
+ event: 'add' | 'chat' | 'click';
497
+ identifier: string;
498
+ source?: string;
499
+ }): Promise<void> => {
500
+ await lambdaClient.market.reportGroupAgentEvent.mutate(params);
501
+ };
502
+
503
+ reportGroupAgentInstall = async (identifier: string): Promise<void> => {
504
+ await lambdaClient.market.reportGroupAgentInstall.mutate({ identifier });
505
+ };
451
506
  }
452
507
 
453
508
  export const discoverService = new DiscoverService();
@@ -5,7 +5,7 @@ import { selectTodosFromMessages } from './dbMessage';
5
5
 
6
6
  describe('selectTodosFromMessages', () => {
7
7
  const createGTDToolMessage = (todos: {
8
- items: Array<{ text: string; completed: boolean }>;
8
+ items: Array<{ text: string; status: 'todo' | 'processing' | 'completed' }>;
9
9
  updatedAt: string;
10
10
  }): UIChatMessage =>
11
11
  ({
@@ -30,7 +30,7 @@ describe('selectTodosFromMessages', () => {
30
30
  content: 'Create a todo list',
31
31
  } as UIChatMessage,
32
32
  createGTDToolMessage({
33
- items: [{ text: 'Buy milk', completed: false }],
33
+ items: [{ text: 'Buy milk', status: 'todo' }],
34
34
  updatedAt: '2024-06-01T00:00:00.000Z',
35
35
  }),
36
36
  ];
@@ -40,13 +40,13 @@ describe('selectTodosFromMessages', () => {
40
40
  expect(result).toBeDefined();
41
41
  expect(result?.items).toHaveLength(1);
42
42
  expect(result?.items[0].text).toBe('Buy milk');
43
- expect(result?.items[0].completed).toBe(false);
43
+ expect(result?.items[0].status).toBe('todo');
44
44
  });
45
45
 
46
46
  it('should return the most recent todos when multiple GTD messages exist', () => {
47
47
  const messages: UIChatMessage[] = [
48
48
  createGTDToolMessage({
49
- items: [{ text: 'Old task', completed: false }],
49
+ items: [{ text: 'Old task', status: 'todo' }],
50
50
  updatedAt: '2024-01-01T00:00:00.000Z',
51
51
  }),
52
52
  {
@@ -56,8 +56,8 @@ describe('selectTodosFromMessages', () => {
56
56
  } as UIChatMessage,
57
57
  createGTDToolMessage({
58
58
  items: [
59
- { text: 'Old task', completed: true },
60
- { text: 'New task', completed: false },
59
+ { text: 'Old task', status: 'completed' },
60
+ { text: 'New task', status: 'todo' },
61
61
  ],
62
62
  updatedAt: '2024-06-01T00:00:00.000Z',
63
63
  }),
@@ -69,7 +69,7 @@ describe('selectTodosFromMessages', () => {
69
69
  expect(result?.items).toHaveLength(2);
70
70
  // Should be from the latest message
71
71
  expect(result?.items[0].text).toBe('Old task');
72
- expect(result?.items[0].completed).toBe(true);
72
+ expect(result?.items[0].status).toBe('completed');
73
73
  expect(result?.items[1].text).toBe('New task');
74
74
  });
75
75
 
@@ -155,7 +155,7 @@ describe('selectTodosFromMessages', () => {
155
155
  },
156
156
  pluginState: {
157
157
  todos: {
158
- items: [{ text: 'Task', completed: false }],
158
+ items: [{ text: 'Task', status: 'todo' }],
159
159
  // No updatedAt
160
160
  },
161
161
  },
@@ -184,8 +184,8 @@ describe('selectTodosFromMessages', () => {
184
184
  pluginState: {
185
185
  // Legacy format: direct array
186
186
  todos: [
187
- { text: 'Task 1', completed: false },
188
- { text: 'Task 2', completed: true },
187
+ { text: 'Task 1', status: 'todo' },
188
+ { text: 'Task 2', status: 'completed' },
189
189
  ],
190
190
  },
191
191
  } as unknown as UIChatMessage,
@@ -196,6 +196,6 @@ describe('selectTodosFromMessages', () => {
196
196
  expect(result).toBeDefined();
197
197
  expect(result?.items).toHaveLength(2);
198
198
  expect(result?.items[0].text).toBe('Task 1');
199
- expect(result?.items[1].completed).toBe(true);
199
+ expect(result?.items[1].status).toBe('completed');
200
200
  });
201
201
  });
@@ -0,0 +1,80 @@
1
+ import { type CategoryItem, type CategoryListQuery } from '@lobehub/market-sdk';
2
+ import useSWR, { type SWRResponse } from 'swr';
3
+ import type { StateCreator } from 'zustand/vanilla';
4
+
5
+ import { discoverService } from '@/services/discover';
6
+ import { type DiscoverStore } from '@/store/discover';
7
+ import { globalHelpers } from '@/store/global/helpers';
8
+ import {
9
+ type DiscoverGroupAgentDetail,
10
+ type GroupAgentListResponse,
11
+ type GroupAgentQueryParams,
12
+ type IdentifiersResponse,
13
+ } from '@/types/discover';
14
+
15
+ export interface GroupAgentAction {
16
+ useGroupAgentCategories: (params?: CategoryListQuery) => SWRResponse<CategoryItem[]>;
17
+ useGroupAgentDetail: (params: {
18
+ identifier: string;
19
+ version?: string;
20
+ }) => SWRResponse<DiscoverGroupAgentDetail | undefined>;
21
+ useGroupAgentIdentifiers: () => SWRResponse<IdentifiersResponse>;
22
+ useGroupAgentList: (params?: GroupAgentQueryParams) => SWRResponse<GroupAgentListResponse>;
23
+ }
24
+
25
+ export const createGroupAgentSlice: StateCreator<
26
+ DiscoverStore,
27
+ [['zustand/devtools', never]],
28
+ [],
29
+ GroupAgentAction
30
+ > = () => ({
31
+ useGroupAgentCategories: (params = {}) => {
32
+ const locale = globalHelpers.getCurrentLanguage();
33
+ return useSWR(
34
+ ['group-agent-categories', locale, ...Object.values(params)].filter(Boolean).join('-'),
35
+ async () => discoverService.getGroupAgentCategories(params),
36
+ {
37
+ revalidateOnFocus: false,
38
+ },
39
+ );
40
+ },
41
+
42
+ useGroupAgentDetail: (params) => {
43
+ const locale = globalHelpers.getCurrentLanguage();
44
+ return useSWR(
45
+ ['group-agent-details', locale, params.identifier, params.version]
46
+ .filter(Boolean)
47
+ .join('-'),
48
+ async () => discoverService.getGroupAgentDetail(params),
49
+ {
50
+ revalidateOnFocus: false,
51
+ },
52
+ );
53
+ },
54
+
55
+ useGroupAgentIdentifiers: () => {
56
+ return useSWR(
57
+ 'group-agent-identifiers',
58
+ async () => discoverService.getGroupAgentIdentifiers(),
59
+ {
60
+ revalidateOnFocus: false,
61
+ },
62
+ );
63
+ },
64
+
65
+ useGroupAgentList: (params = {}) => {
66
+ const locale = globalHelpers.getCurrentLanguage();
67
+ return useSWR(
68
+ ['group-agent-list', locale, ...Object.values(params)].filter(Boolean).join('-'),
69
+ async () =>
70
+ discoverService.getGroupAgentList({
71
+ ...params,
72
+ page: params.page ? Number(params.page) : 1,
73
+ pageSize: params.pageSize ? Number(params.pageSize) : 20,
74
+ }),
75
+ {
76
+ revalidateOnFocus: false,
77
+ },
78
+ );
79
+ },
80
+ });
@@ -4,6 +4,7 @@ import { type StateCreator } from 'zustand/vanilla';
4
4
 
5
5
  import { createDevtools } from '../middleware/createDevtools';
6
6
  import { type AssistantAction, createAssistantSlice } from './slices/assistant/action';
7
+ import { type GroupAgentAction, createGroupAgentSlice } from './slices/groupAgent/action';
7
8
  import { type MCPAction, createMCPSlice } from './slices/mcp';
8
9
  import { type ModelAction, createModelSlice } from './slices/model/action';
9
10
  import { type PluginAction, createPluginSlice } from './slices/plugin/action';
@@ -15,6 +16,7 @@ import { type UserAction, createUserSlice } from './slices/user';
15
16
 
16
17
  export type DiscoverStore = MCPAction &
17
18
  AssistantAction &
19
+ GroupAgentAction &
18
20
  ProviderAction &
19
21
  ModelAction &
20
22
  PluginAction &
@@ -26,6 +28,7 @@ const createStore: StateCreator<DiscoverStore, [['zustand/devtools', never]]> =
26
28
  ) => ({
27
29
  ...createMCPSlice(...parameters),
28
30
  ...createAssistantSlice(...parameters),
31
+ ...createGroupAgentSlice(...parameters),
29
32
  ...createProviderSlice(...parameters),
30
33
  ...createModelSlice(...parameters),
31
34
  ...createPluginSlice(...parameters),
@@ -239,9 +239,11 @@ export const createResourceSlice: StateCreator<
239
239
  'deleteResource/optimistic',
240
240
  );
241
241
 
242
- // 2. Enqueue sync (background)
242
+ // 2. Enqueue sync and await completion.
243
+ // Important: if callers revalidate the list immediately, doing so before the server-side
244
+ // deletion finishes can re-introduce the item from a still-stale query response.
243
245
  const syncEngine = getSyncEngine();
244
- syncEngine.enqueue({
246
+ await syncEngine.enqueue({
245
247
  id: `sync-${id}-${Date.now()}`,
246
248
  payload: {},
247
249
  resourceId: id,
@@ -23,6 +23,7 @@ import {
23
23
  LocalSystemInspectors,
24
24
  LocalSystemManifest,
25
25
  } from '@lobechat/builtin-tool-local-system/client';
26
+ import { MemoryInspectors, MemoryManifest } from '@lobechat/builtin-tool-memory/client';
26
27
  import { NotebookInspectors, NotebookManifest } from '@lobechat/builtin-tool-notebook/client';
27
28
  import { PageAgentInspectors, PageAgentManifest } from '@lobechat/builtin-tool-page-agent/client';
28
29
  import {
@@ -52,6 +53,7 @@ const BuiltinToolInspectors: Record<string, Record<string, BuiltinInspector>> =
52
53
  [GTDManifest.identifier]: GTDInspectors as Record<string, BuiltinInspector>,
53
54
  [KnowledgeBaseManifest.identifier]: KnowledgeBaseInspectors as Record<string, BuiltinInspector>,
54
55
  [LocalSystemManifest.identifier]: LocalSystemInspectors as Record<string, BuiltinInspector>,
56
+ [MemoryManifest.identifier]: MemoryInspectors as Record<string, BuiltinInspector>,
55
57
  [NotebookManifest.identifier]: NotebookInspectors as Record<string, BuiltinInspector>,
56
58
  [PageAgentManifest.identifier]: PageAgentInspectors as Record<string, BuiltinInspector>,
57
59
  [WebBrowsingManifest.identifier]: WebBrowsingInspectors as Record<string, BuiltinInspector>,