@lobehub/lobehub 2.0.0-next.306 → 2.0.0-next.308

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 (254) hide show
  1. package/.vscode/settings.json +18 -3
  2. package/CHANGELOG.md +61 -0
  3. package/changelog/v1.json +21 -0
  4. package/locales/ar/agentGroup.json +5 -0
  5. package/locales/ar/chat.json +26 -0
  6. package/locales/ar/models.json +43 -5
  7. package/locales/ar/plugin.json +4 -5
  8. package/locales/ar/setting.json +11 -0
  9. package/locales/ar/subscription.json +2 -0
  10. package/locales/ar/tool.json +2 -0
  11. package/locales/bg-BG/agentGroup.json +5 -0
  12. package/locales/bg-BG/chat.json +26 -0
  13. package/locales/bg-BG/models.json +49 -3
  14. package/locales/bg-BG/plugin.json +4 -5
  15. package/locales/bg-BG/setting.json +11 -0
  16. package/locales/bg-BG/subscription.json +2 -0
  17. package/locales/bg-BG/tool.json +2 -0
  18. package/locales/de-DE/agentGroup.json +5 -0
  19. package/locales/de-DE/chat.json +26 -0
  20. package/locales/de-DE/models.json +48 -5
  21. package/locales/de-DE/plugin.json +4 -5
  22. package/locales/de-DE/setting.json +11 -0
  23. package/locales/de-DE/subscription.json +2 -0
  24. package/locales/de-DE/tool.json +2 -0
  25. package/locales/en-US/models.json +8 -6
  26. package/locales/en-US/plugin.json +2 -4
  27. package/locales/en-US/setting.json +10 -11
  28. package/locales/en-US/tool.json +2 -0
  29. package/locales/es-ES/agentGroup.json +5 -0
  30. package/locales/es-ES/chat.json +26 -0
  31. package/locales/es-ES/models.json +43 -5
  32. package/locales/es-ES/plugin.json +4 -5
  33. package/locales/es-ES/setting.json +11 -0
  34. package/locales/es-ES/subscription.json +2 -0
  35. package/locales/es-ES/tool.json +2 -0
  36. package/locales/fa-IR/agentGroup.json +5 -0
  37. package/locales/fa-IR/chat.json +26 -0
  38. package/locales/fa-IR/models.json +42 -5
  39. package/locales/fa-IR/plugin.json +4 -5
  40. package/locales/fa-IR/setting.json +11 -0
  41. package/locales/fa-IR/subscription.json +2 -0
  42. package/locales/fa-IR/tool.json +2 -0
  43. package/locales/fr-FR/agentGroup.json +5 -0
  44. package/locales/fr-FR/chat.json +26 -0
  45. package/locales/fr-FR/models.json +5 -5
  46. package/locales/fr-FR/plugin.json +4 -5
  47. package/locales/fr-FR/setting.json +11 -0
  48. package/locales/fr-FR/subscription.json +2 -0
  49. package/locales/fr-FR/tool.json +2 -0
  50. package/locales/it-IT/agentGroup.json +5 -0
  51. package/locales/it-IT/chat.json +26 -0
  52. package/locales/it-IT/models.json +1 -3
  53. package/locales/it-IT/plugin.json +4 -5
  54. package/locales/it-IT/setting.json +11 -0
  55. package/locales/it-IT/subscription.json +2 -0
  56. package/locales/it-IT/tool.json +2 -0
  57. package/locales/ja-JP/agentGroup.json +5 -0
  58. package/locales/ja-JP/chat.json +26 -0
  59. package/locales/ja-JP/models.json +1 -5
  60. package/locales/ja-JP/plugin.json +4 -5
  61. package/locales/ja-JP/setting.json +11 -0
  62. package/locales/ja-JP/subscription.json +2 -0
  63. package/locales/ja-JP/tool.json +2 -0
  64. package/locales/ko-KR/agentGroup.json +5 -0
  65. package/locales/ko-KR/chat.json +26 -0
  66. package/locales/ko-KR/models.json +1 -3
  67. package/locales/ko-KR/plugin.json +4 -5
  68. package/locales/ko-KR/setting.json +11 -0
  69. package/locales/ko-KR/subscription.json +2 -0
  70. package/locales/ko-KR/tool.json +2 -0
  71. package/locales/nl-NL/agentGroup.json +5 -0
  72. package/locales/nl-NL/chat.json +26 -0
  73. package/locales/nl-NL/models.json +35 -3
  74. package/locales/nl-NL/plugin.json +4 -5
  75. package/locales/nl-NL/setting.json +11 -0
  76. package/locales/nl-NL/subscription.json +2 -0
  77. package/locales/nl-NL/tool.json +2 -0
  78. package/locales/pl-PL/agentGroup.json +5 -0
  79. package/locales/pl-PL/chat.json +26 -0
  80. package/locales/pl-PL/models.json +1 -3
  81. package/locales/pl-PL/plugin.json +4 -5
  82. package/locales/pl-PL/setting.json +11 -0
  83. package/locales/pl-PL/subscription.json +2 -0
  84. package/locales/pl-PL/tool.json +2 -0
  85. package/locales/pt-BR/agentGroup.json +5 -0
  86. package/locales/pt-BR/chat.json +26 -0
  87. package/locales/pt-BR/models.json +50 -5
  88. package/locales/pt-BR/plugin.json +4 -5
  89. package/locales/pt-BR/setting.json +11 -0
  90. package/locales/pt-BR/subscription.json +2 -0
  91. package/locales/pt-BR/tool.json +2 -0
  92. package/locales/ru-RU/agentGroup.json +5 -0
  93. package/locales/ru-RU/chat.json +26 -0
  94. package/locales/ru-RU/models.json +22 -3
  95. package/locales/ru-RU/plugin.json +4 -5
  96. package/locales/ru-RU/setting.json +11 -0
  97. package/locales/ru-RU/subscription.json +2 -0
  98. package/locales/ru-RU/tool.json +2 -0
  99. package/locales/tr-TR/agentGroup.json +5 -0
  100. package/locales/tr-TR/chat.json +26 -0
  101. package/locales/tr-TR/models.json +36 -3
  102. package/locales/tr-TR/plugin.json +4 -5
  103. package/locales/tr-TR/setting.json +11 -0
  104. package/locales/tr-TR/subscription.json +2 -0
  105. package/locales/tr-TR/tool.json +2 -0
  106. package/locales/vi-VN/agentGroup.json +5 -0
  107. package/locales/vi-VN/chat.json +26 -0
  108. package/locales/vi-VN/models.json +1 -1
  109. package/locales/vi-VN/plugin.json +4 -5
  110. package/locales/vi-VN/setting.json +11 -0
  111. package/locales/vi-VN/subscription.json +2 -0
  112. package/locales/vi-VN/tool.json +2 -0
  113. package/locales/zh-CN/models.json +52 -5
  114. package/locales/zh-CN/plugin.json +5 -7
  115. package/locales/zh-CN/setting.json +10 -11
  116. package/locales/zh-CN/tool.json +2 -2
  117. package/locales/zh-TW/agentGroup.json +5 -0
  118. package/locales/zh-TW/chat.json +26 -0
  119. package/locales/zh-TW/models.json +54 -5
  120. package/locales/zh-TW/plugin.json +4 -5
  121. package/locales/zh-TW/setting.json +11 -0
  122. package/locales/zh-TW/subscription.json +2 -0
  123. package/locales/zh-TW/tool.json +2 -0
  124. package/package.json +2 -2
  125. package/packages/builtin-agents/src/agents/group-supervisor/index.ts +1 -7
  126. package/packages/builtin-tool-group-agent-builder/src/ExecutionRuntime/index.ts +29 -0
  127. package/packages/builtin-tool-group-agent-builder/src/executor.ts +18 -0
  128. package/packages/builtin-tool-group-agent-builder/src/manifest.ts +17 -0
  129. package/packages/builtin-tool-group-agent-builder/src/types.ts +10 -0
  130. package/packages/builtin-tool-group-management/src/client/Inspector/ExecuteAgentTask/index.tsx +52 -8
  131. package/packages/builtin-tool-group-management/src/client/Render/ExecuteTask/index.tsx +2 -21
  132. package/packages/builtin-tool-group-management/src/executor.test.ts +6 -16
  133. package/packages/builtin-tool-group-management/src/executor.ts +8 -47
  134. package/packages/builtin-tool-group-management/src/manifest.ts +5 -18
  135. package/packages/builtin-tool-group-management/src/systemRole.ts +1 -8
  136. package/packages/builtin-tool-group-management/src/types.ts +2 -10
  137. package/packages/builtin-tool-local-system/src/ExecutionRuntime/index.ts +70 -31
  138. package/packages/builtin-tool-local-system/src/client/Render/WriteFile/index.tsx +48 -5
  139. package/packages/builtin-tool-local-system/src/client/Streaming/WriteFile/index.tsx +39 -0
  140. package/packages/builtin-tool-local-system/src/client/Streaming/index.ts +2 -0
  141. package/packages/builtin-tool-local-system/src/executor/index.ts +94 -60
  142. package/packages/database/src/repositories/agentGroup/index.ts +23 -0
  143. package/packages/model-bank/src/aiModels/qiniu.ts +24 -0
  144. package/packages/prompts/src/prompts/fileSystem/formatCommandOutput.test.ts +61 -0
  145. package/packages/prompts/src/prompts/fileSystem/formatCommandOutput.ts +21 -0
  146. package/packages/prompts/src/prompts/fileSystem/formatCommandResult.test.ts +87 -0
  147. package/packages/prompts/src/prompts/fileSystem/formatCommandResult.ts +35 -0
  148. package/packages/prompts/src/prompts/fileSystem/formatEditResult.test.ts +57 -0
  149. package/packages/prompts/src/prompts/fileSystem/formatEditResult.ts +17 -0
  150. package/packages/prompts/src/prompts/fileSystem/formatFileContent.test.ts +59 -0
  151. package/packages/prompts/src/prompts/fileSystem/formatFileContent.ts +14 -0
  152. package/packages/prompts/src/prompts/fileSystem/formatFileList.test.ts +62 -0
  153. package/packages/prompts/src/prompts/fileSystem/formatFileList.ts +13 -0
  154. package/packages/prompts/src/prompts/fileSystem/formatFileSearchResults.test.ts +34 -0
  155. package/packages/prompts/src/prompts/fileSystem/formatFileSearchResults.ts +12 -0
  156. package/packages/prompts/src/prompts/fileSystem/formatGlobResults.test.ts +64 -0
  157. package/packages/prompts/src/prompts/fileSystem/formatGlobResults.ts +23 -0
  158. package/packages/prompts/src/prompts/fileSystem/formatGrepResults.test.ts +85 -0
  159. package/packages/prompts/src/prompts/fileSystem/formatGrepResults.ts +24 -0
  160. package/packages/prompts/src/prompts/fileSystem/formatKillResult.test.ts +30 -0
  161. package/packages/prompts/src/prompts/fileSystem/formatKillResult.ts +9 -0
  162. package/packages/prompts/src/prompts/fileSystem/formatMoveResults.test.ts +37 -0
  163. package/packages/prompts/src/prompts/fileSystem/formatMoveResults.ts +20 -0
  164. package/packages/prompts/src/prompts/fileSystem/formatMultipleFiles.test.ts +54 -0
  165. package/packages/prompts/src/prompts/fileSystem/formatMultipleFiles.ts +9 -0
  166. package/packages/prompts/src/prompts/fileSystem/formatRenameResult.test.ts +35 -0
  167. package/packages/prompts/src/prompts/fileSystem/formatRenameResult.ts +17 -0
  168. package/packages/prompts/src/prompts/fileSystem/formatWriteResult.test.ts +30 -0
  169. package/packages/prompts/src/prompts/fileSystem/formatWriteResult.ts +11 -0
  170. package/packages/prompts/src/prompts/fileSystem/index.ts +13 -0
  171. package/packages/prompts/src/prompts/index.ts +1 -0
  172. package/src/app/[variants]/(auth)/_layout/index.tsx +0 -2
  173. package/src/app/[variants]/(auth)/layout.tsx +0 -2
  174. package/src/app/[variants]/(auth)/login/[[...login]]/page.tsx +1 -3
  175. package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +1 -3
  176. package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/index.tsx +0 -2
  177. package/src/app/[variants]/(main)/_layout/index.tsx +0 -2
  178. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/Actions.tsx +4 -3
  179. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/useDropdownMenu.tsx +12 -2
  180. package/src/app/[variants]/(main)/agent/_layout/index.tsx +0 -2
  181. package/src/app/[variants]/(main)/agent/features/Portal/index.tsx +0 -2
  182. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/AddGroupAgent.tsx +69 -17
  183. package/src/app/[variants]/(main)/community/(list)/_layout/index.tsx +0 -2
  184. package/src/app/[variants]/(main)/community/(list)/assistant/_layout/index.tsx +0 -2
  185. package/src/app/[variants]/(main)/community/(list)/mcp/_layout/index.tsx +0 -2
  186. package/src/app/[variants]/(main)/community/(list)/model/_layout/index.tsx +0 -2
  187. package/src/app/[variants]/(main)/community/_layout/index.tsx +0 -2
  188. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/Actions.tsx +4 -3
  189. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/useDropdownMenu.tsx +12 -2
  190. package/src/app/[variants]/(main)/group/_layout/index.tsx +0 -2
  191. package/src/app/[variants]/(main)/group/features/Conversation/Header/index.tsx +4 -2
  192. package/src/app/[variants]/(main)/group/features/Portal/index.tsx +0 -2
  193. package/src/app/[variants]/(main)/home/_layout/index.tsx +0 -2
  194. package/src/app/[variants]/(main)/home/index.tsx +0 -2
  195. package/src/app/[variants]/(main)/image/_layout/Topics/TopicUrlSync.tsx +0 -2
  196. package/src/app/[variants]/(main)/image/_layout/index.tsx +0 -2
  197. package/src/app/[variants]/(main)/memory/_layout/index.tsx +0 -2
  198. package/src/app/[variants]/(main)/page/_layout/index.tsx +0 -2
  199. package/src/app/[variants]/(main)/resource/(home)/_layout/index.tsx +0 -2
  200. package/src/app/[variants]/(main)/resource/_layout/index.tsx +0 -2
  201. package/src/app/[variants]/(main)/resource/library/_layout/index.tsx +0 -2
  202. package/src/app/[variants]/(main)/resource/library/features/Container.tsx +0 -2
  203. package/src/app/[variants]/(main)/settings/_layout/index.tsx +0 -2
  204. package/src/app/[variants]/(main)/settings/about/index.tsx +0 -2
  205. package/src/app/[variants]/(main)/settings/agent/index.tsx +0 -2
  206. package/src/app/[variants]/(main)/settings/apikey/index.tsx +0 -2
  207. package/src/app/[variants]/(main)/settings/chat-appearance/index.tsx +0 -2
  208. package/src/app/[variants]/(main)/settings/common/index.tsx +0 -2
  209. package/src/app/[variants]/(main)/settings/hotkey/index.tsx +0 -2
  210. package/src/app/[variants]/(main)/settings/image/index.tsx +0 -2
  211. package/src/app/[variants]/(main)/settings/memory/index.tsx +0 -2
  212. package/src/app/[variants]/(main)/settings/provider/(list)/index.tsx +0 -2
  213. package/src/app/[variants]/(main)/settings/proxy/index.tsx +0 -2
  214. package/src/app/[variants]/(main)/settings/security/index.tsx +1 -3
  215. package/src/app/[variants]/(main)/settings/storage/index.tsx +0 -2
  216. package/src/app/[variants]/(main)/settings/tts/index.tsx +0 -2
  217. package/src/app/[variants]/(mobile)/(home)/_layout/index.tsx +0 -2
  218. package/src/app/[variants]/(mobile)/_layout/index.tsx +1 -3
  219. package/src/app/[variants]/(mobile)/chat/_layout/index.tsx +0 -2
  220. package/src/app/[variants]/(mobile)/chat/settings/_layout/index.tsx +0 -2
  221. package/src/app/[variants]/(mobile)/community/(detail)/_layout/index.tsx +0 -2
  222. package/src/app/[variants]/(mobile)/community/(list)/_layout/index.tsx +0 -2
  223. package/src/app/[variants]/(mobile)/community/_layout/index.tsx +0 -2
  224. package/src/app/[variants]/(mobile)/router/MobileClientRouter.tsx +0 -2
  225. package/src/app/[variants]/(mobile)/settings/index.tsx +0 -2
  226. package/src/app/[variants]/onboarding/_layout/index.tsx +0 -2
  227. package/src/app/[variants]/router/DesktopClientRouter.tsx +0 -2
  228. package/src/components/ModelSelect/index.tsx +6 -56
  229. package/src/components/server/MobileNavLayout.tsx +0 -2
  230. package/src/components/server/ServerLayout.tsx +0 -2
  231. package/src/features/ChatInput/ActionBar/Upload/ServerMode.tsx +13 -3
  232. package/src/features/ChatInput/ActionBar/components/ActionDropdown.tsx +26 -3
  233. package/src/features/ModelSwitchPanel/components/Footer.tsx +0 -2
  234. package/src/features/ModelSwitchPanel/components/List/MultipleProvidersModelItem.tsx +0 -1
  235. package/src/features/ModelSwitchPanel/components/List/SingleProviderModelItem.tsx +0 -1
  236. package/src/features/ModelSwitchPanel/components/List/VirtualItemRenderer.tsx +0 -1
  237. package/src/features/ModelSwitchPanel/components/List/index.tsx +15 -13
  238. package/src/features/ModelSwitchPanel/components/PanelContent.tsx +0 -2
  239. package/src/features/ModelSwitchPanel/index.tsx +21 -23
  240. package/src/features/ResourceManager/components/Explorer/MasonryView/index.tsx +0 -2
  241. package/src/features/ResourceManager/components/Header/AddButton.tsx +20 -3
  242. package/src/features/User/UserAvatar.tsx +0 -2
  243. package/src/locales/default/plugin.ts +2 -1
  244. package/src/server/routers/lambda/__tests__/agentGroup.test.ts +1 -0
  245. package/src/server/routers/lambda/agentGroup.ts +22 -0
  246. package/src/services/chat/index.ts +1 -0
  247. package/src/services/chat/mecha/agentConfigResolver.test.ts +62 -45
  248. package/src/services/chat/mecha/agentConfigResolver.ts +29 -27
  249. package/src/services/chatGroup/index.ts +14 -0
  250. package/src/store/chat/agents/GroupOrchestration/__tests__/call-supervisor.test.ts +305 -0
  251. package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +2 -1
  252. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +6 -2
  253. package/src/store/chat/slices/plugin/actions/exector.ts +92 -0
  254. package/src/store/chat/slices/plugin/actions/pluginTypes.ts +82 -177
