@lobehub/lobehub 2.0.0-next.338 → 2.0.0-next.339

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 (257) hide show
  1. package/.gitattributes +35 -0
  2. package/CHANGELOG.md +44 -0
  3. package/changelog/v1.json +15 -0
  4. package/locales/ar/plugin.json +12 -2
  5. package/locales/ar/providers.json +1 -0
  6. package/locales/ar/setting.json +77 -1
  7. package/locales/bg-BG/models.json +5 -10
  8. package/locales/bg-BG/plugin.json +12 -2
  9. package/locales/bg-BG/providers.json +1 -0
  10. package/locales/bg-BG/setting.json +78 -2
  11. package/locales/de-DE/models.json +51 -9
  12. package/locales/de-DE/plugin.json +12 -2
  13. package/locales/de-DE/providers.json +1 -0
  14. package/locales/de-DE/setting.json +78 -2
  15. package/locales/en-US/models.json +11 -10
  16. package/locales/en-US/plugin.json +14 -4
  17. package/locales/en-US/providers.json +1 -0
  18. package/locales/en-US/setting.json +78 -2
  19. package/locales/es-ES/plugin.json +12 -2
  20. package/locales/es-ES/providers.json +1 -0
  21. package/locales/es-ES/setting.json +78 -2
  22. package/locales/fa-IR/plugin.json +12 -2
  23. package/locales/fa-IR/providers.json +1 -0
  24. package/locales/fa-IR/setting.json +78 -2
  25. package/locales/fr-FR/plugin.json +12 -2
  26. package/locales/fr-FR/providers.json +1 -0
  27. package/locales/fr-FR/setting.json +78 -2
  28. package/locales/it-IT/plugin.json +12 -2
  29. package/locales/it-IT/providers.json +1 -0
  30. package/locales/it-IT/setting.json +78 -2
  31. package/locales/ja-JP/plugin.json +12 -2
  32. package/locales/ja-JP/providers.json +1 -0
  33. package/locales/ja-JP/setting.json +78 -2
  34. package/locales/ko-KR/plugin.json +12 -2
  35. package/locales/ko-KR/providers.json +1 -0
  36. package/locales/ko-KR/setting.json +78 -2
  37. package/locales/nl-NL/models.json +4 -9
  38. package/locales/nl-NL/plugin.json +12 -2
  39. package/locales/nl-NL/providers.json +1 -0
  40. package/locales/nl-NL/setting.json +78 -2
  41. package/locales/pl-PL/plugin.json +12 -2
  42. package/locales/pl-PL/providers.json +1 -0
  43. package/locales/pl-PL/setting.json +78 -2
  44. package/locales/pt-BR/plugin.json +12 -2
  45. package/locales/pt-BR/providers.json +1 -0
  46. package/locales/pt-BR/setting.json +78 -2
  47. package/locales/ru-RU/plugin.json +12 -2
  48. package/locales/ru-RU/providers.json +1 -0
  49. package/locales/ru-RU/setting.json +78 -2
  50. package/locales/tr-TR/plugin.json +12 -2
  51. package/locales/tr-TR/providers.json +1 -0
  52. package/locales/tr-TR/setting.json +78 -2
  53. package/locales/vi-VN/plugin.json +12 -2
  54. package/locales/vi-VN/providers.json +1 -0
  55. package/locales/vi-VN/setting.json +77 -1
  56. package/locales/zh-CN/plugin.json +12 -2
  57. package/locales/zh-CN/providers.json +1 -0
  58. package/locales/zh-CN/setting.json +78 -2
  59. package/locales/zh-TW/plugin.json +12 -2
  60. package/locales/zh-TW/providers.json +1 -0
  61. package/locales/zh-TW/setting.json +78 -2
  62. package/package.json +1 -1
  63. package/packages/agent-runtime/src/groupOrchestration/GroupOrchestrationSupervisor.ts +2 -0
  64. package/packages/agent-runtime/src/groupOrchestration/__tests__/GroupOrchestrationSupervisor.test.ts +3 -1
  65. package/packages/agent-runtime/src/groupOrchestration/types.ts +5 -0
  66. package/packages/const/src/index.ts +1 -0
  67. package/packages/const/src/klavis.ts +144 -0
  68. package/packages/const/src/lobehubSkill.ts +34 -0
  69. package/packages/const/src/recommendedSkill.ts +17 -0
  70. package/packages/model-runtime/src/core/contextBuilders/anthropic.test.ts +38 -0
  71. package/packages/model-runtime/src/core/contextBuilders/anthropic.ts +20 -1
  72. package/packages/model-runtime/src/core/contextBuilders/google.test.ts +42 -0
  73. package/packages/model-runtime/src/core/contextBuilders/google.ts +17 -0
  74. package/scripts/electronWorkflow/modifiers/dynamicToStatic.mts +273 -0
  75. package/scripts/electronWorkflow/modifiers/index.mts +10 -0
  76. package/scripts/electronWorkflow/modifiers/nextConfig.mts +1 -0
  77. package/scripts/electronWorkflow/modifiers/nextDynamicToStatic.mts +233 -0
  78. package/scripts/electronWorkflow/modifiers/removeSuspense.mts +124 -0
  79. package/scripts/electronWorkflow/modifiers/routes.mts +14 -2
  80. package/scripts/electronWorkflow/modifiers/settingsContentToStatic.mts +148 -0
  81. package/scripts/electronWorkflow/modifiers/wrapChildrenWithClientOnly.mts +73 -0
  82. package/src/app/[variants]/(main)/home/features/InputArea/SkillInstallBanner.tsx +131 -0
  83. package/src/app/[variants]/(main)/home/features/InputArea/index.tsx +34 -27
  84. package/src/app/[variants]/(main)/settings/features/SettingHeader.tsx +8 -4
  85. package/src/app/[variants]/(main)/settings/features/SettingsContent.tsx +3 -0
  86. package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +6 -0
  87. package/src/{features/PluginStore/InstalledList/List/Item/Action.tsx → app/[variants]/(main)/settings/skill/features/Actions.tsx} +45 -40
  88. package/src/app/[variants]/(main)/settings/skill/features/KlavisSkillItem.tsx +353 -0
  89. package/src/app/[variants]/(main)/settings/skill/features/LobehubSkillItem.tsx +344 -0
  90. package/src/app/[variants]/(main)/settings/skill/features/McpSkillItem.tsx +116 -0
  91. package/src/app/[variants]/(main)/settings/skill/features/SkillList.tsx +244 -0
  92. package/src/app/[variants]/(main)/settings/skill/index.tsx +35 -0
  93. package/src/components/Plugins/PluginTag.tsx +23 -35
  94. package/src/components/client/ClientOnly.tsx +6 -2
  95. package/src/features/AgentSetting/AgentPlugin/index.tsx +2 -2
  96. package/src/features/ChatInput/ActionBar/Tools/KlavisServerItem.tsx +8 -32
  97. package/src/features/ChatInput/ActionBar/Tools/LobehubSkillServerItem.tsx +8 -30
  98. package/src/features/ChatInput/ActionBar/Tools/PopoverContent.tsx +48 -59
  99. package/src/features/ChatInput/ActionBar/Tools/index.tsx +5 -23
  100. package/src/features/ChatInput/ActionBar/Tools/useControls.tsx +158 -56
  101. package/src/features/IntegrationDetailModal/index.tsx +293 -0
  102. package/src/features/{PluginStore/McpList/Detail → MCP/MCPDetail}/index.tsx +15 -6
  103. package/src/features/MCP/MCPSettings/McpSettingsModal.tsx +58 -0
  104. package/src/features/{PluginStore/McpList/Detail/Settings → MCP/MCPSettings}/index.tsx +39 -27
  105. package/src/features/PluginDetailModal/index.tsx +2 -2
  106. package/src/features/PluginDevModal/index.tsx +16 -40
  107. package/src/features/ProfileEditor/AgentTool.tsx +2 -2
  108. package/src/features/ProtocolUrlHandler/InstallPlugin/OfficialPluginInstallModal/index.tsx +1 -1
  109. package/src/features/{PluginStore/AddPluginButton.tsx → SkillStore/AddSkillButton.tsx} +3 -3
  110. package/src/features/SkillStore/CommunityList/Item.tsx +158 -0
  111. package/src/features/SkillStore/CommunityList/index.tsx +101 -0
  112. package/src/features/SkillStore/Content.tsx +59 -0
  113. package/src/features/{PluginStore/PluginEmpty.tsx → SkillStore/Empty.tsx} +8 -8
  114. package/src/features/SkillStore/LobeHubList/Item.tsx +118 -0
  115. package/src/features/SkillStore/LobeHubList/index.tsx +187 -0
  116. package/src/features/SkillStore/LobeHubList/useSkillConnect.ts +239 -0
  117. package/src/features/SkillStore/Search/index.tsx +43 -0
  118. package/src/features/{PluginStore → SkillStore}/index.tsx +14 -10
  119. package/src/features/SkillStore/style.ts +27 -0
  120. package/src/locales/default/plugin.ts +15 -4
  121. package/src/locales/default/setting.ts +185 -2
  122. package/src/services/chat/mecha/agentConfigResolver.test.ts +197 -0
  123. package/src/services/chat/mecha/agentConfigResolver.ts +44 -17
  124. package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +40 -37
  125. package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +78 -0
  126. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +50 -16
  127. package/src/store/global/initialState.ts +1 -0
  128. package/src/store/tool/slices/lobehubSkillStore/action.test.ts +914 -0
  129. package/src/store/tool/slices/lobehubSkillStore/selectors.test.ts +548 -0
  130. package/.cursor/skills/vercel-react-best-practices/AGENTS.md +0 -2410
  131. package/.cursor/skills/vercel-react-best-practices/SKILL.md +0 -125
  132. package/.cursor/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  133. package/.cursor/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -49
  134. package/.cursor/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
  135. package/.cursor/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
  136. package/.cursor/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -36
  137. package/.cursor/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
  138. package/.cursor/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
  139. package/.cursor/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
  140. package/.cursor/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
  141. package/.cursor/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
  142. package/.cursor/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  143. package/.cursor/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
  144. package/.cursor/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
  145. package/.cursor/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
  146. package/.cursor/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
  147. package/.cursor/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
  148. package/.cursor/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -57
  149. package/.cursor/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
  150. package/.cursor/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
  151. package/.cursor/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
  152. package/.cursor/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
  153. package/.cursor/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
  154. package/.cursor/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
  155. package/.cursor/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
  156. package/.cursor/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
  157. package/.cursor/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
  158. package/.cursor/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
  159. package/.cursor/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
  160. package/.cursor/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
  161. package/.cursor/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  162. package/.cursor/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
  163. package/.cursor/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
  164. package/.cursor/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  165. package/.cursor/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  166. package/.cursor/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
  167. package/.cursor/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
  168. package/.cursor/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
  169. package/.cursor/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
  170. package/.cursor/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
  171. package/.cursor/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  172. package/.cursor/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
  173. package/.cursor/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
  174. package/.cursor/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
  175. package/.cursor/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
  176. package/.cursor/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
  177. package/.cursor/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
  178. package/.cursor/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
  179. package/src/features/PluginStore/Content.tsx +0 -54
  180. package/src/features/PluginStore/InstalledList/Detail/CustomPluginEmptyState.tsx +0 -79
  181. package/src/features/PluginStore/InstalledList/Detail/index.tsx +0 -21
  182. package/src/features/PluginStore/InstalledList/List/Item/index.tsx +0 -61
  183. package/src/features/PluginStore/InstalledList/List/index.tsx +0 -72
  184. package/src/features/PluginStore/InstalledList/index.tsx +0 -90
  185. package/src/features/PluginStore/McpList/List/Action.tsx +0 -119
  186. package/src/features/PluginStore/McpList/List/Item.tsx +0 -83
  187. package/src/features/PluginStore/McpList/List/index.tsx +0 -93
  188. package/src/features/PluginStore/McpList/index.tsx +0 -58
  189. package/src/features/PluginStore/PluginList/Detail/DetailProvider.tsx +0 -19
  190. package/src/features/PluginStore/PluginList/Detail/EmptyState.tsx +0 -56
  191. package/src/features/PluginStore/PluginList/Detail/Header.tsx +0 -130
  192. package/src/features/PluginStore/PluginList/Detail/InstallDetail/Nav.tsx +0 -73
  193. package/src/features/PluginStore/PluginList/Detail/InstallDetail/Settings.tsx +0 -19
  194. package/src/features/PluginStore/PluginList/Detail/InstallDetail/Tools.tsx +0 -111
  195. package/src/features/PluginStore/PluginList/Detail/InstallDetail/index.tsx +0 -24
  196. package/src/features/PluginStore/PluginList/Detail/Loading.tsx +0 -42
  197. package/src/features/PluginStore/PluginList/Detail/TagList.tsx +0 -35
  198. package/src/features/PluginStore/PluginList/Detail/index.tsx +0 -39
  199. package/src/features/PluginStore/PluginList/Detail/useCategory.tsx +0 -76
  200. package/src/features/PluginStore/PluginList/List/Action.tsx +0 -78
  201. package/src/features/PluginStore/PluginList/List/Item.tsx +0 -92
  202. package/src/features/PluginStore/PluginList/List/index.tsx +0 -94
  203. package/src/features/PluginStore/PluginList/index.tsx +0 -46
  204. package/src/features/PluginStore/Search/index.tsx +0 -40
  205. /package/{.codex/skills → .agents}/vercel-react-best-practices/AGENTS.md +0 -0
  206. /package/{.codex/skills → .agents}/vercel-react-best-practices/SKILL.md +0 -0
  207. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -0
  208. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/advanced-use-latest.md +0 -0
  209. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-api-routes.md +0 -0
  210. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-defer-await.md +0 -0
  211. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-dependencies.md +0 -0
  212. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-parallel.md +0 -0
  213. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -0
  214. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -0
  215. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-conditional.md +0 -0
  216. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -0
  217. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -0
  218. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-preload.md +0 -0
  219. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-event-listeners.md +0 -0
  220. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -0
  221. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -0
  222. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-swr-dedup.md +0 -0
  223. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -0
  224. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-cache-function-results.md +0 -0
  225. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-cache-property-access.md +0 -0
  226. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-cache-storage.md +0 -0
  227. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-combine-iterations.md +0 -0
  228. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-early-exit.md +0 -0
  229. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -0
  230. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-index-maps.md +0 -0
  231. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-length-check-first.md +0 -0
  232. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-min-max-loop.md +0 -0
  233. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -0
  234. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -0
  235. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-activity.md +0 -0
  236. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -0
  237. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -0
  238. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -0
  239. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -0
  240. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -0
  241. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -0
  242. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -0
  243. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-dependencies.md +0 -0
  244. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-derived-state.md +0 -0
  245. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -0
  246. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -0
  247. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-memo.md +0 -0
  248. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-transitions.md +0 -0
  249. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -0
  250. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-cache-lru.md +0 -0
  251. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-cache-react.md +0 -0
  252. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -0
  253. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-serialization.md +0 -0
  254. /package/src/{features/PluginStore/InstalledList → app/[variants]/(main)/settings/skill/features}/EditCustomPlugin.tsx +0 -0
  255. /package/src/features/{PluginStore/McpList/Detail → MCP/MCPDetail}/Loading.tsx +0 -0
  256. /package/src/features/{PluginStore → SkillStore}/Loading.tsx +0 -0
  257. /package/src/features/{PluginStore → SkillStore}/VirtuosoLoading.tsx +0 -0
