@lobehub/lobehub 2.0.0-next.376 → 2.0.0-next.378
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 +67 -0
- package/changelog/v1.json +21 -0
- package/docs/development/database-schema.dbml +51 -0
- package/docs/self-hosting/advanced/auth/providers/casdoor.mdx +1 -1
- package/docs/self-hosting/advanced/auth/providers/casdoor.zh-CN.mdx +1 -1
- package/docs/self-hosting/advanced/auth/providers/logto.mdx +1 -1
- package/docs/self-hosting/advanced/auth/providers/logto.zh-CN.mdx +1 -1
- package/package.json +1 -2
- package/packages/database/migrations/0075_add_user_memory_persona.sql +51 -0
- package/packages/database/migrations/meta/0075_snapshot.json +11957 -0
- package/packages/database/migrations/meta/_journal.json +8 -1
- package/packages/database/src/schemas/userMemories/persona.ts +81 -0
- package/scripts/_shared/checkDeprecatedAuth.js +46 -16
- package/scripts/_shared/checkDeprecatedAuth.test.ts +180 -0
- package/src/app/(backend)/api/webhooks/casdoor/route.ts +1 -2
- package/src/app/(backend)/api/webhooks/logto/route.ts +2 -3
- package/src/app/(backend)/trpc/async/[trpc]/route.ts +1 -2
- package/src/app/(backend)/trpc/mobile/[trpc]/route.ts +1 -2
- package/src/app/[variants]/(main)/agent/profile/features/ProfileEditor/index.tsx +1 -0
- package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/AgentProfilePopup.tsx +9 -0
- package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/GroupMember.tsx +27 -2
- package/src/app/[variants]/(main)/home/_layout/Body/Agent/Actions.tsx +1 -1
- package/src/app/[variants]/(main)/home/features/InputArea/SkillInstallBanner.tsx +40 -32
- package/src/app/[variants]/(main)/memory/(home)/index.tsx +1 -1
- package/src/app/[variants]/(main)/memory/contexts/index.tsx +2 -0
- package/src/app/[variants]/(main)/memory/experiences/index.tsx +2 -0
- package/src/app/[variants]/(main)/memory/features/MemoryAnalysis/Action.tsx +13 -2
- package/src/app/[variants]/(main)/memory/features/MemoryAnalysis/AnalysisTrigger.tsx +26 -13
- package/src/app/[variants]/(main)/memory/features/MemoryAnalysis/index.tsx +10 -1
- package/src/app/[variants]/(main)/memory/identities/index.tsx +2 -0
- package/src/app/[variants]/(main)/memory/preferences/index.tsx +2 -0
- package/src/app/[variants]/(main)/resource/library/_layout/Header/LibraryHead.tsx +7 -3
- package/src/app/[variants]/(main)/settings/skill/features/KlavisSkillItem.tsx +30 -30
- package/src/app/[variants]/(main)/settings/skill/features/LobehubSkillItem.tsx +31 -31
- package/src/app/[variants]/(main)/settings/skill/index.tsx +2 -2
- package/src/components/FileParsingStatus/EmbeddingStatus.tsx +3 -16
- package/src/components/FileParsingStatus/index.tsx +2 -15
- package/src/features/ChatInput/ActionBar/Tools/PopoverContent.tsx +1 -3
- package/src/features/ChatInput/ActionBar/Tools/ToolsList.tsx +4 -0
- package/src/features/ChatInput/ActionBar/Tools/index.tsx +1 -10
- package/src/features/ChatInput/ActionBar/Tools/useControls.tsx +41 -16
- package/src/features/ChatInput/ActionBar/components/ActionDropdown.tsx +2 -1
- package/src/features/Conversation/ChatItem/components/Title.tsx +6 -2
- package/src/features/ModelSelect/index.tsx +10 -3
- package/src/features/ProfileEditor/AgentTool.tsx +52 -33
- package/src/features/ProfileEditor/PopoverContent.tsx +28 -61
- package/src/features/SharePopover/index.tsx +3 -3
- package/src/features/SkillStore/CommunityList/Item.tsx +2 -1
- package/src/features/SkillStore/CommunityList/index.tsx +16 -22
- package/src/features/SkillStore/CustomList/Item.tsx +2 -1
- package/src/features/SkillStore/CustomList/index.tsx +11 -31
- package/src/features/SkillStore/LobeHubList/Item.tsx +4 -3
- package/src/features/SkillStore/LobeHubList/index.tsx +2 -18
- package/src/features/SkillStore/Search/index.tsx +1 -1
- package/src/features/SkillStore/index.tsx +6 -3
- package/src/features/SkillStore/style.ts +34 -1
- package/src/libs/next/config/define-config.ts +0 -3
- package/src/server/routers/lambda/agent.ts +1 -2
- package/src/server/services/user/index.ts +1 -2
- package/src/server/services/webhookUser/index.test.ts +290 -0
- package/src/server/services/webhookUser/index.ts +29 -12
- package/src/libs/logger/index.ts +0 -5
|
@@ -18,12 +18,11 @@ const styles = createStaticStyles(({ css }) => ({
|
|
|
18
18
|
}));
|
|
19
19
|
|
|
20
20
|
interface PopoverContentProps {
|
|
21
|
-
enableKlavis: boolean;
|
|
22
21
|
items: ItemType[];
|
|
23
22
|
onOpenStore: () => void;
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
const PopoverContent = memo<PopoverContentProps>(({ items,
|
|
25
|
+
const PopoverContent = memo<PopoverContentProps>(({ items, onOpenStore }) => {
|
|
27
26
|
const { t } = useTranslation('setting');
|
|
28
27
|
const navigate = useNavigate();
|
|
29
28
|
|
|
@@ -34,7 +33,6 @@ const PopoverContent = memo<PopoverContentProps>(({ items, enableKlavis, onOpenS
|
|
|
34
33
|
<div
|
|
35
34
|
style={{
|
|
36
35
|
maxHeight: 500,
|
|
37
|
-
minHeight: enableKlavis ? 500 : undefined,
|
|
38
36
|
overflowY: 'auto',
|
|
39
37
|
}}
|
|
40
38
|
>
|
|
@@ -6,7 +6,6 @@ import { createSkillStoreModal } 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';
|
|
9
|
-
import { serverConfigSelectors, useServerConfigStore } from '@/store/serverConfig';
|
|
10
9
|
|
|
11
10
|
import { useAgentId } from '../../hooks/useAgentId';
|
|
12
11
|
import Action from '../components/Action';
|
|
@@ -20,8 +19,6 @@ const Tools = memo(() => {
|
|
|
20
19
|
setUpdating,
|
|
21
20
|
});
|
|
22
21
|
|
|
23
|
-
const enableKlavis = useServerConfigStore(serverConfigSelectors.enableKlavis);
|
|
24
|
-
|
|
25
22
|
const agentId = useAgentId();
|
|
26
23
|
const model = useAgentStore((s) => agentByIdSelectors.getAgentModelById(agentId)(s));
|
|
27
24
|
const provider = useAgentStore((s) => agentByIdSelectors.getAgentModelProviderById(agentId)(s));
|
|
@@ -41,13 +38,7 @@ const Tools = memo(() => {
|
|
|
41
38
|
icon={Blocks}
|
|
42
39
|
loading={updating}
|
|
43
40
|
popover={{
|
|
44
|
-
content:
|
|
45
|
-
<PopoverContent
|
|
46
|
-
enableKlavis={enableKlavis}
|
|
47
|
-
items={marketItems}
|
|
48
|
-
onOpenStore={handleOpenStore}
|
|
49
|
-
/>
|
|
50
|
-
),
|
|
41
|
+
content: <PopoverContent items={marketItems} onOpenStore={handleOpenStore} />,
|
|
51
42
|
maxWidth: 320,
|
|
52
43
|
minWidth: 320,
|
|
53
44
|
styles: {
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
RECOMMENDED_SKILLS,
|
|
7
7
|
RecommendedSkillType,
|
|
8
8
|
} from '@lobechat/const';
|
|
9
|
-
import { Avatar, Icon,
|
|
9
|
+
import { Avatar, Icon, 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';
|
|
@@ -32,18 +32,25 @@ import KlavisServerItem from './KlavisServerItem';
|
|
|
32
32
|
import LobehubSkillServerItem from './LobehubSkillServerItem';
|
|
33
33
|
import ToolItem from './ToolItem';
|
|
34
34
|
|
|
35
|
+
const SKILL_ICON_SIZE = 20;
|
|
36
|
+
|
|
35
37
|
/**
|
|
36
38
|
* Klavis 服务器图标组件
|
|
37
|
-
* 对于 string 类型的 icon,使用 Image 组件渲染
|
|
38
|
-
* 对于 IconType 类型的 icon,使用 Icon 组件渲染,并根据主题设置填充色
|
|
39
39
|
*/
|
|
40
40
|
const KlavisIcon = memo<Pick<KlavisServerType, 'icon' | 'label'>>(({ icon, label }) => {
|
|
41
41
|
if (typeof icon === 'string') {
|
|
42
|
-
return
|
|
42
|
+
return (
|
|
43
|
+
<Avatar
|
|
44
|
+
alt={label}
|
|
45
|
+
avatar={icon}
|
|
46
|
+
shape={'square'}
|
|
47
|
+
size={SKILL_ICON_SIZE}
|
|
48
|
+
style={{ flex: 'none' }}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
43
51
|
}
|
|
44
52
|
|
|
45
|
-
|
|
46
|
-
return <Icon fill={cssVar.colorText} icon={icon} size={18} />;
|
|
53
|
+
return <Icon fill={cssVar.colorText} icon={icon} size={SKILL_ICON_SIZE} />;
|
|
47
54
|
});
|
|
48
55
|
|
|
49
56
|
KlavisIcon.displayName = 'KlavisIcon';
|
|
@@ -54,10 +61,18 @@ KlavisIcon.displayName = 'KlavisIcon';
|
|
|
54
61
|
const LobehubSkillIcon = memo<Pick<LobehubSkillProviderType, 'icon' | 'label'>>(
|
|
55
62
|
({ icon, label }) => {
|
|
56
63
|
if (typeof icon === 'string') {
|
|
57
|
-
return
|
|
64
|
+
return (
|
|
65
|
+
<Avatar
|
|
66
|
+
alt={label}
|
|
67
|
+
avatar={icon}
|
|
68
|
+
shape={'square'}
|
|
69
|
+
size={SKILL_ICON_SIZE}
|
|
70
|
+
style={{ flex: 'none' }}
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
58
73
|
}
|
|
59
74
|
|
|
60
|
-
return <Icon fill={cssVar.colorText} icon={icon} size={
|
|
75
|
+
return <Icon fill={cssVar.colorText} icon={icon} size={SKILL_ICON_SIZE} />;
|
|
61
76
|
},
|
|
62
77
|
);
|
|
63
78
|
|
|
@@ -193,7 +208,12 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean)
|
|
|
193
208
|
() =>
|
|
194
209
|
filteredBuiltinList.map((item) => ({
|
|
195
210
|
icon: (
|
|
196
|
-
<Avatar
|
|
211
|
+
<Avatar
|
|
212
|
+
avatar={item.meta.avatar}
|
|
213
|
+
shape={'square'}
|
|
214
|
+
size={SKILL_ICON_SIZE}
|
|
215
|
+
style={{ flex: 'none' }}
|
|
216
|
+
/>
|
|
197
217
|
),
|
|
198
218
|
key: item.identifier,
|
|
199
219
|
label: (
|
|
@@ -236,9 +256,9 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean)
|
|
|
236
256
|
// 生成插件列表项的函数
|
|
237
257
|
const mapPluginToItem = (item: (typeof list)[0]) => ({
|
|
238
258
|
icon: item?.avatar ? (
|
|
239
|
-
<PluginAvatar avatar={item.avatar} size={
|
|
259
|
+
<PluginAvatar avatar={item.avatar} size={SKILL_ICON_SIZE} />
|
|
240
260
|
) : (
|
|
241
|
-
<Icon icon={ToyBrick} size={
|
|
261
|
+
<Icon icon={ToyBrick} size={SKILL_ICON_SIZE} />
|
|
242
262
|
),
|
|
243
263
|
key: item.identifier,
|
|
244
264
|
label: (
|
|
@@ -315,7 +335,12 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean)
|
|
|
315
335
|
.filter((item) => checked.includes(item.identifier))
|
|
316
336
|
.map((item) => ({
|
|
317
337
|
icon: (
|
|
318
|
-
<Avatar
|
|
338
|
+
<Avatar
|
|
339
|
+
avatar={item.meta.avatar}
|
|
340
|
+
shape={'square'}
|
|
341
|
+
size={SKILL_ICON_SIZE}
|
|
342
|
+
style={{ flex: 'none' }}
|
|
343
|
+
/>
|
|
319
344
|
),
|
|
320
345
|
key: item.identifier,
|
|
321
346
|
label: (
|
|
@@ -371,9 +396,9 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean)
|
|
|
371
396
|
.filter((item) => checked.includes(item.identifier))
|
|
372
397
|
.map((item) => ({
|
|
373
398
|
icon: item?.avatar ? (
|
|
374
|
-
<PluginAvatar avatar={item.avatar} size={
|
|
399
|
+
<PluginAvatar avatar={item.avatar} size={SKILL_ICON_SIZE} />
|
|
375
400
|
) : (
|
|
376
|
-
<Icon icon={ToyBrick} size={
|
|
401
|
+
<Icon icon={ToyBrick} size={SKILL_ICON_SIZE} />
|
|
377
402
|
),
|
|
378
403
|
key: item.identifier,
|
|
379
404
|
label: (
|
|
@@ -395,9 +420,9 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean)
|
|
|
395
420
|
.filter((item) => checked.includes(item.identifier))
|
|
396
421
|
.map((item) => ({
|
|
397
422
|
icon: item?.avatar ? (
|
|
398
|
-
<PluginAvatar avatar={item.avatar} size={
|
|
423
|
+
<PluginAvatar avatar={item.avatar} size={SKILL_ICON_SIZE} />
|
|
399
424
|
) : (
|
|
400
|
-
<Icon icon={ToyBrick} size={
|
|
425
|
+
<Icon icon={ToyBrick} size={SKILL_ICON_SIZE} />
|
|
401
426
|
),
|
|
402
427
|
key: item.identifier,
|
|
403
428
|
label: (
|
|
@@ -117,8 +117,9 @@ const ActionDropdown = memo<ActionDropdownProps>(
|
|
|
117
117
|
return trigger === 'hover';
|
|
118
118
|
}, [trigger]);
|
|
119
119
|
const resolvedTriggerProps = useMemo(() => {
|
|
120
|
-
if (openOnHover === undefined) return triggerProps;
|
|
120
|
+
if (openOnHover === undefined) return { nativeButton: false, ...triggerProps };
|
|
121
121
|
return {
|
|
122
|
+
nativeButton: false,
|
|
122
123
|
...triggerProps,
|
|
123
124
|
openOnHover,
|
|
124
125
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Text } from '@lobehub/ui';
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
import { memo } from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
4
5
|
|
|
5
6
|
import { type ChatItemProps } from '../type';
|
|
6
7
|
|
|
@@ -12,11 +13,14 @@ export interface TitleProps {
|
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
const Title = memo<TitleProps>(({ showTitle, time, avatar, titleAddon }) => {
|
|
16
|
+
const { t } = useTranslation('chat');
|
|
17
|
+
const title = avatar.title || t('untitledAgent');
|
|
18
|
+
|
|
15
19
|
return (
|
|
16
20
|
<>
|
|
17
|
-
{showTitle &&
|
|
21
|
+
{showTitle && (
|
|
18
22
|
<Text fontSize={14} weight={500}>
|
|
19
|
-
{
|
|
23
|
+
{title}
|
|
20
24
|
</Text>
|
|
21
25
|
)}
|
|
22
26
|
{showTitle ? titleAddon : undefined}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { LobeSelect, type LobeSelectProps, TooltipGroup } from '@lobehub/ui';
|
|
2
|
-
import {
|
|
2
|
+
import { createStyles } from 'antd-style';
|
|
3
3
|
import { type ReactNode, memo, useMemo } from 'react';
|
|
4
4
|
|
|
5
5
|
import { ModelItemRender, ProviderItemRender } from '@/components/ModelSelect';
|
|
6
6
|
import { useEnabledChatModels } from '@/hooks/useEnabledChatModels';
|
|
7
7
|
import { type EnabledProviderWithModels } from '@/types/aiProvider';
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const useStyles = createStyles(({ css }, { popupWidth }: { popupWidth?: number | string }) => ({
|
|
10
10
|
popup: css`
|
|
11
|
-
width:
|
|
11
|
+
width: ${popupWidth
|
|
12
|
+
? typeof popupWidth === 'number'
|
|
13
|
+
? `${popupWidth}px`
|
|
14
|
+
: popupWidth
|
|
15
|
+
: 'max(360px, var(--anchor-width))'};
|
|
12
16
|
`,
|
|
13
17
|
}));
|
|
14
18
|
|
|
@@ -27,6 +31,7 @@ interface ModelSelectProps extends Pick<LobeSelectProps, 'loading' | 'size' | 's
|
|
|
27
31
|
defaultValue?: { model: string; provider?: string };
|
|
28
32
|
initialWidth?: boolean;
|
|
29
33
|
onChange?: (props: { model: string; provider: string }) => void;
|
|
34
|
+
popupWidth?: number | string;
|
|
30
35
|
requiredAbilities?: (keyof EnabledProviderWithModels['children'][number]['abilities'])[];
|
|
31
36
|
showAbility?: boolean;
|
|
32
37
|
|
|
@@ -41,10 +46,12 @@ const ModelSelect = memo<ModelSelectProps>(
|
|
|
41
46
|
showAbility = true,
|
|
42
47
|
requiredAbilities,
|
|
43
48
|
loading,
|
|
49
|
+
popupWidth,
|
|
44
50
|
size,
|
|
45
51
|
style,
|
|
46
52
|
variant,
|
|
47
53
|
}) => {
|
|
54
|
+
const { styles } = useStyles({ popupWidth });
|
|
48
55
|
const enabledList = useEnabledChatModels();
|
|
49
56
|
|
|
50
57
|
const options = useMemo<LobeSelectProps['options']>(() => {
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type LobehubSkillProviderType,
|
|
8
8
|
} from '@lobechat/const';
|
|
9
9
|
import { Avatar, Button, Flexbox, Icon, type ItemType } from '@lobehub/ui';
|
|
10
|
-
import {
|
|
10
|
+
import { cssVar } from 'antd-style';
|
|
11
11
|
import isEqual from 'fast-deep-equal';
|
|
12
12
|
import { PlusIcon, ToyBrick } from 'lucide-react';
|
|
13
13
|
import React, { Suspense, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
@@ -40,30 +40,25 @@ const WEB_BROWSING_IDENTIFIER = 'lobe-web-browsing';
|
|
|
40
40
|
|
|
41
41
|
type TabType = 'all' | 'installed';
|
|
42
42
|
|
|
43
|
-
const
|
|
44
|
-
icon: css`
|
|
45
|
-
flex: none;
|
|
46
|
-
width: 18px;
|
|
47
|
-
height: 18px;
|
|
48
|
-
margin-inline-end: ${cssVar.marginXS};
|
|
49
|
-
`,
|
|
50
|
-
scroller: css`
|
|
51
|
-
overflow: hidden auto;
|
|
52
|
-
`,
|
|
53
|
-
}));
|
|
43
|
+
const SKILL_ICON_SIZE = 20;
|
|
54
44
|
|
|
55
45
|
/**
|
|
56
46
|
* Klavis 服务器图标组件
|
|
57
|
-
* 对于 string 类型的 icon,使用 Image 组件渲染
|
|
58
|
-
* 对于 IconType 类型的 icon,使用 Icon 组件渲染,并根据主题设置填充色
|
|
59
47
|
*/
|
|
60
48
|
const KlavisIcon = memo<Pick<KlavisServerType, 'icon' | 'label'>>(({ icon, label }) => {
|
|
61
49
|
if (typeof icon === 'string') {
|
|
62
|
-
return
|
|
50
|
+
return (
|
|
51
|
+
<Avatar
|
|
52
|
+
alt={label}
|
|
53
|
+
avatar={icon}
|
|
54
|
+
shape={'square'}
|
|
55
|
+
size={SKILL_ICON_SIZE}
|
|
56
|
+
style={{ flex: 'none' }}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
63
59
|
}
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
return <Icon className={styles.icon} fill={cssVar.colorText} icon={icon} size={18} />;
|
|
61
|
+
return <Icon fill={cssVar.colorText} icon={icon} size={SKILL_ICON_SIZE} />;
|
|
67
62
|
});
|
|
68
63
|
|
|
69
64
|
/**
|
|
@@ -72,10 +67,18 @@ const KlavisIcon = memo<Pick<KlavisServerType, 'icon' | 'label'>>(({ icon, label
|
|
|
72
67
|
const LobehubSkillIcon = memo<Pick<LobehubSkillProviderType, 'icon' | 'label'>>(
|
|
73
68
|
({ icon, label }) => {
|
|
74
69
|
if (typeof icon === 'string') {
|
|
75
|
-
return
|
|
70
|
+
return (
|
|
71
|
+
<Avatar
|
|
72
|
+
alt={label}
|
|
73
|
+
avatar={icon}
|
|
74
|
+
shape={'square'}
|
|
75
|
+
size={SKILL_ICON_SIZE}
|
|
76
|
+
style={{ flex: 'none' }}
|
|
77
|
+
/>
|
|
78
|
+
);
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
return <Icon
|
|
81
|
+
return <Icon fill={cssVar.colorText} icon={icon} size={SKILL_ICON_SIZE} />;
|
|
79
82
|
},
|
|
80
83
|
);
|
|
81
84
|
|
|
@@ -315,7 +318,12 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
315
318
|
// 原有的 builtin 工具
|
|
316
319
|
...filteredBuiltinList.map((item) => ({
|
|
317
320
|
icon: (
|
|
318
|
-
<Avatar
|
|
321
|
+
<Avatar
|
|
322
|
+
avatar={item.meta.avatar}
|
|
323
|
+
shape={'square'}
|
|
324
|
+
size={SKILL_ICON_SIZE}
|
|
325
|
+
style={{ flex: 'none' }}
|
|
326
|
+
/>
|
|
319
327
|
),
|
|
320
328
|
key: item.identifier,
|
|
321
329
|
label: (
|
|
@@ -347,9 +355,9 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
347
355
|
const mapPluginToItem = useCallback(
|
|
348
356
|
(item: (typeof installedPluginList)[0]) => ({
|
|
349
357
|
icon: item?.avatar ? (
|
|
350
|
-
<PluginAvatar avatar={item.avatar} size={
|
|
358
|
+
<PluginAvatar avatar={item.avatar} size={SKILL_ICON_SIZE} />
|
|
351
359
|
) : (
|
|
352
|
-
<Icon icon={ToyBrick} size={
|
|
360
|
+
<Icon icon={ToyBrick} size={SKILL_ICON_SIZE} />
|
|
353
361
|
),
|
|
354
362
|
key: item.identifier,
|
|
355
363
|
label: (
|
|
@@ -428,7 +436,14 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
428
436
|
const enabledBuiltinItems = filteredBuiltinList
|
|
429
437
|
.filter((item) => isToolEnabled(item.identifier))
|
|
430
438
|
.map((item) => ({
|
|
431
|
-
icon:
|
|
439
|
+
icon: (
|
|
440
|
+
<Avatar
|
|
441
|
+
avatar={item.meta.avatar}
|
|
442
|
+
shape={'square'}
|
|
443
|
+
size={SKILL_ICON_SIZE}
|
|
444
|
+
style={{ flex: 'none' }}
|
|
445
|
+
/>
|
|
446
|
+
),
|
|
432
447
|
key: item.identifier,
|
|
433
448
|
label: (
|
|
434
449
|
<ToolItem
|
|
@@ -475,9 +490,9 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
475
490
|
.filter((item) => plugins.includes(item.identifier))
|
|
476
491
|
.map((item) => ({
|
|
477
492
|
icon: item?.avatar ? (
|
|
478
|
-
<PluginAvatar avatar={item.avatar} size={
|
|
493
|
+
<PluginAvatar avatar={item.avatar} size={SKILL_ICON_SIZE} />
|
|
479
494
|
) : (
|
|
480
|
-
<Icon icon={ToyBrick} size={
|
|
495
|
+
<Icon icon={ToyBrick} size={SKILL_ICON_SIZE} />
|
|
481
496
|
),
|
|
482
497
|
key: item.identifier,
|
|
483
498
|
label: (
|
|
@@ -508,9 +523,9 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
508
523
|
.filter((item) => plugins.includes(item.identifier))
|
|
509
524
|
.map((item) => ({
|
|
510
525
|
icon: item?.avatar ? (
|
|
511
|
-
<PluginAvatar avatar={item.avatar} size={
|
|
526
|
+
<PluginAvatar avatar={item.avatar} size={SKILL_ICON_SIZE} />
|
|
512
527
|
) : (
|
|
513
|
-
<Icon icon={ToyBrick} size={
|
|
528
|
+
<Icon icon={ToyBrick} size={SKILL_ICON_SIZE} />
|
|
514
529
|
),
|
|
515
530
|
key: item.identifier,
|
|
516
531
|
label: (
|
|
@@ -552,7 +567,6 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
552
567
|
|
|
553
568
|
// Use effective tab for display (default to all while initializing)
|
|
554
569
|
const effectiveTab = activeTab ?? 'all';
|
|
555
|
-
const currentItems = effectiveTab === 'all' ? allTabItems : installedTabItems;
|
|
556
570
|
|
|
557
571
|
const button = (
|
|
558
572
|
<Button
|
|
@@ -581,11 +595,11 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
581
595
|
{/* Plugin Selector and Tags */}
|
|
582
596
|
<Flexbox align="center" gap={8} horizontal wrap={'wrap'}>
|
|
583
597
|
<Suspense fallback={button}>
|
|
584
|
-
|
|
598
|
+
{/* Plugin Selector Dropdown - Using Action component pattern */}
|
|
585
599
|
<ActionDropdown
|
|
586
600
|
maxWidth={400}
|
|
587
601
|
menu={{
|
|
588
|
-
items:
|
|
602
|
+
items: [],
|
|
589
603
|
style: {
|
|
590
604
|
// let only the custom scroller scroll
|
|
591
605
|
maxHeight: 'unset',
|
|
@@ -596,15 +610,20 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
596
610
|
onOpenChange={setDropdownOpen}
|
|
597
611
|
open={dropdownOpen}
|
|
598
612
|
placement={'bottomLeft'}
|
|
599
|
-
|
|
613
|
+
popupProps={{
|
|
614
|
+
style: {
|
|
615
|
+
padding: 0,
|
|
616
|
+
},
|
|
617
|
+
}}
|
|
618
|
+
popupRender={() => (
|
|
600
619
|
<PopoverContent
|
|
601
620
|
activeTab={effectiveTab}
|
|
621
|
+
allTabItems={allTabItems}
|
|
602
622
|
installedTabItems={installedTabItems}
|
|
603
|
-
menu={menu}
|
|
604
623
|
onClose={() => setDropdownOpen(false)}
|
|
605
624
|
onOpenStore={() => {
|
|
606
625
|
setDropdownOpen(false);
|
|
607
|
-
createSkillStoreModal()
|
|
626
|
+
createSkillStoreModal();
|
|
608
627
|
}}
|
|
609
628
|
onTabChange={setActiveTab}
|
|
610
629
|
/>
|
|
@@ -1,56 +1,22 @@
|
|
|
1
1
|
import { Flexbox, Icon, type ItemType, Segmented } from '@lobehub/ui';
|
|
2
2
|
import { createStaticStyles, cssVar } from 'antd-style';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { ChevronRight, ExternalLink, Settings, Store } from 'lucide-react';
|
|
4
|
+
import { memo } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { useNavigate } from 'react-router-dom';
|
|
7
7
|
|
|
8
|
+
import ToolsList, { toolsListStyles } from '@/features/ChatInput/ActionBar/Tools/ToolsList';
|
|
9
|
+
|
|
8
10
|
import Empty from './Empty';
|
|
9
11
|
|
|
10
12
|
type TabType = 'all' | 'installed';
|
|
11
13
|
|
|
12
|
-
const
|
|
14
|
+
const SKILL_ICON_SIZE = 20;
|
|
13
15
|
|
|
14
16
|
const styles = createStaticStyles(({ css }) => ({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
.${prefixCls}-dropdown-menu {
|
|
20
|
-
border-radius: 0 !important;
|
|
21
|
-
background: transparent !important;
|
|
22
|
-
box-shadow: none !important;
|
|
23
|
-
}
|
|
24
|
-
`,
|
|
25
|
-
footerItem: css`
|
|
26
|
-
cursor: pointer;
|
|
27
|
-
|
|
28
|
-
display: flex;
|
|
29
|
-
gap: 12px;
|
|
30
|
-
align-items: center;
|
|
31
|
-
|
|
32
|
-
padding-block: 8px;
|
|
33
|
-
padding-inline: 12px;
|
|
34
|
-
border-radius: 6px;
|
|
35
|
-
|
|
36
|
-
transition: background-color 0.2s;
|
|
37
|
-
|
|
38
|
-
&:hover {
|
|
39
|
-
background: ${cssVar.colorFillTertiary};
|
|
40
|
-
}
|
|
41
|
-
`,
|
|
42
|
-
footerItemContent: css`
|
|
43
|
-
flex: 1;
|
|
44
|
-
min-width: 0;
|
|
45
|
-
`,
|
|
46
|
-
footerItemIcon: css`
|
|
47
|
-
display: flex;
|
|
48
|
-
flex-shrink: 0;
|
|
49
|
-
align-items: center;
|
|
50
|
-
justify-content: center;
|
|
51
|
-
|
|
52
|
-
width: 24px;
|
|
53
|
-
height: 24px;
|
|
17
|
+
footer: css`
|
|
18
|
+
padding: 4px;
|
|
19
|
+
border-block-start: 1px solid ${cssVar.colorBorderSecondary};
|
|
54
20
|
`,
|
|
55
21
|
header: css`
|
|
56
22
|
padding: ${cssVar.paddingXS};
|
|
@@ -67,20 +33,22 @@ const styles = createStaticStyles(({ css }) => ({
|
|
|
67
33
|
|
|
68
34
|
interface PopoverContentProps {
|
|
69
35
|
activeTab: TabType;
|
|
36
|
+
allTabItems: ItemType[];
|
|
70
37
|
installedTabItems: ItemType[];
|
|
71
|
-
menu: ReactNode;
|
|
72
38
|
onClose?: () => void;
|
|
73
39
|
onOpenStore: () => void;
|
|
74
40
|
onTabChange: (tab: TabType) => void;
|
|
75
41
|
}
|
|
76
42
|
|
|
77
43
|
const PopoverContent = memo<PopoverContentProps>(
|
|
78
|
-
({
|
|
44
|
+
({ activeTab, onTabChange, allTabItems, installedTabItems, onOpenStore, onClose }) => {
|
|
79
45
|
const { t } = useTranslation('setting');
|
|
80
46
|
const navigate = useNavigate();
|
|
81
47
|
|
|
48
|
+
const currentItems = activeTab === 'all' ? allTabItems : installedTabItems;
|
|
49
|
+
|
|
82
50
|
return (
|
|
83
|
-
<Flexbox
|
|
51
|
+
<Flexbox style={{ maxHeight: 500, width: '100%' }}>
|
|
84
52
|
{/* stopPropagation prevents dropdown's onClick from calling preventDefault on Segmented */}
|
|
85
53
|
<div className={styles.header} onClick={(e) => e.stopPropagation()}>
|
|
86
54
|
<Segmented
|
|
@@ -101,23 +69,22 @@ const PopoverContent = memo<PopoverContentProps>(
|
|
|
101
69
|
/>
|
|
102
70
|
</div>
|
|
103
71
|
<div className={styles.scroller} style={{ flex: 1 }}>
|
|
104
|
-
{activeTab === 'installed' && installedTabItems.length === 0 ?
|
|
72
|
+
{activeTab === 'installed' && installedTabItems.length === 0 ? (
|
|
73
|
+
<Empty />
|
|
74
|
+
) : (
|
|
75
|
+
<ToolsList items={currentItems} />
|
|
76
|
+
)}
|
|
105
77
|
</div>
|
|
106
|
-
<div
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}}
|
|
111
|
-
>
|
|
112
|
-
<div className={styles.footerItem} onClick={onOpenStore} role="button" tabIndex={0}>
|
|
113
|
-
<div className={styles.footerItemIcon}>
|
|
114
|
-
<Icon icon={Store} size={20} />
|
|
78
|
+
<div className={styles.footer}>
|
|
79
|
+
<div className={toolsListStyles.item} onClick={onOpenStore} role="button" tabIndex={0}>
|
|
80
|
+
<div className={toolsListStyles.itemIcon}>
|
|
81
|
+
<Icon icon={Store} size={SKILL_ICON_SIZE} />
|
|
115
82
|
</div>
|
|
116
|
-
<div className={
|
|
117
|
-
<Icon className={styles.trailingIcon} icon={
|
|
83
|
+
<div className={toolsListStyles.itemContent}>{t('skillStore.title')}</div>
|
|
84
|
+
<Icon className={styles.trailingIcon} icon={ChevronRight} size={16} />
|
|
118
85
|
</div>
|
|
119
86
|
<div
|
|
120
|
-
className={
|
|
87
|
+
className={toolsListStyles.item}
|
|
121
88
|
onClick={() => {
|
|
122
89
|
onClose?.();
|
|
123
90
|
navigate('/settings/skill');
|
|
@@ -125,10 +92,10 @@ const PopoverContent = memo<PopoverContentProps>(
|
|
|
125
92
|
role="button"
|
|
126
93
|
tabIndex={0}
|
|
127
94
|
>
|
|
128
|
-
<div className={
|
|
129
|
-
<Icon icon={Settings} size={
|
|
95
|
+
<div className={toolsListStyles.itemIcon}>
|
|
96
|
+
<Icon icon={Settings} size={SKILL_ICON_SIZE} />
|
|
130
97
|
</div>
|
|
131
|
-
<div className={
|
|
98
|
+
<div className={toolsListStyles.itemContent}>{t('tools.plugins.management')}</div>
|
|
132
99
|
<Icon className={styles.trailingIcon} icon={ExternalLink} size={16} />
|
|
133
100
|
</div>
|
|
134
101
|
</div>
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
import {
|
|
4
4
|
Button,
|
|
5
5
|
Flexbox,
|
|
6
|
+
LobeSelect,
|
|
6
7
|
Popover,
|
|
7
8
|
Skeleton,
|
|
8
9
|
Text,
|
|
9
10
|
copyToClipboard,
|
|
10
11
|
usePopoverContext,
|
|
11
12
|
} from '@lobehub/ui';
|
|
12
|
-
import { App, Divider
|
|
13
|
+
import { App, Divider } from 'antd';
|
|
13
14
|
import { ExternalLinkIcon, LinkIcon, LockIcon } from 'lucide-react';
|
|
14
15
|
import { type ReactNode, memo, useCallback, useEffect, useRef, useState } from 'react';
|
|
15
16
|
import { useTranslation } from 'react-i18next';
|
|
@@ -146,9 +147,8 @@ const SharePopoverContent = memo<SharePopoverContentProps>(({ onOpenModal }) =>
|
|
|
146
147
|
|
|
147
148
|
<Flexbox gap={4}>
|
|
148
149
|
<Text type="secondary">{t('shareModal.popover.visibility')}</Text>
|
|
149
|
-
<
|
|
150
|
+
<LobeSelect
|
|
150
151
|
disabled={updating}
|
|
151
|
-
getPopupContainer={() => containerRef.current || document.body}
|
|
152
152
|
labelRender={({ value }) => {
|
|
153
153
|
const option = visibilityOptions.find((o) => o.value === value);
|
|
154
154
|
return (
|
|
@@ -9,8 +9,8 @@ import { useTranslation } from 'react-i18next';
|
|
|
9
9
|
|
|
10
10
|
import PluginAvatar from '@/components/Plugins/PluginAvatar';
|
|
11
11
|
import McpDetail from '@/features/MCP/MCPDetail';
|
|
12
|
-
import MCPInstallProgress from '@/features/MCP/MCPInstallProgress';
|
|
13
12
|
import McpDetailLoading from '@/features/MCP/MCPDetail/Loading';
|
|
13
|
+
import MCPInstallProgress from '@/features/MCP/MCPInstallProgress';
|
|
14
14
|
import { useMarketAuth } from '@/layout/AuthProvider/MarketAuth';
|
|
15
15
|
import { useAgentStore } from '@/store/agent';
|
|
16
16
|
import { agentSelectors } from '@/store/agent/selectors';
|
|
@@ -95,6 +95,7 @@ const Item = memo<DiscoverMcpItem>(({ name, description, icon, identifier }) =>
|
|
|
95
95
|
},
|
|
96
96
|
},
|
|
97
97
|
]}
|
|
98
|
+
nativeButton={false}
|
|
98
99
|
placement="bottomRight"
|
|
99
100
|
>
|
|
100
101
|
<ActionIcon icon={MoreVerticalIcon} />
|