@@ -1,4 +1,4 @@
1
- import { Popover, TooltipGroup } from '@lobehub/ui';
1
+ import { Popover } from '@lobehub/ui';
2
2
  import { memo, useCallback, useState } from 'react';
3
3
 
4
4
  import { PanelContent } from './components/PanelContent';
@@ -29,28 +29,26 @@ const ModelSwitchPanel = memo<ModelSwitchPanelProps>(
29
29
  );
30
30
 
31
31
  return (
32
- <TooltipGroup>
33
- <Popover
34
- classNames={{
35
- content: styles.container,
36
- }}
37
- content={
38
- <PanelContent
39
- isOpen={isOpen}
40
- model={modelProp}
41
- onModelChange={onModelChange}
42
- onOpenChange={handleOpenChange}
43
- provider={providerProp}
44
- />
45
- }
46
- nativeButton={false}
47
- onOpenChange={handleOpenChange}
48
- open={isOpen}
49
- placement={placement}
50
- >
51
- {children}
52
- </Popover>
53
- </TooltipGroup>
32
+ <Popover
33
+ classNames={{
34
+ content: styles.container,
35
+ }}
36
+ content={
37
+ <PanelContent
38
+ isOpen={isOpen}
39
+ model={modelProp}
40
+ onModelChange={onModelChange}
41
+ onOpenChange={handleOpenChange}
42
+ provider={providerProp}
43
+ />
44
+ }
45
+ nativeButton={false}
46
+ onOpenChange={handleOpenChange}
47
+ open={isOpen}
48
+ placement={placement}
49
+ >
50
+ {children}
51
+ </Popover>
54
52
  );
