@lobehub/lobehub 2.0.0-next.337 → 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 (270) hide show
  1. package/.gitattributes +35 -0
  2. package/CHANGELOG.md +69 -0
  3. package/changelog/v1.json +24 -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 +97 -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/auth.json +1 -0
  57. package/locales/zh-CN/plugin.json +12 -2
  58. package/locales/zh-CN/providers.json +1 -0
  59. package/locales/zh-CN/setting.json +97 -2
  60. package/locales/zh-TW/plugin.json +12 -2
  61. package/locales/zh-TW/providers.json +1 -0
  62. package/locales/zh-TW/setting.json +78 -2
  63. package/package.json +1 -1
  64. package/packages/agent-runtime/src/groupOrchestration/GroupOrchestrationSupervisor.ts +2 -0
  65. package/packages/agent-runtime/src/groupOrchestration/__tests__/GroupOrchestrationSupervisor.test.ts +3 -1
  66. package/packages/agent-runtime/src/groupOrchestration/types.ts +5 -0
  67. package/packages/const/src/index.ts +1 -0
  68. package/packages/const/src/klavis.ts +144 -0
  69. package/packages/const/src/lobehubSkill.ts +34 -0
  70. package/packages/const/src/recommendedSkill.ts +17 -0
  71. package/packages/model-runtime/src/core/contextBuilders/anthropic.test.ts +38 -0
  72. package/packages/model-runtime/src/core/contextBuilders/anthropic.ts +20 -1
  73. package/packages/model-runtime/src/core/contextBuilders/google.test.ts +42 -0
  74. package/packages/model-runtime/src/core/contextBuilders/google.ts +17 -0
  75. package/packages/model-runtime/src/providers/google/index.ts +14 -14
  76. package/packages/model-runtime/src/providers/moonshot/index.ts +1 -1
  77. package/packages/model-runtime/src/providers/openai/index.ts +3 -3
  78. package/packages/types/src/discover/index.ts +1 -1
  79. package/scripts/electronWorkflow/modifiers/dynamicToStatic.mts +273 -0
  80. package/scripts/electronWorkflow/modifiers/index.mts +10 -0
  81. package/scripts/electronWorkflow/modifiers/nextConfig.mts +1 -0
  82. package/scripts/electronWorkflow/modifiers/nextDynamicToStatic.mts +233 -0
  83. package/scripts/electronWorkflow/modifiers/removeSuspense.mts +124 -0
  84. package/scripts/electronWorkflow/modifiers/routes.mts +14 -2
  85. package/scripts/electronWorkflow/modifiers/settingsContentToStatic.mts +148 -0
  86. package/scripts/electronWorkflow/modifiers/wrapChildrenWithClientOnly.mts +73 -0
  87. package/src/app/[variants]/(main)/agent/cron/[cronId]/CronConfig.ts +16 -16
  88. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobSaveButton.tsx +1 -1
  89. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobScheduleConfig.tsx +5 -2
  90. package/src/app/[variants]/(main)/community/features/Search.tsx +1 -1
  91. package/src/app/[variants]/(main)/home/features/InputArea/SkillInstallBanner.tsx +131 -0
  92. package/src/app/[variants]/(main)/home/features/InputArea/index.tsx +34 -27
  93. package/src/app/[variants]/(main)/settings/features/SettingHeader.tsx +8 -4
  94. package/src/app/[variants]/(main)/settings/features/SettingsContent.tsx +3 -0
  95. package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +6 -0
  96. package/src/{features/PluginStore/InstalledList/List/Item/Action.tsx → app/[variants]/(main)/settings/skill/features/Actions.tsx} +45 -40
  97. package/src/app/[variants]/(main)/settings/skill/features/KlavisSkillItem.tsx +353 -0
  98. package/src/app/[variants]/(main)/settings/skill/features/LobehubSkillItem.tsx +344 -0
  99. package/src/app/[variants]/(main)/settings/skill/features/McpSkillItem.tsx +116 -0
  100. package/src/app/[variants]/(main)/settings/skill/features/SkillList.tsx +244 -0
  101. package/src/app/[variants]/(main)/settings/skill/index.tsx +35 -0
  102. package/src/app/[variants]/(mobile)/router/mobileRouter.config.tsx +27 -0
  103. package/src/app/[variants]/(mobile)/settings/_layout/Header.tsx +8 -17
  104. package/src/app/[variants]/(mobile)/settings/_layout/index.tsx +6 -1
  105. package/src/app/[variants]/(mobile)/settings/provider/_layout/index.tsx +22 -0
  106. package/src/components/Plugins/PluginTag.tsx +23 -35
  107. package/src/components/client/ClientOnly.tsx +6 -2
  108. package/src/features/AgentSetting/AgentPlugin/index.tsx +2 -2
  109. package/src/features/ChatInput/ActionBar/Tools/KlavisServerItem.tsx +8 -32
  110. package/src/features/ChatInput/ActionBar/Tools/LobehubSkillServerItem.tsx +8 -30
  111. package/src/features/ChatInput/ActionBar/Tools/PopoverContent.tsx +48 -59
  112. package/src/features/ChatInput/ActionBar/Tools/index.tsx +5 -23
  113. package/src/features/ChatInput/ActionBar/Tools/useControls.tsx +158 -56
  114. package/src/features/IntegrationDetailModal/index.tsx +293 -0
  115. package/src/features/{PluginStore/McpList/Detail → MCP/MCPDetail}/index.tsx +15 -6
  116. package/src/features/MCP/MCPSettings/McpSettingsModal.tsx +58 -0
  117. package/src/features/{PluginStore/McpList/Detail/Settings → MCP/MCPSettings}/index.tsx +39 -27
  118. package/src/features/PluginDetailModal/index.tsx +2 -2
  119. package/src/features/PluginDevModal/index.tsx +16 -40
  120. package/src/features/ProfileEditor/AgentTool.tsx +2 -2
  121. package/src/features/ProtocolUrlHandler/InstallPlugin/OfficialPluginInstallModal/index.tsx +1 -1
  122. package/src/features/{PluginStore/AddPluginButton.tsx → SkillStore/AddSkillButton.tsx} +3 -3
  123. package/src/features/SkillStore/CommunityList/Item.tsx +158 -0
  124. package/src/features/SkillStore/CommunityList/index.tsx +101 -0
  125. package/src/features/SkillStore/Content.tsx +59 -0
  126. package/src/features/{PluginStore/PluginEmpty.tsx → SkillStore/Empty.tsx} +8 -8
  127. package/src/features/SkillStore/LobeHubList/Item.tsx +118 -0
  128. package/src/features/SkillStore/LobeHubList/index.tsx +187 -0
  129. package/src/features/SkillStore/LobeHubList/useSkillConnect.ts +239 -0
  130. package/src/features/SkillStore/Search/index.tsx +43 -0
  131. package/src/features/{PluginStore → SkillStore}/index.tsx +14 -10
  132. package/src/features/SkillStore/style.ts +27 -0
  133. package/src/locales/default/plugin.ts +15 -4
  134. package/src/locales/default/setting.ts +204 -2
  135. package/src/services/chat/mecha/agentConfigResolver.test.ts +197 -0
  136. package/src/services/chat/mecha/agentConfigResolver.ts +44 -17
  137. package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +40 -37
  138. package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +78 -0
  139. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +50 -16
  140. package/src/store/global/initialState.ts +1 -0
  141. package/src/store/tool/slices/lobehubSkillStore/action.test.ts +914 -0
  142. package/src/store/tool/slices/lobehubSkillStore/selectors.test.ts +548 -0
  143. package/.cursor/skills/vercel-react-best-practices/AGENTS.md +0 -2410
  144. package/.cursor/skills/vercel-react-best-practices/SKILL.md +0 -125
  145. package/.cursor/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  146. package/.cursor/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -49
  147. package/.cursor/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
  148. package/.cursor/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
  149. package/.cursor/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -36
  150. package/.cursor/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
  151. package/.cursor/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
  152. package/.cursor/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
  153. package/.cursor/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
  154. package/.cursor/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
  155. package/.cursor/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  156. package/.cursor/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
  157. package/.cursor/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
  158. package/.cursor/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
  159. package/.cursor/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
  160. package/.cursor/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
  161. package/.cursor/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -57
  162. package/.cursor/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
  163. package/.cursor/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
  164. package/.cursor/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
  165. package/.cursor/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
  166. package/.cursor/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
  167. package/.cursor/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
  168. package/.cursor/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
  169. package/.cursor/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
  170. package/.cursor/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
  171. package/.cursor/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
  172. package/.cursor/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
  173. package/.cursor/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
  174. package/.cursor/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  175. package/.cursor/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
  176. package/.cursor/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
  177. package/.cursor/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  178. package/.cursor/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  179. package/.cursor/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
  180. package/.cursor/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
  181. package/.cursor/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
  182. package/.cursor/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
  183. package/.cursor/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
  184. package/.cursor/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  185. package/.cursor/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
  186. package/.cursor/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
  187. package/.cursor/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
  188. package/.cursor/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
  189. package/.cursor/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
  190. package/.cursor/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
  191. package/.cursor/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
  192. package/src/features/PluginStore/Content.tsx +0 -54
  193. package/src/features/PluginStore/InstalledList/Detail/CustomPluginEmptyState.tsx +0 -79
  194. package/src/features/PluginStore/InstalledList/Detail/index.tsx +0 -21
  195. package/src/features/PluginStore/InstalledList/List/Item/index.tsx +0 -61
  196. package/src/features/PluginStore/InstalledList/List/index.tsx +0 -72
  197. package/src/features/PluginStore/InstalledList/index.tsx +0 -90
  198. package/src/features/PluginStore/McpList/List/Action.tsx +0 -119
  199. package/src/features/PluginStore/McpList/List/Item.tsx +0 -83
  200. package/src/features/PluginStore/McpList/List/index.tsx +0 -93
  201. package/src/features/PluginStore/McpList/index.tsx +0 -58
  202. package/src/features/PluginStore/PluginList/Detail/DetailProvider.tsx +0 -19
  203. package/src/features/PluginStore/PluginList/Detail/EmptyState.tsx +0 -56
  204. package/src/features/PluginStore/PluginList/Detail/Header.tsx +0 -130
  205. package/src/features/PluginStore/PluginList/Detail/InstallDetail/Nav.tsx +0 -73
  206. package/src/features/PluginStore/PluginList/Detail/InstallDetail/Settings.tsx +0 -19
  207. package/src/features/PluginStore/PluginList/Detail/InstallDetail/Tools.tsx +0 -111
  208. package/src/features/PluginStore/PluginList/Detail/InstallDetail/index.tsx +0 -24
  209. package/src/features/PluginStore/PluginList/Detail/Loading.tsx +0 -42
  210. package/src/features/PluginStore/PluginList/Detail/TagList.tsx +0 -35
  211. package/src/features/PluginStore/PluginList/Detail/index.tsx +0 -39
  212. package/src/features/PluginStore/PluginList/Detail/useCategory.tsx +0 -76
  213. package/src/features/PluginStore/PluginList/List/Action.tsx +0 -78
  214. package/src/features/PluginStore/PluginList/List/Item.tsx +0 -92
  215. package/src/features/PluginStore/PluginList/List/index.tsx +0 -94
  216. package/src/features/PluginStore/PluginList/index.tsx +0 -46
  217. package/src/features/PluginStore/Search/index.tsx +0 -40
  218. /package/{.codex/skills → .agents}/vercel-react-best-practices/AGENTS.md +0 -0
  219. /package/{.codex/skills → .agents}/vercel-react-best-practices/SKILL.md +0 -0
  220. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -0
  221. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/advanced-use-latest.md +0 -0
  222. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-api-routes.md +0 -0
  223. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-defer-await.md +0 -0
  224. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-dependencies.md +0 -0
  225. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-parallel.md +0 -0
  226. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -0
  227. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -0
  228. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-conditional.md +0 -0
  229. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -0
  230. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -0
  231. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-preload.md +0 -0
  232. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-event-listeners.md +0 -0
  233. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -0
  234. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -0
  235. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-swr-dedup.md +0 -0
  236. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -0
  237. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-cache-function-results.md +0 -0
  238. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-cache-property-access.md +0 -0
  239. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-cache-storage.md +0 -0
  240. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-combine-iterations.md +0 -0
  241. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-early-exit.md +0 -0
  242. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -0
  243. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-index-maps.md +0 -0
  244. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-length-check-first.md +0 -0
  245. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-min-max-loop.md +0 -0
  246. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -0
  247. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -0
  248. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-activity.md +0 -0
  249. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -0
  250. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -0
  251. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -0
  252. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -0
  253. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -0
  254. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -0
  255. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -0
  256. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-dependencies.md +0 -0
  257. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-derived-state.md +0 -0
  258. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -0
  259. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -0
  260. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-memo.md +0 -0
  261. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-transitions.md +0 -0
  262. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -0
  263. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-cache-lru.md +0 -0
  264. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-cache-react.md +0 -0
  265. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -0
  266. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-serialization.md +0 -0
  267. /package/src/{features/PluginStore/InstalledList → app/[variants]/(main)/settings/skill/features}/EditCustomPlugin.tsx +0 -0
  268. /package/src/features/{PluginStore/McpList/Detail → MCP/MCPDetail}/Loading.tsx +0 -0
  269. /package/src/features/{PluginStore → SkillStore}/Loading.tsx +0 -0
  270. /package/src/features/{PluginStore → SkillStore}/VirtuosoLoading.tsx +0 -0
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+
3
+ import { Button, Icon } from '@lobehub/ui';
4
+ import { Store } from 'lucide-react';
5
+ import { useState } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+
8
+ import SettingHeader from '@/app/[variants]/(main)/settings/features/SettingHeader';
9
+ import SkillStore from '@/features/SkillStore';
10
+
11
+ import SkillList from './features/SkillList';
12
+
13
+ const Page = () => {
14
+ const { t } = useTranslation('setting');
15
+ const [open, setOpen] = useState(false);
16
+
17
+ return (
18
+ <>
19
+ <SettingHeader
20
+ extra={
21
+ <Button icon={<Icon icon={Store} />} onClick={() => setOpen(true)}>
22
+ {t('skillStore.button')}
23
+ </Button>
24
+ }
25
+ title={t('tab.skill')}
26
+ />
27
+ <SkillList />
28
+ <SkillStore open={open} setOpen={setOpen} />
29
+ </>
30
+ );
31
+ };
32
+
33
+ Page.displayName = 'SkillsSetting';
34
+
35
+ export default Page;
@@ -7,6 +7,7 @@ import MobileChatLayout from '@/app/[variants]/(mobile)/chat/_layout';
7
7
  import MobileMeHomeLayout from '@/app/[variants]/(mobile)/me/(home)/layout';
