@lobehub/lobehub 2.0.0-next.367 → 2.0.0-next.369
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/locales/ar/auth.json +2 -1
- package/locales/ar/models.json +6 -14
- package/locales/ar/providers.json +1 -0
- package/locales/ar/setting.json +1 -0
- package/locales/bg-BG/auth.json +2 -1
- package/locales/bg-BG/models.json +33 -7
- package/locales/bg-BG/providers.json +1 -0
- package/locales/bg-BG/setting.json +1 -0
- package/locales/de-DE/auth.json +2 -1
- package/locales/de-DE/models.json +32 -14
- package/locales/de-DE/providers.json +1 -0
- package/locales/de-DE/setting.json +1 -0
- package/locales/en-US/auth.json +1 -1
- package/locales/en-US/models.json +16 -15
- package/locales/en-US/providers.json +1 -0
- package/locales/en-US/setting.json +1 -0
- package/locales/es-ES/auth.json +2 -1
- package/locales/es-ES/models.json +5 -13
- package/locales/es-ES/providers.json +1 -0
- package/locales/es-ES/setting.json +1 -0
- package/locales/fa-IR/auth.json +2 -1
- package/locales/fa-IR/models.json +38 -12
- package/locales/fa-IR/providers.json +1 -0
- package/locales/fa-IR/setting.json +1 -0
- package/locales/fr-FR/auth.json +2 -1
- package/locales/fr-FR/models.json +43 -15
- package/locales/fr-FR/providers.json +1 -0
- package/locales/fr-FR/setting.json +1 -0
- package/locales/it-IT/auth.json +2 -1
- package/locales/it-IT/models.json +51 -10
- package/locales/it-IT/providers.json +1 -0
- package/locales/it-IT/setting.json +1 -0
- package/locales/ja-JP/auth.json +2 -1
- package/locales/ja-JP/models.json +33 -15
- package/locales/ja-JP/providers.json +1 -0
- package/locales/ja-JP/setting.json +1 -0
- package/locales/ko-KR/auth.json +2 -1
- package/locales/ko-KR/models.json +47 -8
- package/locales/ko-KR/providers.json +1 -0
- package/locales/ko-KR/setting.json +1 -0
- package/locales/nl-NL/auth.json +2 -1
- package/locales/nl-NL/models.json +5 -13
- package/locales/nl-NL/providers.json +1 -0
- package/locales/nl-NL/setting.json +1 -0
- package/locales/pl-PL/auth.json +2 -1
- package/locales/pl-PL/models.json +35 -13
- package/locales/pl-PL/providers.json +1 -0
- package/locales/pl-PL/setting.json +1 -0
- package/locales/pt-BR/auth.json +2 -1
- package/locales/pt-BR/models.json +50 -13
- package/locales/pt-BR/providers.json +1 -0
- package/locales/pt-BR/setting.json +1 -0
- package/locales/ru-RU/auth.json +2 -1
- package/locales/ru-RU/models.json +6 -9
- package/locales/ru-RU/providers.json +1 -0
- package/locales/ru-RU/setting.json +1 -0
- package/locales/tr-TR/auth.json +2 -1
- package/locales/tr-TR/models.json +49 -15
- package/locales/tr-TR/providers.json +1 -0
- package/locales/tr-TR/setting.json +1 -0
- package/locales/vi-VN/auth.json +2 -1
- package/locales/vi-VN/models.json +34 -7
- package/locales/vi-VN/providers.json +1 -0
- package/locales/vi-VN/setting.json +1 -0
- package/locales/zh-CN/auth.json +1 -1
- package/locales/zh-CN/models.json +48 -12
- package/locales/zh-CN/providers.json +1 -0
- package/locales/zh-CN/setting.json +1 -0
- package/locales/zh-TW/auth.json +2 -1
- package/locales/zh-TW/models.json +31 -14
- package/locales/zh-TW/providers.json +1 -0
- package/locales/zh-TW/setting.json +1 -0
- package/package.json +1 -1
- package/packages/types/src/agentGroup/index.ts +4 -0
- package/src/app/[variants]/(main)/agent/profile/features/Header/AgentForkTag.tsx +86 -0
- package/src/app/[variants]/(main)/agent/profile/features/Header/AgentStatusTag.tsx +82 -0
- package/src/app/[variants]/(main)/agent/profile/features/ProfileEditor/AgentHeader.tsx +27 -15
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/ForkGroupAndChat.tsx +1 -0
- package/src/app/[variants]/(main)/group/profile/features/GroupProfile/GroupForkTag.tsx +80 -0
- package/src/app/[variants]/(main)/group/profile/features/GroupProfile/GroupHeader.tsx +27 -15
- package/src/app/[variants]/(main)/group/profile/features/GroupProfile/GroupStatusTag.tsx +83 -0
- package/src/app/[variants]/(main)/settings/skill/features/Actions.tsx +0 -3
- package/src/app/[variants]/(main)/settings/skill/features/McpSkillItem.tsx +9 -3
- package/src/app/[variants]/(main)/settings/skill/features/SkillList.tsx +35 -1
- package/src/components/Plugins/PluginTag.tsx +36 -23
- package/src/features/ChatInput/ActionBar/Tools/PopoverContent.tsx +3 -3
- package/src/features/ChatInput/ActionBar/Tools/useControls.tsx +96 -78
- package/src/features/PluginDetailModal/index.tsx +1 -0
- package/src/features/ProfileEditor/AgentTool.tsx +141 -126
- package/src/features/ProfileEditor/Empty.tsx +22 -0
- package/src/features/ProfileEditor/PluginTag.tsx +33 -7
- package/src/features/ProfileEditor/PopoverContent.tsx +142 -0
- package/src/features/SkillStore/CommunityList/Item.tsx +5 -2
- package/src/features/SkillStore/CustomList/Item.tsx +149 -0
- package/src/features/SkillStore/CustomList/index.tsx +71 -0
- package/src/features/SkillStore/Empty.tsx +3 -0
- package/src/features/SkillStore/Search/index.tsx +5 -0
- package/src/features/SkillStore/SkillStoreContent.tsx +10 -2
- package/src/features/SkillStore/index.tsx +8 -1
- package/src/libs/trpc/lambda/middleware/marketUserInfo.ts +13 -1
- package/src/locales/default/setting.ts +1 -0
- package/src/services/marketApi.ts +1 -1
- package/src/store/agentGroup/selectors/byId.ts +1 -0
- package/src/store/tool/slices/customPlugin/initialState.ts +2 -0
- package/src/store/tool/slices/mcpStore/action.ts +1 -0
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
RECOMMENDED_SKILLS,
|
|
7
7
|
RecommendedSkillType,
|
|
8
8
|
} from '@lobechat/const';
|
|
9
|
-
import { Avatar,
|
|
9
|
+
import { Avatar, Icon, Image, type ItemType } from '@lobehub/ui';
|
|
10
10
|
import { cssVar } from 'antd-style';
|
|
11
11
|
import isEqual from 'fast-deep-equal';
|
|
12
12
|
import { ToyBrick } from 'lucide-react';
|
|
@@ -72,12 +72,6 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean)
|
|
|
72
72
|
s.togglePlugin,
|
|
73
73
|
]);
|
|
74
74
|
const builtinList = useToolStore(builtinToolSelectors.metaList, isEqual);
|
|
75
|
-
const enablePluginCount = useAgentStore(
|
|
76
|
-
(s) =>
|
|
77
|
-
agentByIdSelectors
|
|
78
|
-
.getAgentPluginsById(agentId)(s)
|
|
79
|
-
.filter((i) => !builtinList.some((b) => b.identifier === i)).length,
|
|
80
|
-
);
|
|
81
75
|
const plugins = useAgentStore((s) => agentByIdSelectors.getAgentPluginsById(agentId)(s));
|
|
82
76
|
|
|
83
77
|
// Klavis 相关状态
|
|
@@ -219,10 +213,21 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean)
|
|
|
219
213
|
);
|
|
220
214
|
|
|
221
215
|
// Skills 列表项(包含 LobeHub Skill 和 Klavis)
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
[lobehubSkillItems, klavisServerItems]
|
|
225
|
-
|
|
216
|
+
// 已连接的排在前面
|
|
217
|
+
const skillItems = useMemo(() => {
|
|
218
|
+
const allItems = [...lobehubSkillItems, ...klavisServerItems];
|
|
219
|
+
|
|
220
|
+
return allItems.sort((a, b) => {
|
|
221
|
+
const isConnectedA =
|
|
222
|
+
installedLobehubIds.has(a.key as string) || installedKlavisIds.has(a.key as string);
|
|
223
|
+
const isConnectedB =
|
|
224
|
+
installedLobehubIds.has(b.key as string) || installedKlavisIds.has(b.key as string);
|
|
225
|
+
|
|
226
|
+
if (isConnectedA && !isConnectedB) return -1;
|
|
227
|
+
if (!isConnectedA && isConnectedB) return 1;
|
|
228
|
+
return 0;
|
|
229
|
+
});
|
|
230
|
+
}, [lobehubSkillItems, klavisServerItems, installedLobehubIds, installedKlavisIds]);
|
|
226
231
|
|
|
227
232
|
// 区分社区插件和自定义插件
|
|
228
233
|
const communityPlugins = list.filter((item) => item.type !== 'customPlugin');
|
|
@@ -250,47 +255,55 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean)
|
|
|
250
255
|
),
|
|
251
256
|
});
|
|
252
257
|
|
|
253
|
-
// 构建
|
|
254
|
-
const
|
|
255
|
-
// 1.
|
|
258
|
+
// 构建 LobeHub 分组的 children(包含内置工具和 LobeHub Skill/Klavis)
|
|
259
|
+
const lobehubGroupChildren: ItemType[] = [
|
|
260
|
+
// 1. 内置工具
|
|
261
|
+
...builtinItems,
|
|
262
|
+
// 2. LobeHub Skill 和 Klavis(作为内置技能)
|
|
256
263
|
...skillItems,
|
|
257
|
-
// 2. divider (如果有 skillItems 且有社区插件)
|
|
258
|
-
...(skillItems.length > 0 && communityPlugins.length > 0
|
|
259
|
-
? [{ key: 'divider-skill-community', type: 'divider' as const }]
|
|
260
|
-
: []),
|
|
261
|
-
// 3. 社区插件
|
|
262
|
-
...communityPlugins.map(mapPluginToItem),
|
|
263
|
-
// 4. divider (如果有自定义插件)
|
|
264
|
-
...(customPlugins.length > 0
|
|
265
|
-
? [{ key: 'divider-community-custom', type: 'divider' as const }]
|
|
266
|
-
: []),
|
|
267
|
-
// 5. 自定义插件
|
|
268
|
-
...customPlugins.map(mapPluginToItem),
|
|
269
264
|
];
|
|
270
265
|
|
|
266
|
+
// 构建 Community 分组的 children(只包含社区插件)
|
|
267
|
+
const communityGroupChildren: ItemType[] = communityPlugins.map(mapPluginToItem);
|
|
268
|
+
|
|
269
|
+
// 构建 Custom 分组的 children(只包含自定义插件)
|
|
270
|
+
const customGroupChildren: ItemType[] = customPlugins.map(mapPluginToItem);
|
|
271
|
+
|
|
271
272
|
// 市场 tab 的 items
|
|
272
273
|
const marketItems: ItemType[] = [
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
274
|
+
// LobeHub 分组
|
|
275
|
+
...(lobehubGroupChildren.length > 0
|
|
276
|
+
? [
|
|
277
|
+
{
|
|
278
|
+
children: lobehubGroupChildren,
|
|
279
|
+
key: 'lobehub',
|
|
280
|
+
label: t('skillStore.tabs.lobehub'),
|
|
281
|
+
type: 'group' as const,
|
|
282
|
+
},
|
|
283
|
+
]
|
|
284
|
+
: []),
|
|
285
|
+
// Community 分组
|
|
286
|
+
...(communityGroupChildren.length > 0
|
|
287
|
+
? [
|
|
288
|
+
{
|
|
289
|
+
children: communityGroupChildren,
|
|
290
|
+
key: 'community',
|
|
291
|
+
label: t('skillStore.tabs.community'),
|
|
292
|
+
type: 'group' as const,
|
|
293
|
+
},
|
|
294
|
+
]
|
|
295
|
+
: []),
|
|
296
|
+
// Custom 分组(只有在有自定义插件时才显示)
|
|
297
|
+
...(customGroupChildren.length > 0
|
|
298
|
+
? [
|
|
299
|
+
{
|
|
300
|
+
children: customGroupChildren,
|
|
301
|
+
key: 'custom',
|
|
302
|
+
label: t('skillStore.tabs.custom'),
|
|
303
|
+
type: 'group' as const,
|
|
304
|
+
},
|
|
305
|
+
]
|
|
306
|
+
: []),
|
|
294
307
|
];
|
|
295
308
|
|
|
296
309
|
// 已安装 tab 的 items - 只显示已安装的插件
|
|
@@ -319,15 +332,6 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean)
|
|
|
319
332
|
),
|
|
320
333
|
}));
|
|
321
334
|
|
|
322
|
-
if (enabledBuiltinItems.length > 0) {
|
|
323
|
-
installedItems.push({
|
|
324
|
-
children: enabledBuiltinItems,
|
|
325
|
-
key: 'installed-builtins',
|
|
326
|
-
label: t('tools.builtins.groupName'),
|
|
327
|
-
type: 'group',
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
|
|
331
335
|
// 已连接的 Klavis 服务器
|
|
332
336
|
const connectedKlavisItems = klavisServerItems.filter((item) =>
|
|
333
337
|
checked.includes(item.key as string),
|
|
@@ -338,9 +342,30 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean)
|
|
|
338
342
|
checked.includes(item.key as string),
|
|
339
343
|
);
|
|
340
344
|
|
|
341
|
-
// 合并已启用的 LobeHub Skill 和 Klavis
|
|
345
|
+
// 合并已启用的 LobeHub Skill 和 Klavis(作为内置技能)
|
|
342
346
|
const enabledSkillItems = [...connectedLobehubSkillItems, ...connectedKlavisItems];
|
|
343
347
|
|
|
348
|
+
// 构建内置工具分组的 children(包含内置工具和 LobeHub Skill/Klavis)
|
|
349
|
+
const allBuiltinItems: ItemType[] = [
|
|
350
|
+
// 1. 内置工具
|
|
351
|
+
...enabledBuiltinItems,
|
|
352
|
+
// 2. divider (如果有内置工具且有 skill items)
|
|
353
|
+
...(enabledBuiltinItems.length > 0 && enabledSkillItems.length > 0
|
|
354
|
+
? [{ key: 'installed-divider-builtin-skill', type: 'divider' as const }]
|
|
355
|
+
: []),
|
|
356
|
+
// 3. LobeHub Skill 和 Klavis
|
|
357
|
+
...enabledSkillItems,
|
|
358
|
+
];
|
|
359
|
+
|
|
360
|
+
if (allBuiltinItems.length > 0) {
|
|
361
|
+
installedItems.push({
|
|
362
|
+
children: allBuiltinItems,
|
|
363
|
+
key: 'installed-lobehub',
|
|
364
|
+
label: t('skillStore.tabs.lobehub'),
|
|
365
|
+
type: 'group',
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
344
369
|
// 已启用的社区插件
|
|
345
370
|
const enabledCommunityPlugins = communityPlugins
|
|
346
371
|
.filter((item) => checked.includes(item.identifier))
|
|
@@ -389,29 +414,22 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean)
|
|
|
389
414
|
),
|
|
390
415
|
}));
|
|
391
416
|
|
|
392
|
-
//
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
...enabledCommunityPlugins,
|
|
402
|
-
// 4. divider (如果有自定义插件)
|
|
403
|
-
...(enabledCustomPlugins.length > 0
|
|
404
|
-
? [{ key: 'installed-divider-community-custom', type: 'divider' as const }]
|
|
405
|
-
: []),
|
|
406
|
-
// 5. 自定义插件
|
|
407
|
-
...enabledCustomPlugins,
|
|
408
|
-
];
|
|
417
|
+
// Community 分组(只包含社区插件)
|
|
418
|
+
if (enabledCommunityPlugins.length > 0) {
|
|
419
|
+
installedItems.push({
|
|
420
|
+
children: enabledCommunityPlugins,
|
|
421
|
+
key: 'installed-community',
|
|
422
|
+
label: t('skillStore.tabs.community'),
|
|
423
|
+
type: 'group',
|
|
424
|
+
});
|
|
425
|
+
}
|
|
409
426
|
|
|
410
|
-
|
|
427
|
+
// Custom 分组(只包含自定义插件)
|
|
428
|
+
if (enabledCustomPlugins.length > 0) {
|
|
411
429
|
installedItems.push({
|
|
412
|
-
children:
|
|
413
|
-
key: 'installed-
|
|
414
|
-
label: t('
|
|
430
|
+
children: enabledCustomPlugins,
|
|
431
|
+
key: 'installed-custom',
|
|
432
|
+
label: t('skillStore.tabs.custom'),
|
|
415
433
|
type: 'group',
|
|
416
434
|
});
|
|
417
435
|
}
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
LOBEHUB_SKILL_PROVIDERS,
|
|
7
7
|
type LobehubSkillProviderType,
|
|
8
8
|
} from '@lobechat/const';
|
|
9
|
-
import { Avatar, Button, Flexbox, Icon, type ItemType
|
|
9
|
+
import { Avatar, Button, Flexbox, Icon, type ItemType } from '@lobehub/ui';
|
|
10
10
|
import { createStaticStyles, cssVar } from 'antd-style';
|
|
11
11
|
import isEqual from 'fast-deep-equal';
|
|
12
|
-
import {
|
|
12
|
+
import { PlusIcon, ToyBrick } from 'lucide-react';
|
|
13
13
|
import React, { Suspense, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
14
14
|
import { useTranslation } from 'react-i18next';
|
|
15
15
|
|
|
@@ -34,29 +34,13 @@ import {
|
|
|
34
34
|
import { type LobeToolMetaWithAvailability } from '@/store/tool/slices/builtin/selectors';
|
|
35
35
|
|
|
36
36
|
import PluginTag from './PluginTag';
|
|
37
|
+
import PopoverContent from './PopoverContent';
|
|
37
38
|
|
|
38
39
|
const WEB_BROWSING_IDENTIFIER = 'lobe-web-browsing';
|
|
39
40
|
|
|
40
41
|
type TabType = 'all' | 'installed';
|
|
41
42
|
|
|
42
|
-
const prefixCls = 'ant';
|
|
43
|
-
|
|
44
43
|
const styles = createStaticStyles(({ css }) => ({
|
|
45
|
-
dropdown: css`
|
|
46
|
-
overflow: hidden;
|
|
47
|
-
width: 100%;
|
|
48
|
-
|
|
49
|
-
.${prefixCls}-dropdown-menu {
|
|
50
|
-
border-radius: 0 !important;
|
|
51
|
-
background: transparent !important;
|
|
52
|
-
box-shadow: none !important;
|
|
53
|
-
}
|
|
54
|
-
`,
|
|
55
|
-
header: css`
|
|
56
|
-
padding: ${cssVar.paddingXS};
|
|
57
|
-
border-block-end: 1px solid ${cssVar.colorBorderSecondary};
|
|
58
|
-
background: transparent;
|
|
59
|
-
`,
|
|
60
44
|
icon: css`
|
|
61
45
|
flex: none;
|
|
62
46
|
width: 18px;
|
|
@@ -152,6 +136,7 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
152
136
|
const isLobehubSkillEnabled = useServerConfigStore(serverConfigSelectors.enableLobehubSkill);
|
|
153
137
|
|
|
154
138
|
const [updating, setUpdating] = useState(false);
|
|
139
|
+
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
155
140
|
|
|
156
141
|
// Tab state for dual-column layout
|
|
157
142
|
const [activeTab, setActiveTab] = useState<TabType | null>(null);
|
|
@@ -227,10 +212,11 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
227
212
|
);
|
|
228
213
|
|
|
229
214
|
// Set default tab based on installed plugins (only on first load)
|
|
215
|
+
// Only show 'installed' tab by default if more than 5 plugins are enabled
|
|
230
216
|
useEffect(() => {
|
|
231
217
|
if (!isInitializedRef.current && plugins.length >= 0) {
|
|
232
218
|
isInitializedRef.current = true;
|
|
233
|
-
setActiveTab(plugins.length >
|
|
219
|
+
setActiveTab(plugins.length > 5 ? 'installed' : 'all');
|
|
234
220
|
}
|
|
235
221
|
}, [plugins.length]);
|
|
236
222
|
|
|
@@ -323,11 +309,6 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
323
309
|
}
|
|
324
310
|
};
|
|
325
311
|
|
|
326
|
-
// Build dropdown menu items (adapted from useControls)
|
|
327
|
-
const enablePluginCount = plugins.filter(
|
|
328
|
-
(id) => !builtinList.some((b) => b.identifier === id),
|
|
329
|
-
).length;
|
|
330
|
-
|
|
331
312
|
// 合并 builtin 工具、LobeHub Skill Providers 和 Klavis 服务器
|
|
332
313
|
const builtinItems = useMemo(
|
|
333
314
|
() => [
|
|
@@ -358,58 +339,85 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
358
339
|
[filteredBuiltinList, klavisServerItems, lobehubSkillItems, isToolEnabled, handleToggleTool],
|
|
359
340
|
);
|
|
360
341
|
|
|
361
|
-
//
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
342
|
+
// 区分社区插件和自定义插件
|
|
343
|
+
const communityPlugins = installedPluginList.filter((item) => item.type !== 'customPlugin');
|
|
344
|
+
const customPlugins = installedPluginList.filter((item) => item.type === 'customPlugin');
|
|
345
|
+
|
|
346
|
+
// 生成插件列表项的函数
|
|
347
|
+
const mapPluginToItem = useCallback(
|
|
348
|
+
(item: (typeof installedPluginList)[0]) => ({
|
|
349
|
+
icon: item?.avatar ? (
|
|
350
|
+
<PluginAvatar avatar={item.avatar} size={20} />
|
|
351
|
+
) : (
|
|
352
|
+
<Icon icon={ToyBrick} size={20} />
|
|
353
|
+
),
|
|
354
|
+
key: item.identifier,
|
|
355
|
+
label: (
|
|
356
|
+
<ToolItem
|
|
357
|
+
checked={plugins.includes(item.identifier)}
|
|
358
|
+
id={item.identifier}
|
|
359
|
+
label={item.title}
|
|
360
|
+
onUpdate={async () => {
|
|
361
|
+
setUpdating(true);
|
|
362
|
+
await togglePlugin(item.identifier);
|
|
363
|
+
setUpdating(false);
|
|
364
|
+
}}
|
|
365
|
+
/>
|
|
366
|
+
),
|
|
367
|
+
}),
|
|
368
|
+
[plugins, togglePlugin],
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
// Community 插件列表项
|
|
372
|
+
const communityPluginItems = useMemo(
|
|
373
|
+
() => communityPlugins.map(mapPluginToItem),
|
|
374
|
+
[communityPlugins, mapPluginToItem],
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
// Custom 插件列表项
|
|
378
|
+
const customPluginItems = useMemo(
|
|
379
|
+
() => customPlugins.map(mapPluginToItem),
|
|
380
|
+
[customPlugins, mapPluginToItem],
|
|
385
381
|
);
|
|
386
382
|
|
|
387
383
|
// All tab items (市场 tab)
|
|
388
384
|
const allTabItems: ItemType[] = useMemo(
|
|
389
385
|
() => [
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
386
|
+
// LobeHub 分组
|
|
387
|
+
...(builtinItems.length > 0
|
|
388
|
+
? [
|
|
389
|
+
{
|
|
390
|
+
children: builtinItems,
|
|
391
|
+
key: 'lobehub',
|
|
392
|
+
label: t('skillStore.tabs.lobehub'),
|
|
393
|
+
type: 'group' as const,
|
|
394
|
+
},
|
|
395
|
+
]
|
|
396
|
+
: []),
|
|
397
|
+
// Community 分组
|
|
398
|
+
...(communityPluginItems.length > 0
|
|
399
|
+
? [
|
|
400
|
+
{
|
|
401
|
+
children: communityPluginItems,
|
|
402
|
+
key: 'community',
|
|
403
|
+
label: t('skillStore.tabs.community'),
|
|
404
|
+
type: 'group' as const,
|
|
405
|
+
},
|
|
406
|
+
]
|
|
407
|
+
: []),
|
|
408
|
+
// Custom 分组
|
|
409
|
+
...(customPluginItems.length > 0
|
|
410
|
+
? [
|
|
411
|
+
{
|
|
412
|
+
children: customPluginItems,
|
|
413
|
+
key: 'custom',
|
|
414
|
+
label: t('skillStore.tabs.custom'),
|
|
415
|
+
type: 'group' as const,
|
|
416
|
+
},
|
|
417
|
+
]
|
|
418
|
+
: []),
|
|
411
419
|
],
|
|
412
|
-
[builtinItems,
|
|
420
|
+
[builtinItems, communityPluginItems, customPluginItems, t],
|
|
413
421
|
);
|
|
414
422
|
|
|
415
423
|
// Installed tab items - 只显示已启用的
|
|
@@ -446,24 +454,57 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
446
454
|
plugins.includes(item.key as string),
|
|
447
455
|
);
|
|
448
456
|
|
|
449
|
-
//
|
|
450
|
-
const
|
|
457
|
+
// LobeHub 分组(builtin + LobeHub Skill + Klavis)
|
|
458
|
+
const lobehubGroupItems = [
|
|
451
459
|
...enabledBuiltinItems,
|
|
452
|
-
...connectedKlavisItems,
|
|
453
460
|
...connectedLobehubSkillItems,
|
|
461
|
+
...connectedKlavisItems,
|
|
454
462
|
];
|
|
455
463
|
|
|
456
|
-
if (
|
|
464
|
+
if (lobehubGroupItems.length > 0) {
|
|
465
|
+
items.push({
|
|
466
|
+
children: lobehubGroupItems,
|
|
467
|
+
key: 'installed-lobehub',
|
|
468
|
+
label: t('skillStore.tabs.lobehub'),
|
|
469
|
+
type: 'group',
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// 已启用的社区插件
|
|
474
|
+
const enabledCommunityPlugins = communityPlugins
|
|
475
|
+
.filter((item) => plugins.includes(item.identifier))
|
|
476
|
+
.map((item) => ({
|
|
477
|
+
icon: item?.avatar ? (
|
|
478
|
+
<PluginAvatar avatar={item.avatar} size={20} />
|
|
479
|
+
) : (
|
|
480
|
+
<Icon icon={ToyBrick} size={20} />
|
|
481
|
+
),
|
|
482
|
+
key: item.identifier,
|
|
483
|
+
label: (
|
|
484
|
+
<ToolItem
|
|
485
|
+
checked={true}
|
|
486
|
+
id={item.identifier}
|
|
487
|
+
label={item.title}
|
|
488
|
+
onUpdate={async () => {
|
|
489
|
+
setUpdating(true);
|
|
490
|
+
await togglePlugin(item.identifier);
|
|
491
|
+
setUpdating(false);
|
|
492
|
+
}}
|
|
493
|
+
/>
|
|
494
|
+
),
|
|
495
|
+
}));
|
|
496
|
+
|
|
497
|
+
if (enabledCommunityPlugins.length > 0) {
|
|
457
498
|
items.push({
|
|
458
|
-
children:
|
|
459
|
-
key: 'installed-
|
|
460
|
-
label: t('
|
|
499
|
+
children: enabledCommunityPlugins,
|
|
500
|
+
key: 'installed-community',
|
|
501
|
+
label: t('skillStore.tabs.community'),
|
|
461
502
|
type: 'group',
|
|
462
503
|
});
|
|
463
504
|
}
|
|
464
505
|
|
|
465
|
-
//
|
|
466
|
-
const
|
|
506
|
+
// 已启用的自定义插件
|
|
507
|
+
const enabledCustomPlugins = customPlugins
|
|
467
508
|
.filter((item) => plugins.includes(item.identifier))
|
|
468
509
|
.map((item) => ({
|
|
469
510
|
icon: item?.avatar ? (
|
|
@@ -486,11 +527,11 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
486
527
|
),
|
|
487
528
|
}));
|
|
488
529
|
|
|
489
|
-
if (
|
|
530
|
+
if (enabledCustomPlugins.length > 0) {
|
|
490
531
|
items.push({
|
|
491
|
-
children:
|
|
492
|
-
key: 'installed-
|
|
493
|
-
label: t('
|
|
532
|
+
children: enabledCustomPlugins,
|
|
533
|
+
key: 'installed-custom',
|
|
534
|
+
label: t('skillStore.tabs.custom'),
|
|
494
535
|
type: 'group',
|
|
495
536
|
});
|
|
496
537
|
}
|
|
@@ -500,7 +541,8 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
500
541
|
filteredBuiltinList,
|
|
501
542
|
klavisServerItems,
|
|
502
543
|
lobehubSkillItems,
|
|
503
|
-
|
|
544
|
+
communityPlugins,
|
|
545
|
+
customPlugins,
|
|
504
546
|
plugins,
|
|
505
547
|
isToolEnabled,
|
|
506
548
|
handleToggleTool,
|
|
@@ -538,8 +580,8 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
538
580
|
<>
|
|
539
581
|
{/* Plugin Selector and Tags */}
|
|
540
582
|
<Flexbox align="center" gap={8} horizontal wrap={'wrap'}>
|
|
541
|
-
{/* Plugin Selector Dropdown - Using Action component pattern */}
|
|
542
583
|
<Suspense fallback={button}>
|
|
584
|
+
{/* Plugin Selector Dropdown - Using Action component pattern */}
|
|
543
585
|
<ActionDropdown
|
|
544
586
|
maxWidth={400}
|
|
545
587
|
menu={{
|
|
@@ -551,48 +593,21 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
551
593
|
},
|
|
552
594
|
}}
|
|
553
595
|
minWidth={400}
|
|
596
|
+
onOpenChange={setDropdownOpen}
|
|
597
|
+
open={dropdownOpen}
|
|
554
598
|
placement={'bottomLeft'}
|
|
555
599
|
popupRender={(menu) => (
|
|
556
|
-
<
|
|
557
|
-
{
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
{
|
|
568
|
-
label: t('tools.tabs.installed', { defaultValue: 'Installed' }),
|
|
569
|
-
value: 'installed',
|
|
570
|
-
},
|
|
571
|
-
]}
|
|
572
|
-
size="small"
|
|
573
|
-
value={effectiveTab}
|
|
574
|
-
/>
|
|
575
|
-
</div>
|
|
576
|
-
<div className={styles.scroller} style={{ flex: 1 }}>
|
|
577
|
-
{menu}
|
|
578
|
-
</div>
|
|
579
|
-
<Flexbox
|
|
580
|
-
align="center"
|
|
581
|
-
gap={8}
|
|
582
|
-
horizontal
|
|
583
|
-
onClick={() => createSkillStoreModal()}
|
|
584
|
-
style={{
|
|
585
|
-
borderBlockStart: `1px solid ${cssVar.colorBorderSecondary}`,
|
|
586
|
-
cursor: 'pointer',
|
|
587
|
-
flex: 'none',
|
|
588
|
-
padding: cssVar.paddingSM,
|
|
589
|
-
}}
|
|
590
|
-
>
|
|
591
|
-
<Icon icon={Store} />
|
|
592
|
-
<span style={{ flex: 1 }}>{t('tools.plugins.store')}</span>
|
|
593
|
-
<Icon icon={ArrowRight} />
|
|
594
|
-
</Flexbox>
|
|
595
|
-
</Flexbox>
|
|
600
|
+
<PopoverContent
|
|
601
|
+
activeTab={effectiveTab}
|
|
602
|
+
installedTabItems={installedTabItems}
|
|
603
|
+
menu={menu}
|
|
604
|
+
onClose={() => setDropdownOpen(false)}
|
|
605
|
+
onOpenStore={() => {
|
|
606
|
+
setDropdownOpen(false);
|
|
607
|
+
createSkillStoreModal()
|
|
608
|
+
}}
|
|
609
|
+
onTabChange={setActiveTab}
|
|
610
|
+
/>
|
|
596
611
|
)}
|
|
597
612
|
positionerProps={{
|
|
598
613
|
collisionAvoidance: { align: 'flip', fallbackAxisSide: 'end', side: 'flip' },
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Empty as EmptyComponent } from '@lobehub/ui';
|
|
2
|
+
import { Plug2 } from 'lucide-react';
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
|
|
6
|
+
const Empty = memo(() => {
|
|
7
|
+
const { t } = useTranslation('setting');
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<EmptyComponent
|
|
11
|
+
description={t('tools.installed.empty', {
|
|
12
|
+
defaultValue: 'No skills enabled',
|
|
13
|
+
})}
|
|
14
|
+
icon={Plug2}
|
|
15
|
+
style={{ paddingBlock: 40 }}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
Empty.displayName = 'ToolEmpty';
|
|
21
|
+
|
|
22
|
+
export default Empty;
|