55
53
  },
56
54
  );
@@ -197,6 +197,4 @@ const MasonryView = memo(function MasonryView() {
197
197
  );
198
198
  });
199
199
 
200
- MasonryView.displayName = 'MasonryView';
201
-
202
200
  export default MasonryView;
@@ -5,7 +5,7 @@ import { Notion } from '@lobehub/icons';
5
5
  import { Button, DropdownMenu, Icon, type MenuProps } from '@lobehub/ui';
6
6
  import { Upload } from 'antd';
7
7
  import { FilePenLine, FileUp, FolderIcon, FolderUp, Link, Plus } from 'lucide-react';
8
- import { useCallback, useMemo } from 'react';
8
+ import { type ChangeEvent, useCallback, useMemo, useState } from 'react';
9
9
  import { useTranslation } from 'react-i18next';
10
10
 
11
11
  import { useResourceManagerStore } from '@/app/[variants]/(main)/resource/features/store';
@@ -23,6 +23,7 @@ const AddButton = () => {
23
23
  const pushDockFileList = useFileStore((s) => s.pushDockFileList);
24
24
  const uploadFolderWithStructure = useFileStore((s) => s.uploadFolderWithStructure);
25
25
  const createResourceAndSync = useFileStore((s) => s.createResourceAndSync);
26
+ const [menuOpen, setMenuOpen] = useState(false);
26
27
 
27
28
  // TODO: Migrate Notion import to use createResource
28
29
  // Keep old functions temporarily for components not yet migrated
@@ -121,6 +122,13 @@ const AddButton = () => {
121
122
  t,
122
123
  uploadFolderWithStructure,
123
124
  });