8
8
  import MobileMeProfileLayout from '@/app/[variants]/(mobile)/me/profile/layout';
9
9
  import MobileMeSettingsLayout from '@/app/[variants]/(mobile)/me/settings/layout';
10
+ import MobileSettingsProviderLayout from '@/app/[variants]/(mobile)/settings/provider/_layout';
10
11
  import {
11
12
  BusinessMobileRoutesWithMainLayout,
12
13
  BusinessMobileRoutesWithoutMainLayout,
@@ -174,6 +175,32 @@ export const mobileRoutes: RouteConfig[] = [
174
175
  element: dynamicElement(() => import('../settings'), 'Mobile > Settings'),
175
176
  index: true,
176
177
  },
178
+ // Provider routes with nested structure
179
+ {
180
+ children: [
181
+ {
182
+ element: redirectElement('/settings/provider/all'),
183
+ index: true,
184
+ },
185
+ {
186
+ element: dynamicElement(
187
+ () => import('../../(main)/settings/provider').then((m) => m.ProviderDetailPage),
188
+ 'Mobile > Settings > Provider > Detail',
189
+ ),
190
+ path: ':providerId',
191
+ },
192
+ ],
193
+ element: <MobileSettingsProviderLayout />,
194
+ path: 'provider',
195
+ },
196
+ // Other settings tabs (common, agent, memory, tts, about, etc.)
197
+ {
198
+ element: dynamicElement(
199
+ () => import('../../(main)/settings'),
200
+ 'Mobile > Settings > Tab',
201
+ ),
202
+ path: ':tab',
203
+ },
177
204
  ],