@@ -212,9 +212,9 @@ export default {
212
212
  'dev.deleteSuccess': 'Skill deleted',
213
213
  'dev.manifest.identifier.desc': 'Unique identifier for the Skill',
214
214
  'dev.manifest.identifier.label': 'Identifier',
215
+ 'dev.manifest.mode.claude': 'Claude Skill',
216
+ 'dev.manifest.mode.claudeWip': 'Coming Soon',
215
217
  'dev.manifest.mode.mcp': 'MCP',
216
- 'dev.manifest.mode.mcpExp': 'Experimental',
217
- 'dev.manifest.mode.url': 'Online URL',
218
218
  'dev.manifest.name.desc': 'Skill title',
219
219
  'dev.manifest.name.label': 'Title',
220
220
  'dev.manifest.name.placeholder': 'Search engine',
@@ -321,8 +321,11 @@ export default {
321
321
  'dev.saveSuccess': 'Settings saved',
322
322
  'dev.tabs.manifest': 'Manifest',
323
323
  'dev.tabs.meta': 'Meta info',
324
- 'dev.title.create': 'Add custom Skill',
325
- 'dev.title.edit': 'Edit custom Skill',
324
+ 'dev.title.create': 'Add Custom Skill',
325
+ 'dev.title.edit': 'Edit Custom Skill',
326
+ 'dev.title.editCommunity': 'Edit Community Skill',
327
+ 'dev.title.skillDetails': 'Skill Details',
328
+ 'dev.title.skillSettings': 'Skill Settings',
326
329
  'dev.type.lobe': '{{appName}} Skill',
327
330
  'dev.type.openai': 'OpenAI Skill',
328
331
  'dev.update': 'Update',
@@ -346,6 +349,12 @@ export default {
346
349
  'inspector.orphanedToolCall':
347
350
  'Orphaned Skill call detected, may affect Agent execution. Remove it.',
348
351
  'inspector.pluginRender': 'View Skill UI',
352
+ 'integrationDetail.author': 'Author',
353
+ 'integrationDetail.details': 'Details',
354
+ 'integrationDetail.developedBy': 'Developed by',
355
+ 'integrationDetail.tools': 'Tools',
356
+ 'integrationDetail.trustWarning':
357
+ "Only use connectors from developers you trust. LobeHub does not control which tools developers make available and cannot verify that they will work as intended or that they won't change.",
349
358
  'list.item.deprecated.title': 'Deleted',
350
359
  'list.item.local.config': 'Config',
351
360
  'list.item.local.title': 'Custom',
@@ -491,7 +500,9 @@ export default {
491
500
  'settings.saveSettings': 'Save',
492
501
  'settings.title': 'Skill community settings',
493
502
  'showInPortal': 'View details in Workspace',
503
+ 'skillInstallBanner.title': 'Add skills to Lobe AI',
494
504
  'store.actions.cancel': 'Cancel',
505
+ 'store.actions.configure': 'Configure',
495
506
  'store.actions.confirmUninstall': 'Uninstalling will clear Skill config. Continue?',
496
507
  'store.actions.detail': 'Details',
497
508
  'store.actions.install': 'Install',
@@ -116,7 +116,7 @@ export default {
116
116
  'defaultAgent.model.desc': 'Default model used when creating a new Agent',
117
117
  'defaultAgent.model.title': 'Model',
118
118
  'defaultAgent.title': 'Default Agent Settings',
119
- 'group.aiConfig': 'Model',
119
+ 'group.aiConfig': 'Agent',
120
120
  'group.common': 'General',
121
121
  'group.profile': 'Account',
122
122
  'group.subscription': 'Subscription',
@@ -557,6 +557,14 @@ export default {
557
557
  'Select a voice for the current agent, different TTS services support different voices',
558
558
  'settingTTS.voice.preview': 'Voice Preview',
559
559
  'settingTTS.voice.title': 'Text-to-Speech Voice',
560
+ 'skillStore.button': 'Skill Store',
561
+ 'skillStore.empty': 'Browse the Skill store. Install one to get started, add more later.',
562
+ 'skillStore.emptySearch': 'No matching Skills',
563
+ 'skillStore.networkError': 'Network error, please try again',
564
+ 'skillStore.search': 'Search skills by name or keyword, press Enter to search…',
565
+ 'skillStore.tabs.community': 'Community',
566
+ 'skillStore.tabs.lobehub': 'LobeHub',
567
+ 'skillStore.title': 'Skill Store',
560
568
  'startConversation': 'Start Conversation',
561
569
  'storage.actions.export.button': 'Export',
562
570
  'storage.actions.export.exportType.agent': 'Export Agent Settings',
@@ -639,6 +647,7 @@ export default {
639
647
  'systemAgent.translation.modelDesc': 'Specify the model used for translation',
640
648
  'systemAgent.translation.title': 'Message Translation Agent',
641
649
  'tab.about': 'About',
650
+ 'tab.addCustomSkill': 'Add custom skill',
642
651
  'tab.agent': 'Agent Service',
643
652
  'tab.all': 'All',
644
653
  'tab.apikey': 'API Key Management',
@@ -653,6 +662,12 @@ export default {
653
662
  'tab.provider': 'AI Service Provider',
654
663
  'tab.proxy': 'Network Proxy',
655
664
  'tab.security': 'Security',
665
+ 'tab.skill': 'Skill Management',
666
+ 'tab.skillDesc': 'Manage your connected skills and integrations',
667
+ 'tab.skillDetail': 'Skill Details',
668
+ 'tab.skillEmpty': 'No skills connected yet',
669
+ 'tab.skillInstalled': 'Installed Skills',
670
+ 'tab.skillIntegration': 'Integration',
656
671
  'tab.stats': 'Analytics',
657
672
  'tab.storage': 'Data Storage',
658
673
  'tab.sync': 'Cloud Sync',
@@ -665,7 +680,10 @@ export default {
665
680
  'tools.klavis.authCompleted': 'Authentication Completed',
666
681
  'tools.klavis.authFailed': 'Authentication Failed',
667
682
  'tools.klavis.authRequired': 'Authentication Required',
683
+ 'tools.klavis.connect': 'Connect',
668
684
  'tools.klavis.connected': 'Connected',
685
+ 'tools.klavis.disconnect': 'Disconnect',
686
+ 'tools.klavis.disconnected': 'Disconnected',
669
687
  'tools.klavis.error': 'Error',
670
688
  'tools.klavis.groupName': 'Klavis Tools',
671
689
  'tools.klavis.manage': 'Manage Klavis',
@@ -678,18 +696,183 @@ export default {
678
696
  'tools.klavis.serverCreatedFailed': 'Failed to create server',
679
697
  'tools.klavis.serverRemoved': 'Server removed',
680
698
  'tools.klavis.servers': 'servers',
699
+
700
+ 'tools.klavis.servers.airtable.description':
701
+ 'Airtable is a cloud-based database and spreadsheet platform that combines the flexibility of a spreadsheet with the power of a database, enabling teams to organize, track, and collaborate on projects with customizable views and powerful automation features',
702
+
703
+ 'tools.klavis.servers.airtable.introduction':
704
+ 'Integrate with Airtable to manage your databases and workflows. Query records, create entries, update data, and automate operations with customizable views and powerful tracking features.',
705
+
706
+ 'tools.klavis.servers.cal-com.description':
707
+ 'Cal.com is an open-source scheduling platform that helps you schedule meetings without the back-and-forth emails. Manage event types, bookings, availability, and integrate with calendars for seamless appointment scheduling',
708
+
709
+ 'tools.klavis.servers.cal-com.introduction':
710
+ 'Connect to Cal.com to manage your scheduling and appointments. View availability, book meetings, manage event types, and automate your calendar through natural conversation.',
711
+
712
+ 'tools.klavis.servers.clickup.description':
713
+ 'ClickUp is a comprehensive project management and productivity platform that helps teams organize tasks, manage projects, and collaborate effectively with customizable workflows and powerful tracking features',
714
+
715
+ 'tools.klavis.servers.clickup.introduction':
716
+ 'Connect to ClickUp to manage tasks, track projects, and organize your work. Create tasks, update statuses, manage custom workflows, and collaborate with your team through natural language commands.',
717
+
718
+ 'tools.klavis.servers.confluence.description':
719
+ 'Confluence is a team workspace where knowledge and collaboration meet',
720
+
721
+ 'tools.klavis.servers.confluence.introduction':
722
+ 'Connect to Confluence to access and manage team documentation. Search pages, create content, organize spaces, and build your knowledge base through conversational AI assistance.',
723
+
724
+ 'tools.klavis.servers.dropbox.description':
725
+ 'Complete file management solution for Dropbox cloud storage. Upload, download, organize files and folders, manage sharing and collaboration, handle file versions, create file requests, and perform batch operations on your Dropbox files and folders',
726
+
727
+ 'tools.klavis.servers.dropbox.introduction':
728
+ 'Integrate with Dropbox to access and manage your files. Upload, download, share files, manage folders, handle file versions, and organize your cloud storage through conversational AI.',
729
+
730
+ 'tools.klavis.servers.figma.description':
731
+ 'Figma is a collaborative interface design tool for web and mobile applications.',
732
+
733
+ 'tools.klavis.servers.figma.introduction':
734
+ 'Connect to Figma to access design files and collaborate on projects. View designs, export assets, browse components, and manage your design workflow through natural conversation.',
735
+
736
+ 'tools.klavis.servers.github.description': 'Enhanced GitHub MCP Server',
737
+
738
+ 'tools.klavis.servers.github.introduction':
739
+ 'Connect to GitHub to manage repositories, issues, pull requests, and code. Search code, review changes, create branches, and collaborate on software development projects through conversational AI.',
740
+
741
+ // Klavis Servers i18n
742
+ 'tools.klavis.servers.gmail.description': 'Gmail is a free email service provided by Google',
743
+
744
+ 'tools.klavis.servers.gmail.introduction':
745
+ 'Bring the power of Gmail directly into your AI assistant. Read, compose, and send emails, search your inbox, manage labels, and organize your communications—all through natural conversation.',
746
+
747
+ 'tools.klavis.servers.google-calendar.description':
748
+ 'Google Calendar is a time-management and scheduling calendar service',
749
+
750
+ 'tools.klavis.servers.google-calendar.introduction':
751
+ 'Integrate Google Calendar to view, create, and manage your events seamlessly. Schedule meetings, set reminders, check availability, and coordinate your time—all through natural language commands.',
752
+
753
+ 'tools.klavis.servers.google-docs.description':
754
+ 'Google Docs is a word processor included as part of the free, web-based Google Docs Editors suite',
755
+
756
+ 'tools.klavis.servers.google-docs.introduction':
757
+ 'Integrate with Google Docs to create, edit, and manage documents. Write content, format text, collaborate in real-time, and access your documents through natural conversation.',
758
+
759
+ 'tools.klavis.servers.google-drive.description': 'Google Drive is a cloud storage service',
760
+
761
+ 'tools.klavis.servers.google-drive.introduction':
762
+ 'Connect to Google Drive to access, organize, and manage your files. Search documents, upload files, share content, and navigate your cloud storage efficiently through AI assistance.',
763
+
764
+ 'tools.klavis.servers.google-sheets.description':
765
+ 'Google Sheets is a web-based spreadsheet application that allows users to create, edit, and collaborate on spreadsheets online',
766
+
767
+ 'tools.klavis.servers.google-sheets.introduction':
768
+ 'Connect to Google Sheets to read, write, and analyze spreadsheet data. Perform calculations, generate reports, create charts, and manage tabular data collaboratively with AI assistance.',
769
+
770
+ 'tools.klavis.servers.hubspot.description':
771
+ 'HubSpot is a developer and marketer of software products for inbound marketing, sales, and customer service',
772
+
773
+ 'tools.klavis.servers.hubspot.introduction':
774
+ 'Integrate with HubSpot to manage contacts, deals, and marketing campaigns. Access CRM data, track pipelines, automate workflows, and streamline your sales and marketing operations.',
775
+
776
+ 'tools.klavis.servers.jira.description':
777
+ 'Jira is a project management and issue tracking tool developed by Atlassian',
778
+
779
+ 'tools.klavis.servers.jira.introduction':
780
+ 'Integrate with Jira to manage issues, track progress, and organize sprints. Create tickets, update statuses, query project data, and streamline your development workflow through natural conversation.',
781
+
782
+ 'tools.klavis.servers.notion.description':
783
+ 'Notion is a collaborative productivity and note-taking application',
784
+
785
+ 'tools.klavis.servers.notion.introduction':
786
+ 'Connect to Notion to access and manage your workspace. Create pages, search content, update databases, and organize your knowledge base—all through natural conversation with your AI assistant.',
787
+
788
+ 'tools.klavis.servers.onedrive.description':
789
+ 'OneDrive is a file hosting service and synchronization service operated by Microsoft',
790
+
791
+ 'tools.klavis.servers.onedrive.introduction':
792
+ 'Connect to OneDrive to access and manage your Microsoft cloud files. Upload, download, share files, organize folders, and collaborate on documents through AI-powered assistance.',
793
+
794
+ 'tools.klavis.servers.outlook-mail.description':
795
+ 'Outlook Mail is a web-based suite of webmail, contacts, tasks, and calendaring services from Microsoft.',
796
+
797
+ 'tools.klavis.servers.outlook-mail.introduction':
798
+ 'Integrate with Outlook Mail to read, send, and manage your Microsoft emails. Search messages, compose emails, manage folders, and organize your inbox through natural conversation.',
799
+
800
+ 'tools.klavis.servers.salesforce.description':
801
+ "Salesforce is the world's leading customer relationship management (CRM) platform that helps businesses connect with customers, partners, and potential customers",
802
+
803
+ 'tools.klavis.servers.salesforce.introduction':
804
+ 'Connect to Salesforce to manage customer relationships and sales data. Query records, update opportunities, track leads, and automate your CRM workflows through natural language commands.',
805
+
806
+ 'tools.klavis.servers.slack.description':
807
+ 'Slack is a messaging app for business that connects people to the information they need',
808
+
809
+ 'tools.klavis.servers.slack.introduction':
810
+ 'Integrate with Slack to send messages, search conversations, and manage channels. Connect with your team, automate communication workflows, and access workspace information through natural language.',
811
+
812
+ 'tools.klavis.servers.supabase.description': 'Supabase official MCP Server',
813
+
814
+ 'tools.klavis.servers.supabase.introduction':
815
+ 'Integrate with Supabase to manage your database and backend services. Query data, manage authentication, handle storage, and interact with your application backend through natural conversation.',
816
+
817
+ 'tools.klavis.servers.whatsapp.description':
818
+ 'WhatsApp Business API integration that enables sending text messages, media, and managing conversations with customers. Perfect for customer support, marketing campaigns, and automated messaging workflows through the official WhatsApp Business platform.',
819
+
820
+ 'tools.klavis.servers.whatsapp.introduction':
821
+ 'Integrate with WhatsApp Business to send messages, manage conversations, and engage with customers. Automate messaging workflows and handle communications through conversational AI.',
822
+
823
+ 'tools.klavis.servers.youtube.description':
824
+ 'YouTube is a video-sharing platform where users can upload, share, and discover content. Access video information, transcripts, and metadata programmatically.',
825
+
826
+ 'tools.klavis.servers.youtube.introduction':
827
+ 'Connect to YouTube to search videos, access transcripts, and retrieve video information. Analyze content, extract metadata, and discover videos through natural conversation.',
828
+
829
+ 'tools.klavis.servers.zendesk.description': 'Zendesk is a customer service software company',
830
+
831
+ 'tools.klavis.servers.zendesk.introduction':
832
+ 'Integrate with Zendesk to manage support tickets and customer interactions. Create, update, and track support requests, access customer data, and streamline your support operations.',
833
+
681
834
  'tools.klavis.tools': 'tools',
835
+
682
836
  'tools.klavis.verifyAuth': 'I have completed authentication',
837
+
683
838
  'tools.lobehubSkill.authorize': 'Authorize',
839
+
684
840
  'tools.lobehubSkill.connect': 'Connect',
841
+
842
+ 'tools.lobehubSkill.connected': 'Connected',
843
+
844
+ 'tools.lobehubSkill.disconnect': 'Disconnect',
845
+
846
+ 'tools.lobehubSkill.disconnectConfirm.desc':
847
+ "You can still continue previous chats that reference {{name}} content. However, the assistant won't be able to access new content or perform new tasks.",
848
+
849
+ 'tools.lobehubSkill.disconnectConfirm.title': 'Disconnect {{name}}?',
850
+
851
+ 'tools.lobehubSkill.disconnected': 'Disconnected',
852
+
685
853
  'tools.lobehubSkill.error': 'Error',
854
+ // LobeHub Skill Providers i18n
855
+ 'tools.lobehubSkill.providers.linear.description':
856
+ 'Linear is a modern issue tracking and project management tool designed for high-performance teams to build better software faster',
857
+ 'tools.lobehubSkill.providers.linear.introduction':
858
+ 'Bring the power of Linear directly into your AI assistant. Create and update issues, manage sprints, track project progress, and streamline your development workflow—all through natural conversation.',
859
+ 'tools.lobehubSkill.providers.microsoft.description':
860
+ 'Outlook Calendar is an integrated scheduling tool within Microsoft Outlook that enables users to create appointments, organize meetings with others, and manage their time and events effectively.',
861
+ 'tools.lobehubSkill.providers.microsoft.introduction':
862
+ 'Integrate with Outlook Calendar to view, create, and manage your events seamlessly. Schedule meetings, check availability, set reminders, and coordinate your time—all through natural language commands.',
863
+ 'tools.lobehubSkill.providers.twitter.description':
864
+ 'X (Twitter) is a social media platform for sharing real-time updates, news, and engaging with your audience through posts, replies, and direct messages.',
865
+ 'tools.lobehubSkill.providers.twitter.introduction':
866
+ 'Connect to X (Twitter) to post tweets, manage your timeline, and engage with your audience. Create content, schedule posts, monitor mentions, and build your social media presence through conversational AI.',
867
+
686
868
  'tools.notInstalled': 'Not Installed',
687
869
  'tools.notInstalledWarning':
688
870
  'This skill is not currently installed, which may affect agent functionality.',
689
871
  'tools.plugins.enabled': 'Enabled: {{num}}',
690
872
  'tools.plugins.groupName': 'Skills',
873
+ 'tools.plugins.management': 'Skill Management',
691
874
  'tools.plugins.noEnabled': 'No skills enabled',
692
- 'tools.plugins.store': 'Skill Store',
875
+ 'tools.plugins.store': 'Add skill',
693
876
  'tools.tabs.all': 'All',
694
877
  'tools.tabs.installed': 'Enabled',
695
878
  'tools.title': 'Extension Tools',
@@ -651,6 +651,96 @@ describe('resolveAgentConfig', () => {
651
651
  );
652
652
  });
653
653
 
654
+ describe('supervisor with own slug (priority check)', () => {
655
+ // This tests the fix for LOBE-4127: When supervisor agent has its own slug,
656
+ // it should still use 'group-supervisor' slug when in group scope
657
+
658
+ it('should use group-supervisor slug even when agent has its own slug in group scope', () => {
659
+ // Supervisor agent has its own slug (e.g., from being a builtin agent)
660
+ vi.spyOn(agentSelectors.agentSelectors, 'getAgentSlugById').mockReturnValue(
661
+ () => 'some-agent-slug',
662
+ );
663
+
664
+ // Mock: groupById returns the group
665
+ vi.spyOn(agentGroupSelectors.agentGroupByIdSelectors, 'groupById').mockReturnValue(
666
+ () => mockGroupWithSupervisor as any,
667
+ );
668
+
669
+ vi.spyOn(agentGroupSelectors.agentGroupSelectors, 'getGroupMembers').mockReturnValue(
670
+ () =>
671
+ [
672
+ { id: 'member-agent-1', title: 'Agent 1' },
673
+ { id: 'member-agent-2', title: 'Agent 2' },
674
+ ] as any,
675
+ );
676
+
677
+ vi.spyOn(builtinAgents, 'getAgentRuntimeConfig').mockReturnValue({
678
+ chatConfig: { enableHistoryCount: false },
679
+ plugins: [GroupManagementIdentifier, GTDIdentifier],
680
+ systemRole: 'You are a group supervisor...',
681
+ });
682
+
683
+ const result = resolveAgentConfig({
684
+ agentId: 'supervisor-agent-id',
685
+ groupId: 'group-123',
686
+ scope: 'group', // Key: must be 'group' scope
687
+ });
688
+
689
+ // Should use group-supervisor, NOT the agent's own slug
690
+ expect(result.isBuiltinAgent).toBe(true);
691
+ expect(result.slug).toBe('group-supervisor');
692
+ expect(result.plugins).toContain(GroupManagementIdentifier);
693
+ });
694
+
695
+ it('should use agent own slug when scope is not group', () => {
696
+ // Supervisor agent has its own slug
697
+ vi.spyOn(agentSelectors.agentSelectors, 'getAgentSlugById').mockReturnValue(
698
+ () => 'some-agent-slug',
699
+ );
700
+
701
+ // Mock: groupById returns the group
702
+ vi.spyOn(agentGroupSelectors.agentGroupByIdSelectors, 'groupById').mockReturnValue(
703
+ () => mockGroupWithSupervisor as any,
704
+ );
705
+
706
+ vi.spyOn(builtinAgents, 'getAgentRuntimeConfig').mockReturnValue({
707
+ plugins: ['agent-specific-plugin'],
708
+ systemRole: 'Agent specific system role',
709
+ });
710
+
711
+ const result = resolveAgentConfig({
712
+ agentId: 'supervisor-agent-id',
713
+ groupId: 'group-123',
714
+ scope: 'main', // Not 'group' scope
715
+ });
716
+
717
+ // Should use agent's own slug since scope is not 'group'
718
+ expect(result.isBuiltinAgent).toBe(true);
719
+ expect(result.slug).toBe('some-agent-slug');
720
+ });
721
+
722
+ it('should use agent own slug when groupId is not provided', () => {
723
+ // Supervisor agent has its own slug
724
+ vi.spyOn(agentSelectors.agentSelectors, 'getAgentSlugById').mockReturnValue(
725
+ () => 'some-agent-slug',
726
+ );
727
+
728
+ vi.spyOn(builtinAgents, 'getAgentRuntimeConfig').mockReturnValue({
729
+ plugins: ['agent-specific-plugin'],
730
+ systemRole: 'Agent specific system role',
731
+ });
732
+
733
+ const result = resolveAgentConfig({
734
+ agentId: 'supervisor-agent-id',
735
+ scope: 'group', // Even with group scope, no groupId
736
+ });
737
+
738
+ // Should use agent's own slug since no groupId
739
+ expect(result.isBuiltinAgent).toBe(true);
740
+ expect(result.slug).toBe('some-agent-slug');
741
+ });
742
+ });
743
+
654
744
  it('should detect supervisor agent using groupId for direct lookup', () => {
655
745
  // Mock: groupById returns the group
656
746
  vi.spyOn(agentGroupSelectors.agentGroupByIdSelectors, 'groupById').mockReturnValue(
@@ -676,6 +766,7 @@ describe('resolveAgentConfig', () => {
676
766
  const result = resolveAgentConfig({
677
767
  agentId: 'supervisor-agent-id',
678
768
  groupId: 'group-123',
769
+ scope: 'group', // Required: supervisor detection only works in group scope
679
770
  });
680
771
 
681
772
  expect(result.isBuiltinAgent).toBe(true);
@@ -710,6 +801,7 @@ describe('resolveAgentConfig', () => {
710
801
  resolveAgentConfig({
711
802
  agentId: 'supervisor-agent-id',
712
803
  groupId: 'group-123',
804
+ scope: 'group', // Required: supervisor detection only works in group scope
713
805
  });
714
806
 
715
807
  expect(getAgentRuntimeConfigSpy).toHaveBeenCalledWith(
@@ -789,6 +881,7 @@ describe('resolveAgentConfig', () => {
789
881
  const result = resolveAgentConfig({
790
882
  agentId: 'supervisor-agent-id',
791
883
  groupId: 'group-123',
884
+ scope: 'group', // Required: supervisor detection only works in group scope
792
885
  });
793
886
 
794
887
  // Should correctly identify as builtin supervisor agent
@@ -913,4 +1006,108 @@ describe('resolveAgentConfig', () => {
913
1006
  expect(result.plugins).toContain('lobe-gtd');
914
1007
  });
915
1008
  });
1009
+
1010
+ describe('disableTools (broadcast scenario)', () => {
1011
+ beforeEach(() => {
1012
+ vi.spyOn(agentSelectors.agentSelectors, 'getAgentSlugById').mockReturnValue(() => undefined);
1013
+ });
1014
+
1015
+ it('should return empty plugins when disableTools is true for regular agent', () => {
1016
+ vi.spyOn(agentSelectors.agentSelectors, 'getAgentConfigById').mockReturnValue(
1017
+ () =>
1018
+ ({
1019
+ ...mockAgentConfig,
1020
+ plugins: ['plugin-a', 'plugin-b', 'lobe-gtd'],
1021
+ }) as any,
1022
+ );
1023
+
1024
+ const result = resolveAgentConfig({
1025
+ agentId: 'test-agent',
1026
+ disableTools: true,
1027
+ });
1028
+
1029
+ expect(result.plugins).toEqual([]);
1030
+ });
1031
+
1032
+ it('should keep plugins when disableTools is false', () => {
1033
+ const result = resolveAgentConfig({
1034
+ agentId: 'test-agent',
1035
+ disableTools: false,
1036
+ });
1037
+
1038
+ expect(result.plugins).toEqual(['plugin-a', 'plugin-b']);
1039
+ });
1040
+
1041
+ it('should keep plugins when disableTools is undefined', () => {
1042
+ const result = resolveAgentConfig({ agentId: 'test-agent' });
1043
+
1044
+ expect(result.plugins).toEqual(['plugin-a', 'plugin-b']);
1045
+ });
1046
+
1047
+ it('should return empty plugins for builtin agent when disableTools is true', () => {
1048
+ vi.spyOn(agentSelectors.agentSelectors, 'getAgentSlugById').mockReturnValue(
1049
+ () => 'some-builtin-slug',
1050
+ );
1051
+ vi.spyOn(builtinAgents, 'getAgentRuntimeConfig').mockReturnValue({
1052
+ plugins: ['runtime-plugin-1', 'runtime-plugin-2'],
1053
+ systemRole: 'Runtime system role',
1054
+ });
1055
+
1056
+ const result = resolveAgentConfig({
1057
+ agentId: 'builtin-agent',
1058
+ disableTools: true,
1059
+ });
1060
+
1061
+ expect(result.plugins).toEqual([]);
1062
+ expect(result.isBuiltinAgent).toBe(true);
1063
+ });
1064
+
1065
+ it('should return empty plugins in page scope when disableTools is true', () => {
1066
+ vi.spyOn(builtinAgents, 'getAgentRuntimeConfig').mockReturnValue({
1067
+ plugins: [PageAgentIdentifier],
1068
+ systemRole: 'Page agent system role',
1069
+ });
1070
+
1071
+ const result = resolveAgentConfig({
1072
+ agentId: 'test-agent',
1073
+ disableTools: true,
1074
+ scope: 'page',
1075
+ });
1076
+
1077
+ // disableTools should override page scope injection
1078
+ expect(result.plugins).toEqual([]);
1079
+ });
1080
+
1081
+ it('should take precedence over isSubTask filtering', () => {
1082
+ vi.spyOn(agentSelectors.agentSelectors, 'getAgentConfigById').mockReturnValue(
1083
+ () =>
1084
+ ({
1085
+ ...mockAgentConfig,
1086
+ plugins: ['lobe-gtd', 'plugin-a'],
1087
+ }) as any,
1088
+ );
1089
+
1090
+ const result = resolveAgentConfig({
1091
+ agentId: 'test-agent',
1092
+ disableTools: true,
1093
+ isSubTask: true,
1094
+ });
1095
+
1096
+ // disableTools should result in empty plugins regardless of isSubTask
1097
+ expect(result.plugins).toEqual([]);
1098
+ });
1099
+
1100
+ it('should preserve agentConfig and chatConfig when disableTools is true', () => {
1101
+ const result = resolveAgentConfig({
1102
+ agentId: 'test-agent',
1103
+ disableTools: true,
1104
+ });
1105
+
1106
+ // Only plugins should be empty, other config should be preserved
1107
+ expect(result.plugins).toEqual([]);
1108
+ expect(result.agentConfig).toEqual(mockAgentConfig);
1109
+ expect(result.chatConfig).toEqual(mockChatConfig);
1110
+ expect(result.isBuiltinAgent).toBe(false);
1111
+ });
1112
+ });
916
1113
  });
@@ -51,6 +51,12 @@ export interface AgentConfigResolverContext {
51
51
  /** Agent ID to resolve config for */
52
52
  agentId: string;
53
53
 
54
+ /**
55
+ * Whether to disable all tools for this agent execution.
56
+ * When true, returns empty plugins array (used for broadcast scenarios).
57
+ */
58
+ disableTools?: boolean;
59
+
54
60
  // Builtin agent specific context
55
61
  /** Document content for page-agent */
56
62
  documentContent?: string;
@@ -112,13 +118,27 @@ export interface ResolvedAgentConfig {
112
118
  * For regular agents, this simply returns the config from the store.
113
119
  */
114
120
  export const resolveAgentConfig = (ctx: AgentConfigResolverContext): ResolvedAgentConfig => {
115
- const { agentId, model, documentContent, plugins, targetAgentConfig, isSubTask } = ctx;
116
-
117
- log('resolveAgentConfig called with agentId: %s, scope: %s, isSubTask: %s', agentId, ctx.scope, isSubTask);
118
-
119
- // Helper to filter out lobe-gtd in sub-task context to prevent nested sub-task creation
120
- const applySubTaskFilter = (pluginIds: string[]) =>
121
- isSubTask ? pluginIds.filter((id) => id !== 'lobe-gtd') : pluginIds;
121
+ const { agentId, model, documentContent, plugins, targetAgentConfig, isSubTask, disableTools } =
122
+ ctx;
123
+
124
+ log(
125
+ 'resolveAgentConfig called with agentId: %s, scope: %s, isSubTask: %s, disableTools: %s',
126
+ agentId,
127
+ ctx.scope,
128
+ isSubTask,
129
+ disableTools,
130
+ );
131
+
132
+ // Helper to apply plugin filters:
133
+ // 1. If disableTools is true, return empty array (for broadcast scenarios)
134
+ // 2. If isSubTask is true, filter out lobe-gtd to prevent nested sub-task creation
135
+ const applyPluginFilters = (pluginIds: string[]) => {
136
+ if (disableTools) {
137
+ log('disableTools is true, returning empty plugins');
138
+ return [];
139
+ }
140
+ return isSubTask ? pluginIds.filter((id) => id !== 'lobe-gtd') : pluginIds;
141
+ };
122
142
 
123
143
  const agentStoreState = getAgentStoreState();
124
144
 
@@ -130,18 +150,18 @@ export const resolveAgentConfig = (ctx: AgentConfigResolverContext): ResolvedAge
130
150
  const basePlugins = agentConfig.plugins ?? [];
131
151
 
132
152
  // Check if this is a builtin agent
133
- // First check agent store, then check if this is a supervisor agent via groupId
134
- let slug = agentSelectors.getAgentSlugById(agentId)(agentStoreState);
135
- log('slug from agentStore: %s (agentId: %s)', slug, agentId);
153
+ // Priority: supervisor check (when in group scope) > agent store slug
154
+ let slug: string | undefined;
136
155
 
137
- // If not found in agent store, check if this is a supervisor agent using groupId
138
- // This is more reliable than iterating all groups to find a match
139
- if (!slug && ctx.groupId) {
156
+ // IMPORTANT: When in group scope with groupId, check if this agent is the group's supervisor FIRST
157
+ // This takes priority because supervisor needs special group-supervisor behavior,
158
+ // even if the agent has its own slug
159
+ if (ctx.groupId && ctx.scope === 'group') {
140
160
  const groupStoreState = getChatGroupStoreState();
141
161
  const group = agentGroupByIdSelectors.groupById(ctx.groupId)(groupStoreState);
142
162
 
143
163
  log(
144
- 'checking supervisor via groupId %s: group=%o',
164
+ 'checking supervisor FIRST (scope=group): groupId=%s, group=%O, agentId=%s',
145
165
  ctx.groupId,
146
166
  group
147
167
  ? {
@@ -150,6 +170,7 @@ export const resolveAgentConfig = (ctx: AgentConfigResolverContext): ResolvedAge
150
170
  title: group.title,
151
171
  }
152
172
  : null,
173
+ agentId,
153
174
  );
154
175
 
155
176
  // Check if this agent is the supervisor of the specified group
@@ -164,6 +185,12 @@ export const resolveAgentConfig = (ctx: AgentConfigResolverContext): ResolvedAge
164
185
  }
165
186
  }
166
187
 
188
+ // If not identified as supervisor, check agent store for slug
189
+ if (!slug) {
190
+ slug = agentSelectors.getAgentSlugById(agentId)(agentStoreState) ?? undefined;
191
+ log('slug from agentStore: %s (agentId: %s)', slug, agentId);
192
+ }
193
+
167
194
  if (!slug) {
168
195
  log('agentId %s is not a builtin agent (no slug found)', agentId);
169
196
  // Regular agent - use provided plugins if available, fallback to agent's plugins
@@ -209,7 +236,7 @@ export const resolveAgentConfig = (ctx: AgentConfigResolverContext): ResolvedAge
209
236
  agentConfig: finalAgentConfig,
210
237
  chatConfig: finalChatConfig,
211
238
  isBuiltinAgent: false,
212
- plugins: applySubTaskFilter(pageAgentPlugins),
239
+ plugins: applyPluginFilters(pageAgentPlugins),
213
240
  };
214
241
  }
215
242
 
@@ -218,7 +245,7 @@ export const resolveAgentConfig = (ctx: AgentConfigResolverContext): ResolvedAge
218
245
  agentConfig: finalAgentConfig,
219
246
  chatConfig: finalChatConfig,
220
247
  isBuiltinAgent: false,
221
- plugins: applySubTaskFilter(finalPlugins),
248
+ plugins: applyPluginFilters(finalPlugins),
222
249
  };
223
250
  }
224
251
 
@@ -339,7 +366,7 @@ export const resolveAgentConfig = (ctx: AgentConfigResolverContext): ResolvedAge
339
366
  agentConfig: finalAgentConfig,
340
367
  chatConfig: resolvedChatConfig,
341
368
  isBuiltinAgent: true,
342
- plugins: applySubTaskFilter(finalPlugins),
369
+ plugins: applyPluginFilters(finalPlugins),
343
370
  slug,
344
371
  };
345
372
  };