125
+ const handleFolderUploadWithClose = useCallback(
126
+ (event: ChangeEvent<HTMLInputElement>) => {
127
+ setMenuOpen(false);
128
+ return handleFolderUpload(event);
129
+ },
130
+ [handleFolderUpload],
131
+ );
124
132
 
125
133
  const items = useMemo<MenuProps['items']>(
126
134
  () => [
@@ -144,11 +152,13 @@ const AddButton = () => {
144
152
  type: 'divider',
145
153
  },
146
154
  {
155
+ closeOnClick: false,
147
156
  icon: <Icon icon={FileUp} />,
148
157
  key: 'upload-file',
149
158
  label: (
150
159
  <Upload
151
160
  beforeUpload={async (file) => {
161
+ setMenuOpen(false);
152
162
  await pushDockFileList([file], libraryId, currentFolderId ?? undefined);
153
163
 
154
164
  return false;
@@ -161,6 +171,7 @@ const AddButton = () => {
161
171
  ),
162
172
  },
163
173
  {
174
+ closeOnClick: false,
164
175
  icon: <Icon icon={FolderUp} />,
165
176
  key: 'upload-folder',
166
177
  label: <label htmlFor="folder-upload-input">{t('header.actions.uploadFolder')}</label>,
@@ -211,7 +222,13 @@ const AddButton = () => {
211
222
 
212
223
  return (
213
224
  <>
214
- <DropdownMenu items={items} placement="bottomRight" trigger="both">
225
+ <DropdownMenu
226
+ items={items}
227
+ onOpenChange={setMenuOpen}
228
+ open={menuOpen}
229
+ placement="bottomRight"
230
+ trigger="both"
231
+ >
215
232
  <Button data-no-highlight icon={Plus} type="primary">
216
233
  {t('addLibrary')}
217
234
  </Button>
@@ -233,7 +250,7 @@ const AddButton = () => {
233
250
  <input
234
251
  id="folder-upload-input"
235
252
  multiple
236
- onChange={handleFolderUpload}
253
+ onChange={handleFolderUploadWithClose}
237
254
  style={{ display: 'none' }}
238
255
  type="file"
239
256
  // @ts-expect-error - webkitdirectory is not in the React types
@@ -88,6 +88,4 @@ const UserAvatar = forwardRef<HTMLDivElement, UserAvatarProps>(
88
88
  },
89
89
  );
90
90
 
91
- UserAvatar.displayName = 'UserAvatar';
92
-
93
91
  export default UserAvatar;
@@ -70,7 +70,8 @@ export default {
70
70
  'builtins.lobe-group-management.apiName.summarize': 'Summarize conversation',
71
71
  'builtins.lobe-group-management.apiName.vote': 'Start vote',
72
72
  'builtins.lobe-group-management.inspector.broadcast.title': 'Following Agents speak:',
73
- 'builtins.lobe-group-management.inspector.executeAgentTask.title': 'Assigning task to:',
73
+ 'builtins.lobe-group-management.inspector.executeAgentTask.assignTo': 'Assign',
74
+ 'builtins.lobe-group-management.inspector.executeAgentTask.task': 'task:',
74
75
  'builtins.lobe-group-management.inspector.executeAgentTasks.title': 'Assigning tasks to:',
75
76
  'builtins.lobe-group-management.inspector.speak.title': 'Designated Agent speaks:',
76
77
  'builtins.lobe-group-management.title': 'Group Coordinator',
@@ -171,6 +171,7 @@ describe('agentGroupRouter', () => {
171
171
  config: { ...DEFAULT_CHAT_GROUP_CHAT_CONFIG, allowDM: true },
172
172
  },
173
173
  ['agent-1', 'agent-2'],
174
+ undefined,
174
175
  );
175
176
  expect(result).toEqual({
176
177
  agentIds: ['agent-1', 'agent-2'],
@@ -129,6 +129,19 @@ export const agentGroupRouter = router({
129
129
  })
130
130
  .partial(),
131
131
  ),
132
+ supervisorConfig: z
133
+ .object({
134
+ avatar: z.string().nullish(),
135
+ backgroundColor: z.string().nullish(),
136
+ description: z.string().nullish(),
137
+ model: z.string().nullish(),
138
+ params: z.any().nullish(),
139
+ provider: z.string().nullish(),
140
+ systemRole: z.string().nullish(),
141
+ tags: z.array(z.string()).nullish(),
142
+ title: z.string().nullish(),
143
+ })
144
+ .optional(),
132
145
  }),
133
146
  )
134
147
  .mutation(async ({ input, ctx }) => {
@@ -144,6 +157,14 @@ export const agentGroupRouter = router({
144
157
  const memberAgentIds = createdAgents.map((agent) => agent.id);
145
158
 
146
159
  // 2. Create group with supervisor and member agents
160
+ // Filter out null/undefined values from supervisorConfig
161
+ const supervisorConfig = input.supervisorConfig
162
+ ? Object.fromEntries(
163
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, eqeqeq
164
+ Object.entries(input.supervisorConfig).filter(([_, v]) => v != null),
165
+ )
166
+ : undefined;
167
+
147
168
  const { group, supervisorAgentId } = await ctx.agentGroupRepo.createGroupWithSupervisor(
148
169
  {
149
170
  ...input.groupConfig,
@@ -152,6 +173,7 @@ export const agentGroupRouter = router({
152
173
  ),
153
174
  },
154
175
  memberAgentIds,
176
+ supervisorConfig as any,
155
177
  );
156
178
 
157
179
  return { agentIds: memberAgentIds, groupId: group.id, supervisorAgentId };
@@ -138,6 +138,7 @@ class ChatService {
138
138
  plugins: pluginIds,
139
139
  } = resolveAgentConfig({
140
140
  agentId: targetAgentId,
141
+ groupId, // Pass groupId for supervisor detection
141
142
  model: payload.model,
142
143
  plugins: enabledPlugins,
143
144
  provider: payload.provider,
@@ -627,7 +627,7 @@ describe('resolveAgentConfig', () => {
627
627
  });
628
628
  });
629
629
 
630
- describe('supervisor agent (slug from agentGroup store)', () => {
630
+ describe('supervisor agent (detected via groupId)', () => {
631
631
  const mockGroupStoreState = { groupMap: {} };
632
632
  const mockGroupWithSupervisor = {
633
633
  agents: [
@@ -651,18 +651,11 @@ describe('resolveAgentConfig', () => {
651
651
  );
652
652
  });
653
653
 
654
- it('should detect supervisor agent from agentGroup store when not found in agent store', () => {
655
- // Mock: supervisor agent is found in agentGroup store
656
- vi.spyOn(
657
- agentGroupSelectors.agentGroupByIdSelectors,
658
- 'groupBySupervisorAgentId',
659
- ).mockReturnValue(() => mockGroupWithSupervisor as any);
660
-
661
- // Mock: getGroupBySupervisorAgentId for building groupSupervisorContext
662
- vi.spyOn(
663
- agentGroupSelectors.agentGroupSelectors,
664
- 'getGroupBySupervisorAgentId',
665
- ).mockReturnValue(() => mockGroupWithSupervisor as any);
654
+ it('should detect supervisor agent using groupId for direct lookup', () => {
655
+ // Mock: groupById returns the group
656
+ vi.spyOn(agentGroupSelectors.agentGroupByIdSelectors, 'groupById').mockReturnValue(
657
+ () => mockGroupWithSupervisor as any,
658
+ );
666
659
 
667
660
  // Mock: getGroupMembers returns non-supervisor agents
668
661
  vi.spyOn(agentGroupSelectors.agentGroupSelectors, 'getGroupMembers').mockReturnValue(
@@ -680,7 +673,10 @@ describe('resolveAgentConfig', () => {
680
673
  systemRole: 'You are a group supervisor...',
681
674
  });
682
675
 
683
- const result = resolveAgentConfig({ agentId: 'supervisor-agent-id' });
676
+ const result = resolveAgentConfig({
677
+ agentId: 'supervisor-agent-id',
678
+ groupId: 'group-123',
679
+ });
684
680
 
685
681
  expect(result.isBuiltinAgent).toBe(true);
686
682
  expect(result.slug).toBe('group-supervisor');
@@ -689,17 +685,10 @@ describe('resolveAgentConfig', () => {
689
685
  });
690
686
 
691
687
  it('should pass groupSupervisorContext to getAgentRuntimeConfig', () => {
692
- // Mock: supervisor agent is found in agentGroup store
693
- vi.spyOn(
694
- agentGroupSelectors.agentGroupByIdSelectors,
695
- 'groupBySupervisorAgentId',
696
- ).mockReturnValue(() => mockGroupWithSupervisor as any);
697
-
698
- // Mock: getGroupBySupervisorAgentId for building groupSupervisorContext
699
- vi.spyOn(
700
- agentGroupSelectors.agentGroupSelectors,
701
- 'getGroupBySupervisorAgentId',
702
- ).mockReturnValue(() => mockGroupWithSupervisor as any);
688
+ // Mock: groupById returns the group
689
+ vi.spyOn(agentGroupSelectors.agentGroupByIdSelectors, 'groupById').mockReturnValue(
690
+ () => mockGroupWithSupervisor as any,
691
+ );
703
692
 
704
693
  // Mock: getGroupMembers returns non-supervisor agents
705
694
  vi.spyOn(agentGroupSelectors.agentGroupSelectors, 'getGroupMembers').mockReturnValue(
@@ -718,7 +707,10 @@ describe('resolveAgentConfig', () => {
718
707
  systemRole: 'You are a group supervisor...',
719
708
  });
720
709
 
721
- resolveAgentConfig({ agentId: 'supervisor-agent-id' });
710
+ resolveAgentConfig({
711
+ agentId: 'supervisor-agent-id',
712
+ groupId: 'group-123',
713
+ });
722
714
 
723
715
  expect(getAgentRuntimeConfigSpy).toHaveBeenCalledWith(
724
716
  'group-supervisor',
@@ -736,31 +728,53 @@ describe('resolveAgentConfig', () => {
736
728
  );
737
729
  });
738
730
 
739
- it('should treat as regular agent when supervisor is not found in agentGroup store', () => {
740
- // Mock: supervisor agent is NOT found in agentGroup store
741
- vi.spyOn(
742
- agentGroupSelectors.agentGroupByIdSelectors,
743
- 'groupBySupervisorAgentId',
744
- ).mockReturnValue(() => undefined);
745
-
746
- const result = resolveAgentConfig({ agentId: 'some-other-agent' });
731
+ it('should treat as regular agent when groupId is not provided', () => {
732
+ // Without groupId, cannot detect supervisor
733
+ const result = resolveAgentConfig({ agentId: 'supervisor-agent-id' });
747
734
 
748
735
  expect(result.isBuiltinAgent).toBe(false);
749
736
  expect(result.slug).toBeUndefined();
750
737
  expect(result.plugins).toEqual(['plugin-a', 'plugin-b']); // Falls back to agent config plugins
751
738
  });
752
739
 
753
- it('should work correctly when regenerating supervisor message', () => {
754
- // This simulates the regenerate flow where agentId is the supervisor agent ID
755
- vi.spyOn(
756
- agentGroupSelectors.agentGroupByIdSelectors,
757
- 'groupBySupervisorAgentId',
758
- ).mockReturnValue(() => mockGroupWithSupervisor as any);
740
+ it('should treat as regular agent when agentId does not match group supervisorAgentId', () => {
741
+ // Mock: groupById returns the group
742
+ vi.spyOn(agentGroupSelectors.agentGroupByIdSelectors, 'groupById').mockReturnValue(
743
+ () => mockGroupWithSupervisor as any,
744
+ );
759
745
 
760
- vi.spyOn(
761
- agentGroupSelectors.agentGroupSelectors,
762
- 'getGroupBySupervisorAgentId',
763
- ).mockReturnValue(() => mockGroupWithSupervisor as any);
746
+ // Pass a different agentId that is not the supervisor
747
+ const result = resolveAgentConfig({
748
+ agentId: 'some-other-agent',
749
+ groupId: 'group-123',
750
+ });
751
+
752
+ expect(result.isBuiltinAgent).toBe(false);
753
+ expect(result.slug).toBeUndefined();
754
+ expect(result.plugins).toEqual(['plugin-a', 'plugin-b']);
755
+ });
756
+
757
+ it('should treat as regular agent when group is not found', () => {
758
+ // Mock: groupById returns undefined
759
+ vi.spyOn(agentGroupSelectors.agentGroupByIdSelectors, 'groupById').mockReturnValue(
760
+ () => undefined,
761
+ );
762
+
763
+ const result = resolveAgentConfig({
764
+ agentId: 'supervisor-agent-id',
765
+ groupId: 'non-existent-group',
766
+ });
767
+
768
+ expect(result.isBuiltinAgent).toBe(false);
769
+ expect(result.slug).toBeUndefined();
770
+ expect(result.plugins).toEqual(['plugin-a', 'plugin-b']);
771
+ });
772
+
773
+ it('should work correctly when regenerating supervisor message with groupId', () => {
774
+ // This simulates the regenerate flow where both agentId and groupId are provided
775
+ vi.spyOn(agentGroupSelectors.agentGroupByIdSelectors, 'groupById').mockReturnValue(
776
+ () => mockGroupWithSupervisor as any,
777
+ );
764
778
 
765
779
  vi.spyOn(agentGroupSelectors.agentGroupSelectors, 'getGroupMembers').mockReturnValue(
766
780
  () => [{ id: 'member-agent-1', title: 'Agent 1' }] as any,
@@ -772,7 +786,10 @@ describe('resolveAgentConfig', () => {
772
786
  systemRole: 'Supervisor system role',
773
787
  });
774
788
 
775
- const result = resolveAgentConfig({ agentId: 'supervisor-agent-id' });
789
+ const result = resolveAgentConfig({
790
+ agentId: 'supervisor-agent-id',
791
+ groupId: 'group-123',
792
+ });
776
793
 
777
794
  // Should correctly identify as builtin supervisor agent
778
795
  expect(result.isBuiltinAgent).toBe(true);
@@ -55,6 +55,12 @@ export interface AgentConfigResolverContext {
55
55
  /** Document content for page-agent */
56
56
  documentContent?: string;
57
57
 
58
+ /**
59
+ * Group ID for supervisor detection.
60
+ * When provided, used for direct lookup instead of iterating all groups.
61
+ */
62
+ groupId?: string;
63
+
58
64
  /** Current model being used (for template variables) */
59
65
  model?: string;
60
66
  /** Plugins enabled for the agent */
@@ -114,30 +120,19 @@ export const resolveAgentConfig = (ctx: AgentConfigResolverContext): ResolvedAge
114
120
  const basePlugins = agentConfig.plugins ?? [];
115
121
 
116
122
  // Check if this is a builtin agent
117
- // First check agent store, then check if this is a supervisor agent in agentGroup store
123
+ // First check agent store, then check if this is a supervisor agent via groupId
118
124
  let slug = agentSelectors.getAgentSlugById(agentId)(agentStoreState);
119
125
  log('slug from agentStore: %s (agentId: %s)', slug, agentId);
120
126
 
121
- // If not found in agent store, check if this is a supervisor agent in any group
122
- // Supervisor agents have their slug stored in agentGroup store, not agent store
123
- if (!slug) {
127
+ // If not found in agent store, check if this is a supervisor agent using groupId
128
+ // This is more reliable than iterating all groups to find a match
129
+ if (!slug && ctx.groupId) {
124
130
  const groupStoreState = getChatGroupStoreState();
125
- const groupMap = groupStoreState.groupMap;
126
- const groupMapKeys = Object.keys(groupMap);
127
- log(
128
- 'checking groupStore for supervisor - groupMap has %d groups: %o',
129
- groupMapKeys.length,
130
- groupMapKeys.map((key) => ({
131
- groupId: key,
132
- supervisorAgentId: groupMap[key]?.supervisorAgentId,
133
- title: groupMap[key]?.title,
134
- })),
135
- );
131
+ const group = agentGroupByIdSelectors.groupById(ctx.groupId)(groupStoreState);
136
132
 
137
- const group = agentGroupByIdSelectors.groupBySupervisorAgentId(agentId)(groupStoreState);
138
133
  log(
139
- 'groupBySupervisorAgentId result for agentId %s: %o',
140
- agentId,
134
+ 'checking supervisor via groupId %s: group=%o',
135
+ ctx.groupId,
141
136
  group
142
137
  ? {
143
138
  groupId: group.id,
@@ -147,10 +142,15 @@ export const resolveAgentConfig = (ctx: AgentConfigResolverContext): ResolvedAge
147
142
  : null,
148
143
  );
149
144
 
150
- if (group) {
151
- // This is a supervisor agent - use the builtin slug
145
+ // Check if this agent is the supervisor of the specified group
146
+ if (group?.supervisorAgentId === agentId) {
152
147
  slug = BUILTIN_AGENT_SLUGS.groupSupervisor;
153
- log('agentId %s identified as group supervisor, assigned slug: %s', agentId, slug);
148
+ log(
149
+ 'agentId %s identified as group supervisor for group %s, assigned slug: %s',
150
+ agentId,
151
+ ctx.groupId,
152
+ slug,
153
+ );
154
154
  }
155
155
  }
156
156
 
@@ -213,15 +213,17 @@ export const resolveAgentConfig = (ctx: AgentConfigResolverContext): ResolvedAge
213
213
  }
214
214
 
215
215
  // Build groupSupervisorContext if this is a group-supervisor agent
216
+ // Use groupId for direct lookup instead of reverse lookup by supervisorAgentId
216
217
  let groupSupervisorContext;
217
- if (slug === BUILTIN_AGENT_SLUGS.groupSupervisor) {
218
- log('building groupSupervisorContext for agentId: %s', agentId);
218
+ if (slug === BUILTIN_AGENT_SLUGS.groupSupervisor && ctx.groupId) {
219
+ log('building groupSupervisorContext for agentId: %s, groupId: %s', agentId, ctx.groupId);
219
220
  const groupStoreState = getChatGroupStoreState();
220
- // Find the group by supervisor agent ID
221
- const group = agentGroupSelectors.getGroupBySupervisorAgentId(agentId)(groupStoreState);
221
+ // Direct lookup using groupId
222
+ const group = agentGroupByIdSelectors.groupById(ctx.groupId)(groupStoreState);
222
223
 
223
224
  log(
224
- 'getGroupBySupervisorAgentId result: %o',
225
+ 'groupById result for %s: %o',
226
+ ctx.groupId,
225
227
  group
226
228
  ? {
227
229
  agentsCount: group.agents?.length,
@@ -253,7 +255,7 @@ export const resolveAgentConfig = (ctx: AgentConfigResolverContext): ResolvedAge
253
255
  hasSystemPrompt: !!groupSupervisorContext.systemPrompt,
254
256
  });
255
257
  } else {
256
- log('WARNING: group not found for supervisor agentId: %s', agentId);
258
+ log('WARNING: group not found for groupId: %s', ctx.groupId);
257
259
  }
258
260
  }
259
261
 
@@ -20,6 +20,18 @@ export interface GroupMemberConfig {
20
20
  title?: string;
21
21
  }
22
22
 
23
+ export interface SupervisorConfig {
24
+ avatar?: string;
25
+ backgroundColor?: string;
26
+ description?: string;
27
+ model?: string;
28
+ params?: any;
29
+ provider?: string;
30
+ systemRole?: string;
31
+ tags?: string[];
32
+ title?: string;
33
+ }
34
+
23
35
  class ChatGroupService {
24
36
  /**
25
37
  * Create a group with a supervisor agent.
@@ -42,6 +54,7 @@ class ChatGroupService {
42
54
  createGroupWithMembers = (
43
55
  groupConfig: Omit<NewChatGroup, 'userId'>,
44
56
  members: GroupMemberConfig[],
57
+ supervisorConfig?: SupervisorConfig,
45
58
  ): Promise<{ agentIds: string[]; groupId: string; supervisorAgentId: string }> => {
46
59
  return lambdaClient.group.createGroupWithMembers.mutate({
47
60
  groupConfig: {
@@ -49,6 +62,7 @@ class ChatGroupService {
49
62
  config: groupConfig.config as any,
50
63
  },
51
64
  members: members as Partial<AgentItem>[],
65
+ supervisorConfig,
52
66
  });
53
67
  };
54
68