178
205
  element: <MobileSettingsLayout />,
179
206
  errorElement: <ErrorBoundary resetPath="/settings" />,
@@ -4,10 +4,9 @@ import { Flexbox } from '@lobehub/ui';
4
4
  import { ChatHeader } from '@lobehub/ui/mobile';
5
5
  import { memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
- import { useNavigate } from 'react-router-dom';
7
+ import { useNavigate, useParams } from 'react-router-dom';
8
8
 
9
9
  import { enableAuth } from '@/envs/auth';
10
- import { useQueryState } from '@/hooks/useQueryParam';
11
10
  import { useShowMobileWorkspace } from '@/hooks/useShowMobileWorkspace';
12
11
  import { type SettingsTabs } from '@/store/global/initialState';
13
12
  import { useSessionStore } from '@/store/session';
@@ -17,26 +16,16 @@ const Header = memo(() => {
17
16
  const { t } = useTranslation('setting');
18
17
  const showMobileWorkspace = useShowMobileWorkspace();
19
18
  const navigate = useNavigate();
20
- const [activeSettingsKey, setActiveSettingsKey] = useQueryState('active');
21
- const [providerName, setProviderName] = useQueryState('provider');
19
+ const params = useParams<{ providerId?: string, tab?: string; }>();
22
20
 
23
21
  const isSessionActive = useSessionStore((s) => !!s.activeId);
24
- const isProvider = providerName ? true : false;
22
+ const isProvider = params.providerId && params.providerId !== 'all';
25
23
 
26
24
  const handleBackClick = () => {
27
- console.log(
28
- 'gobackclick',
29
- isSessionActive,
30
- showMobileWorkspace,
31
- activeSettingsKey,
32
- providerName,
33
- );
34
25
  if (isSessionActive && showMobileWorkspace) {
35
26
  navigate('/agent');
36
- } else if (activeSettingsKey === 'provider' && providerName) {
37
- setProviderName(null);
38
- setActiveSettingsKey('provider');
39
- navigate(-1);
27
+ } else if (isProvider) {
28
+ navigate('/settings/provider/all');
40
29
  } else {
41
30
  navigate(enableAuth ? '/me/settings' : '/me');
42
31
  }
@@ -49,7 +38,9 @@ const Header = memo(() => {
49
38
  title={
50
39
  <Flexbox align={'center'} gap={8} horizontal>
51
40
  <span style={{ lineHeight: 1.2 }}>
52
- {isProvider ? providerName : t(`tab.${activeSettingsKey as SettingsTabs}` as any)}
41
+ {isProvider
42
+ ? params.providerId
43
+ : t(`tab.${(params.tab || 'all') as SettingsTabs}` as any)}
53
44
  </span>
54
45
  </Flexbox>
55
46
  }
@@ -3,7 +3,10 @@
3
3
  import { memo } from 'react';
4
4
  import { Outlet } from 'react-router-dom';
5
5
 
6
+ import MobileContentLayout from '@/components/server/MobileNavLayout';
7
+
6
8
  import SettingsContextProvider from '../../../(main)/settings/_layout/ContextProvider';
9
+ import Header from './Header';
7
10
 
8
11
  const MobileSettingsWrapper = memo(() => {
9
12
  return (
@@ -13,7 +16,9 @@ const MobileSettingsWrapper = memo(() => {
13
16
  showOpenAIProxyUrl: true,
14
17
  }}
15
18
  >
16
- <Outlet />
19
+ <MobileContentLayout header={<Header />}>
20
+ <Outlet />
21
+ </MobileContentLayout>
17
22
  </SettingsContextProvider>
18
23
  );
19
24
  });
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+
3
+ import { Outlet, useNavigate, useParams } from 'react-router-dom';
4
+
5
+ import ProviderMenu from '../../../../(main)/settings/provider/ProviderMenu';
6
+
7
+ const Layout = () => {
8
+ const params = useParams<{ providerId: string }>();
9
+ const navigate = useNavigate();
10
+
11
+ const handleProviderSelect = (providerKey: string) => {
12
+ navigate(`/settings/provider/${providerKey}`);
13
+ };
14
+
15
+ return params.providerId === 'all' ? (
16
+ <ProviderMenu mobile={true} onProviderSelect={handleProviderSelect} />
17
+ ) : (
18
+ <Outlet />
19
+ );
20
+ };
21
+
22
+ export default Layout;
@@ -3,8 +3,6 @@ import { BadgeCheck, CircleUser, Package } from 'lucide-react';
3
3
  import { memo } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
6
- import MCPTag from './MCPTag';
7
-
8
6
  interface PluginTagProps {
9
7
  author?: string;
10
8
  isMCP?: boolean;
@@ -13,38 +11,28 @@ interface PluginTagProps {
13
11
  type: 'builtin' | 'customPlugin' | 'plugin';
14
12
  }
15
13
 
16
- const PluginTag = memo<PluginTagProps>(
17
- ({ showIcon = true, author, type, showText = true, isMCP }) => {
18
- const { t } = useTranslation('plugin');
19
- const isCustom = type === 'customPlugin';
20
- const isOfficial = author === 'LobeHub';
21
-
22
- const customTag = (
23
- <Tag color={'warning'} icon={showIcon && <Icon icon={Package} />} size={'small'}>
24
- {t('store.customPlugin')}
25
- </Tag>
26
- );
27
-
28
- if (isMCP)
29
- return (
30
- <>
31
- <MCPTag showIcon={showIcon} showText={false} />
32
- {isCustom && customTag}
33
- </>
34
- );
35
-
36
- if (isCustom) return customTag;
37
-
38
- return (
39
- <Tag
40
- color={isOfficial ? 'success' : undefined}
41
- icon={showIcon && <Icon icon={isOfficial ? BadgeCheck : CircleUser} />}
42
- size={'small'}
43
- >
44
- {showText && (author || t('store.communityPlugin'))}
45
- </Tag>
46
- );
47
- },
48
- );
14
+ const PluginTag = memo<PluginTagProps>(({ showIcon = true, author, type, showText = true }) => {
15
+ const { t } = useTranslation('plugin');
16
+ const isCustom = type === 'customPlugin';
17
+ const isOfficial = author === 'LobeHub';
18
+
19
+ const customTag = (
20
+ <Tag color={'warning'} icon={showIcon && <Icon icon={Package} />} size={'small'}>
21
+ {t('store.customPlugin')}
22
+ </Tag>
23
+ );
24
+
25
+ if (isCustom) return customTag;
26
+
27
+ return (
28
+ <Tag
29
+ color={isOfficial ? 'success' : undefined}
30
+ icon={showIcon && <Icon icon={isOfficial ? BadgeCheck : CircleUser} />}
31
+ size={'small'}
32
+ >
33
+ {showText && (author || t('store.communityPlugin'))}
34
+ </Tag>
35
+ );
36
+ });
49
37
 
50
38
  export default PluginTag;
@@ -1,15 +1,19 @@
1
1
  'use client';
2
2
 
3
+ import type React from 'react';
3
4
  import { type FC, type PropsWithChildren, useEffect, useState } from 'react';
4
5
 
5
- const ClientOnly: FC<PropsWithChildren> = ({ children }) => {
6
+ const ClientOnly: FC<PropsWithChildren<{ fallback?: React.ReactNode }>> = ({
7
+ children,
8
+ fallback = null,
9
+ }) => {
6
10
  const [mounted, setMounted] = useState(false);
7
11
 
8
12
  useEffect(() => {
9
13
  setMounted(true);
10
14
  }, []);
11
15
 
12
- if (!mounted) return null;
16
+ if (!mounted) return fallback;
13
17
 
14
18
  return children;
15
19
  };
@@ -12,7 +12,7 @@ import { Link, useNavigate } from 'react-router-dom';
12
12
  import PluginAvatar from '@/components/Plugins/PluginAvatar';
13
13
  import PluginTag from '@/components/Plugins/PluginTag';
14
14
  import { FORM_STYLE } from '@/const/layoutTokens';
15
- import PluginStore from '@/features/PluginStore';
15
+ import SkillStore from '@/features/SkillStore';
16
16
  import { useFetchInstalledPlugins } from '@/hooks/useFetchInstalledPlugins';
17
17
  import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
18
18
  import { pluginHelpers, useToolStore } from '@/store/tool';
@@ -170,7 +170,7 @@ const AgentPlugin = memo(() => {
170
170
 
171
171
  return (
172
172
  <>
173
- <PluginStore open={showStore} setOpen={setShowStore} />
173
+ <SkillStore open={showStore} setOpen={setShowStore} />
174
174
  <Form items={[plugin]} itemsType={'group'} variant={'borderless'} {...FORM_STYLE} />
175
175
  </>
176
176
  );
@@ -1,5 +1,5 @@
1
1
  import { Checkbox, Flexbox, Icon } from '@lobehub/ui';
2
- import { Loader2, SquareArrowOutUpRight, Unplug } from 'lucide-react';
2
+ import { Loader2, SquareArrowOutUpRight } from 'lucide-react';
3
3
  import { memo, useCallback, useEffect, useRef, useState } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
@@ -42,7 +42,6 @@ const KlavisServerItem = memo<KlavisServerItemProps>(
42
42
  const userId = useUserStore(userProfileSelectors.userId);
43
43
  const createKlavisServer = useToolStore((s) => s.createKlavisServer);
44
44
  const refreshKlavisServerTools = useToolStore((s) => s.refreshKlavisServerTools);
45
- const removeKlavisServer = useToolStore((s) => s.removeKlavisServer);
46
45
 
47
46
  // 清理所有定时器
48
47
  const cleanup = useCallback(() => {
@@ -212,18 +211,6 @@ const KlavisServerItem = memo<KlavisServerItemProps>(
212
211
  setIsToggling(false);
213
212
  };
214
213
 
215
- const handleDisconnect = async () => {
216
- if (!server) return;
217
- setIsToggling(true);
218
- // 如果当前已启用,先禁用
219
- if (checked) {
220
- await togglePlugin(pluginId);
221
- }
222
- // 删除服务器(使用 identifier)
223
- await removeKlavisServer(server.identifier);
224
- setIsToggling(false);
225
- };
226
-
227
214
  // 渲染右侧控件
228
215
  const renderRightControl = () => {
229
216
  // 正在连接中
@@ -262,24 +249,13 @@ const KlavisServerItem = memo<KlavisServerItemProps>(
262
249
  return <Icon icon={Loader2} spin />;
263
250
  }
264
251
  return (
265
- <Flexbox align="center" gap={8} horizontal>
266
- <Icon
267
- icon={Unplug}
268
- onClick={(e) => {
269
- e.stopPropagation();
270
- handleDisconnect();
271
- }}
272
- size="small"
273
- style={{ cursor: 'pointer', opacity: 0.5 }}
274
- />
275
- <Checkbox
276
- checked={checked}
277
- onClick={(e) => {
278
- e.stopPropagation();
279
- handleToggle();
280
- }}
281
- />
282
- </Flexbox>
252
+ <Checkbox
253
+ checked={checked}
254
+ onClick={(e) => {
255
+ e.stopPropagation();
256
+ handleToggle();
257
+ }}
258
+ />
283
259
  );
284
260
  }
285
261
  case KlavisServerStatus.PENDING_AUTH: {
@@ -1,5 +1,5 @@
1
1
  import { Checkbox, Flexbox, Icon } from '@lobehub/ui';
2
- import { Loader2, SquareArrowOutUpRight, Unplug } from 'lucide-react';
2
+ import { Loader2, SquareArrowOutUpRight } from 'lucide-react';
3
3
  import { memo, useCallback, useEffect, useRef, useState } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
@@ -36,7 +36,6 @@ const LobehubSkillServerItem = memo<LobehubSkillServerItemProps>(({ provider, la
36
36
 
37
37
  const server = useToolStore(lobehubSkillStoreSelectors.getServerByIdentifier(provider));
38
38
  const checkStatus = useToolStore((s) => s.checkLobehubSkillStatus);
39
- const revokeConnect = useToolStore((s) => s.revokeLobehubSkill);
40
39
  const getAuthorizeUrl = useToolStore((s) => s.getLobehubSkillAuthorizeUrl);
41
40
 
42
41
  const cleanup = useCallback(() => {
@@ -196,16 +195,6 @@ const LobehubSkillServerItem = memo<LobehubSkillServerItemProps>(({ provider, la
196
195
  setIsToggling(false);
197
196
  };
198
197
 
199
- const handleDisconnect = async () => {
200
- if (!server) return;
201
- setIsToggling(true);
202
- if (checked) {
203
- await togglePlugin(pluginId);
204
- }
205
- await revokeConnect(server.identifier);
206
- setIsToggling(false);
207
- };
208
-
209
198
  const renderRightControl = () => {
210
199
  if (isConnecting) {
211
200
  return (
@@ -239,24 +228,13 @@ const LobehubSkillServerItem = memo<LobehubSkillServerItemProps>(({ provider, la
239
228
  return <Icon icon={Loader2} spin />;
240
229
  }
241
230
  return (
242
- <Flexbox align="center" gap={8} horizontal>
243
- <Icon
244
- icon={Unplug}
245
- onClick={(e) => {
246
- e.stopPropagation();
247
- handleDisconnect();
248
- }}
249
- size="small"
250
- style={{ cursor: 'pointer', opacity: 0.5 }}
251
- />
252
- <Checkbox
253
- checked={checked}
254
- onClick={(e) => {
255
- e.stopPropagation();
256
- handleToggle();
257
- }}
258
- />
259
- </Flexbox>
231
+ <Checkbox
232
+ checked={checked}
233
+ onClick={(e) => {
234
+ e.stopPropagation();
235
+ handleToggle();
236
+ }}
237
+ />
260
238
  );
261
239
  }
262
240
  case LobehubSkillStatus.CONNECTING: {
@@ -1,8 +1,9 @@
1
- import { Flexbox, Icon, type ItemType, Segmented, usePopoverContext } from '@lobehub/ui';
1
+ import { Flexbox, Icon, type ItemType, usePopoverContext } from '@lobehub/ui';
2
2
  import { createStaticStyles, cssVar } from 'antd-style';
3
- import { ChevronRight, Store } from 'lucide-react';
3
+ import { ChevronRight, Settings, Store } from 'lucide-react';
4
4
  import { memo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
+ import { useNavigate } from 'react-router-dom';
6
7
 
7
8
  import ToolsList, { toolsListStyles } from './ToolsList';
8
9
 
@@ -11,81 +12,69 @@ const styles = createStaticStyles(({ css }) => ({
11
12
  padding: 4px;
12
13
  border-block-start: 1px solid ${cssVar.colorBorderSecondary};
13
14
  `,
14
- header: css`
15
- padding: 8px;
16
- border-block-end: 1px solid ${cssVar.colorBorderSecondary};
17
- `,
18
15
  trailingIcon: css`
19
16
  opacity: 0.5;
20
17
  `,
21
18
  }));
22
19
 
23
- type TabType = 'all' | 'installed';
24
-
25
20
  interface PopoverContentProps {
26
- activeTab: TabType;
27
- currentItems: ItemType[];
28
21
  enableKlavis: boolean;
22
+ items: ItemType[];
29
23
  onOpenStore: () => void;
30
- onTabChange: (tab: TabType) => void;
31
24
  }
32
25
 
33
- const PopoverContent = memo<PopoverContentProps>(
34
- ({ activeTab, currentItems, enableKlavis, onTabChange, onOpenStore }) => {
35
- const { t } = useTranslation('setting');
26
+ const PopoverContent = memo<PopoverContentProps>(({ items, enableKlavis, onOpenStore }) => {
27
+ const { t } = useTranslation('setting');
28
+ const navigate = useNavigate();
36
29
 
37
- const { close: closePopover } = usePopoverContext();
30
+ const { close: closePopover } = usePopoverContext();
38
31
 
39
- return (
40
- <Flexbox gap={0}>
41
- <div className={styles.header}>
42
- <Segmented
43
- block
44
- onChange={(v) => onTabChange(v as TabType)}
45
- options={[
46
- {
47
- label: t('tools.tabs.all', { defaultValue: 'all' }),
48
- value: 'all',
49
- },
50
- {
51
- label: t('tools.tabs.installed', { defaultValue: 'Installed' }),
52
- value: 'installed',
53
- },
54
- ]}
55
- size="small"
56
- value={activeTab}
57
- />
58
- </div>
32
+ return (
33
+ <Flexbox gap={0}>
34
+ <div
35
+ style={{
36
+ maxHeight: 500,
37
+ minHeight: enableKlavis ? 500 : undefined,
38
+ overflowY: 'auto',
39
+ }}
40
+ >
41
+ <ToolsList items={items} />
42
+ </div>
43
+ <div className={styles.footer}>
59
44
  <div
60
- style={{
61
- maxHeight: 500,
62
- minHeight: enableKlavis ? 500 : undefined,
63
- overflowY: 'auto',
45
+ className={toolsListStyles.item}
46
+ onClick={() => {
47
+ closePopover();
48
+ onOpenStore();
64
49
  }}
50
+ role="button"
51
+ tabIndex={0}
65
52
  >
66
- <ToolsList items={currentItems} />
53
+ <div className={toolsListStyles.itemIcon}>
54
+ <Icon icon={Store} size={20} />
55
+ </div>
56
+ <div className={toolsListStyles.itemContent}>{t('tools.plugins.store')}</div>
57
+ <Icon className={styles.trailingIcon} icon={ChevronRight} size={16} />
67
58
  </div>
68
- <div className={styles.footer}>
69
- <div
70
- className={toolsListStyles.item}
71
- onClick={() => {
72
- closePopover();
73
- onOpenStore();
74
- }}
75
- role="button"
76
- tabIndex={0}
77
- >
78
- <div className={toolsListStyles.itemIcon}>
79
- <Icon icon={Store} size={20} />
80
- </div>
81
- <div className={toolsListStyles.itemContent}>{t('tools.plugins.store')}</div>
82
- <Icon className={styles.trailingIcon} icon={ChevronRight} size={16} />
59
+ <div
60
+ className={toolsListStyles.item}
61
+ onClick={() => {
62
+ closePopover();
63
+ navigate('/settings/skill');
64
+ }}
65
+ role="button"
66
+ tabIndex={0}
67
+ >
68
+ <div className={toolsListStyles.itemIcon}>
69
+ <Icon icon={Settings} size={20} />
83
70
  </div>
71
+ <div className={toolsListStyles.itemContent}>{t('tools.plugins.management')}</div>
72
+ <Icon className={styles.trailingIcon} icon={ChevronRight} size={16} />
84
73
  </div>
85
- </Flexbox>
86
- );
87
- },
88
- );
74
+ </div>
75
+ </Flexbox>
76
+ );
77
+ });
89
78
 
90
79
  PopoverContent.displayName = 'PopoverContent';
91
80
 
@@ -1,8 +1,8 @@
1
1
  import { Blocks } from 'lucide-react';
2
- import { Suspense, memo, useEffect, useRef, useState } from 'react';
2
+ import { Suspense, memo, useState } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
 
5
- import PluginStore from '@/features/PluginStore';
5
+ import SkillStore from '@/features/SkillStore';
6
6
  import { useModelSupportToolUse } from '@/hooks/useModelSupportToolUse';
7
7
  import { useAgentStore } from '@/store/agent';
8
8
  import { agentByIdSelectors } from '@/store/agent/selectors';
@@ -13,27 +13,15 @@ import Action from '../components/Action';
13
13
  import PopoverContent from './PopoverContent';
14
14
  import { useControls } from './useControls';
15
15
 
16
- type TabType = 'all' | 'installed';
17
-
18
16
  const Tools = memo(() => {
19
17
  const { t } = useTranslation('setting');
20
18
  const [modalOpen, setModalOpen] = useState(false);
21
19
  const [updating, setUpdating] = useState(false);
22
- const [activeTab, setActiveTab] = useState<TabType | null>(null);
23
- const { marketItems, installedPluginItems } = useControls({
20
+ const { marketItems } = useControls({
24
21
  setUpdating,
25
22
  });
26
23
 
27
24
  const enableKlavis = useServerConfigStore(serverConfigSelectors.enableKlavis);
28
- const isInitializedRef = useRef(false);
29
-
30
- // Set default tab based on installed plugins (only on first load)
31
- useEffect(() => {
32
- if (!isInitializedRef.current && installedPluginItems.length >= 0) {
33
- isInitializedRef.current = true;
34
- setActiveTab(installedPluginItems.length > 0 ? 'installed' : 'all');
35
- }
36
- }, [installedPluginItems.length]);
37
25
 
38
26
  const agentId = useAgentId();
39
27
  const model = useAgentStore((s) => agentByIdSelectors.getAgentModelById(agentId)(s));
@@ -44,10 +32,6 @@ const Tools = memo(() => {
44
32
  if (!enableFC)
45
33
  return <Action disabled icon={Blocks} showTooltip={true} title={t('tools.disabled')} />;
46
34
 
47
- // Use effective tab for display (default to market while initializing)
48
- const effectiveTab = activeTab ?? 'all';
49
- const currentItems = effectiveTab === 'all' ? marketItems : installedPluginItems;
50
-
51
35
  return (
52
36
  <Suspense fallback={<Action disabled icon={Blocks} title={t('tools.title')} />}>
53
37
  <Action
@@ -56,11 +40,9 @@ const Tools = memo(() => {
56
40
  popover={{
57
41
  content: (
58
42
  <PopoverContent
59
- activeTab={effectiveTab}
60
- currentItems={currentItems}
61
43
  enableKlavis={enableKlavis}
44
+ items={marketItems}
62
45
  onOpenStore={() => setModalOpen(true)}
63
- onTabChange={setActiveTab}
64
46
  />
65
47
  ),
66
48
  maxWidth: 320,
@@ -74,7 +56,7 @@ const Tools = memo(() => {
74
56
  showTooltip={false}
75
57
  title={t('tools.title')}
76
58
  />
77
- <PluginStore open={modalOpen} setOpen={setModalOpen} />
59
+ <SkillStore open={modalOpen} setOpen={setModalOpen} />
78
60
  </Suspense>
79
61
  );
80
62
  });