@lobehub/lobehub 2.1.14 → 2.1.16
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/v2.json +18 -0
- package/locales/en-US/discover.json +9 -0
- package/locales/en-US/setting.json +3 -0
- package/locales/zh-CN/discover.json +9 -0
- package/locales/zh-CN/setting.json +3 -0
- package/package.json +1 -1
- package/packages/types/src/discover/assistants.ts +1 -0
- package/packages/types/src/discover/index.ts +8 -0
- package/packages/utils/src/chunkers/trimBatchProbe/trimBatchProbe.ts +1 -1
- package/packages/utils/src/pricing.ts +6 -6
- package/src/app/[variants]/(main)/agent/profile/features/Header/AgentPublishButton/PublishButton.tsx +52 -8
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Header.tsx +3 -3
- package/src/app/[variants]/(main)/community/(detail)/user/features/DetailProvider.tsx +2 -0
- package/src/app/[variants]/(main)/community/(detail)/user/features/StatusFilter.tsx +36 -0
- package/src/app/[variants]/(main)/community/(detail)/user/features/UserAgentList.tsx +69 -13
- package/src/app/[variants]/(main)/community/(detail)/user/features/UserContent.tsx +0 -11
- package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupList.tsx +68 -14
- package/src/app/[variants]/(main)/community/(detail)/user/index.tsx +3 -1
- package/src/app/[variants]/(main)/community/(list)/agent/features/List/Item.tsx +2 -1
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/PublishButton.tsx +52 -8
- package/src/locales/default/discover.ts +12 -0
- package/src/locales/default/setting.ts +3 -0
- package/src/server/routers/lambda/market/social.ts +1 -1
- package/src/server/services/discover/index.ts +57 -2
- package/src/services/models.ts +0 -1
- package/src/services/social.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 2.1.16](https://github.com/lobehub/lobe-chat/compare/v2.1.15...v2.1.16)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2026-02-04**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Add the preview publish to market button preview check.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Add the preview publish to market button preview check, closes [#12105](https://github.com/lobehub/lobe-chat/issues/12105) ([28887c7](https://github.com/lobehub/lobe-chat/commit/28887c7))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 2.1.15](https://github.com/lobehub/lobe-chat/compare/v2.1.14...v2.1.15)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2026-02-04**</sup>
|
|
33
|
+
|
|
34
|
+
#### 🐛 Bug Fixes
|
|
35
|
+
|
|
36
|
+
- **misc**: Fixed the agents list the show updateAt time error.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### What's fixed
|
|
44
|
+
|
|
45
|
+
- **misc**: Fixed the agents list the show updateAt time error, closes [#12103](https://github.com/lobehub/lobe-chat/issues/12103) ([3063cee](https://github.com/lobehub/lobe-chat/commit/3063cee))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
### [Version 2.1.14](https://github.com/lobehub/lobe-chat/compare/v2.1.13...v2.1.14)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2026-02-04**</sup>
|
package/changelog/v2.json
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"children": {
|
|
4
|
+
"fixes": [
|
|
5
|
+
"Add the preview publish to market button preview check."
|
|
6
|
+
]
|
|
7
|
+
},
|
|
8
|
+
"date": "2026-02-04",
|
|
9
|
+
"version": "2.1.16"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"children": {
|
|
13
|
+
"fixes": [
|
|
14
|
+
"Fixed the agents list the show updateAt time error."
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"date": "2026-02-04",
|
|
18
|
+
"version": "2.1.15"
|
|
19
|
+
},
|
|
2
20
|
{
|
|
3
21
|
"children": {
|
|
4
22
|
"fixes": [
|
|
@@ -490,6 +490,15 @@
|
|
|
490
490
|
"user.noForkedAgentGroups": "No forked Agent Groups yet",
|
|
491
491
|
"user.noForkedAgents": "No forked Agents yet",
|
|
492
492
|
"user.publishedAgents": "Created Agents",
|
|
493
|
+
"user.publishedGroups": "Created Groups",
|
|
494
|
+
"user.searchPlaceholder": "Search by name or description...",
|
|
495
|
+
"user.statusFilter.all": "All",
|
|
496
|
+
"user.statusFilter.archived": "Archived",
|
|
497
|
+
"user.statusFilter.deprecated": "Deprecated",
|
|
498
|
+
"user.statusFilter.favorite": "Favorite",
|
|
499
|
+
"user.statusFilter.forked": "Forked",
|
|
500
|
+
"user.statusFilter.published": "Published",
|
|
501
|
+
"user.statusFilter.unpublished": "Under Review",
|
|
493
502
|
"user.tabs.favorites": "Favorites",
|
|
494
503
|
"user.tabs.forkedAgents": "Forked",
|
|
495
504
|
"user.tabs.publishedAgents": "Created",
|
|
@@ -268,6 +268,9 @@
|
|
|
268
268
|
"marketPublish.upload.button": "Publish New Version",
|
|
269
269
|
"marketPublish.upload.tooltip": "Publish a new version to Agent Community",
|
|
270
270
|
"marketPublish.uploadGroup.tooltip": "Publish a new version to Group Community",
|
|
271
|
+
"marketPublish.validation.confirmPublish": "Are you sure you want to publish to the market?",
|
|
272
|
+
"marketPublish.validation.emptyName": "Cannot publish: Name is required",
|
|
273
|
+
"marketPublish.validation.emptySystemRole": "Cannot publish: System Role is required",
|
|
271
274
|
"memory.enabled.desc": "Allow LobeHub to extract preferences and info from conversations and use them later. You can view, edit, or clear memory anytime.",
|
|
272
275
|
"memory.enabled.title": "Enable Memory",
|
|
273
276
|
"memory.title": "Memory Settings",
|
|
@@ -490,6 +490,15 @@
|
|
|
490
490
|
"user.noForkedAgentGroups": "尚无已派生的代理组",
|
|
491
491
|
"user.noForkedAgents": "尚无已派生的代理",
|
|
492
492
|
"user.publishedAgents": "创作的助理",
|
|
493
|
+
"user.publishedGroups": "创作的群组",
|
|
494
|
+
"user.searchPlaceholder": "搜索名称或描述...",
|
|
495
|
+
"user.statusFilter.all": "全部",
|
|
496
|
+
"user.statusFilter.archived": "已归档",
|
|
497
|
+
"user.statusFilter.deprecated": "已废弃",
|
|
498
|
+
"user.statusFilter.favorite": "已收藏",
|
|
499
|
+
"user.statusFilter.forked": "已派生",
|
|
500
|
+
"user.statusFilter.published": "已发布",
|
|
501
|
+
"user.statusFilter.unpublished": "审核中",
|
|
493
502
|
"user.tabs.favorites": "收藏",
|
|
494
503
|
"user.tabs.forkedAgents": "已派生",
|
|
495
504
|
"user.tabs.publishedAgents": "创作",
|
|
@@ -268,6 +268,9 @@
|
|
|
268
268
|
"marketPublish.upload.button": "发布新版本",
|
|
269
269
|
"marketPublish.upload.tooltip": "发布新版本到助理社区",
|
|
270
270
|
"marketPublish.uploadGroup.tooltip": "向群组社区发布新版本",
|
|
271
|
+
"marketPublish.validation.confirmPublish": "确定要发布到市场吗?",
|
|
272
|
+
"marketPublish.validation.emptyName": "无法发布:名称不能为空",
|
|
273
|
+
"marketPublish.validation.emptySystemRole": "无法发布:系统角色不能为空",
|
|
271
274
|
"memory.enabled.desc": "允许 LobeHub 从对话中提取偏好和信息,并在之后使用。您可以随时查看、编辑或清除记忆内容。",
|
|
272
275
|
"memory.enabled.title": "启用记忆功能",
|
|
273
276
|
"memory.title": "记忆设置",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.16",
|
|
4
4
|
"description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -67,6 +67,14 @@ export interface DiscoverUserInfo {
|
|
|
67
67
|
export interface DiscoverUserProfile {
|
|
68
68
|
agentGroups?: DiscoverGroupAgentItem[];
|
|
69
69
|
agents: DiscoverAssistantItem[];
|
|
70
|
+
/**
|
|
71
|
+
* Agent groups favorited by the user
|
|
72
|
+
*/
|
|
73
|
+
favoriteAgentGroups?: DiscoverGroupAgentItem[];
|
|
74
|
+
/**
|
|
75
|
+
* Agents favorited by the user
|
|
76
|
+
*/
|
|
77
|
+
favoriteAgents?: DiscoverAssistantItem[];
|
|
70
78
|
/**
|
|
71
79
|
* Agent groups forked by the user
|
|
72
80
|
*/
|
|
@@ -202,7 +202,7 @@ export const handleSingle = async (
|
|
|
202
202
|
* to avoid breaking structured XML/JSON-like content mid-way.
|
|
203
203
|
*
|
|
204
204
|
* Bisection example (8 segments, keep newest):
|
|
205
|
-
* try 4 (fits?)
|
|
205
|
+
* try 4 (fits?) -> yes -> try 6 -> no -> try 5 -> yes => best=5
|
|
206
206
|
* if compact retry needed, repeat with build(true) and pick the better fit.
|
|
207
207
|
*
|
|
208
208
|
* This minimizes structural breakage by preferring whole built segments and only truncating the last one as a last resort.
|
|
@@ -2,9 +2,9 @@ import { Pricing, PricingUnit, PricingUnitName } from 'model-bank';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Internal helper to extract the displayed unit rate from a pricing unit by strategy
|
|
5
|
-
* - fixed
|
|
6
|
-
* - tiered
|
|
7
|
-
* - lookup
|
|
5
|
+
* - fixed: rate
|
|
6
|
+
* - tiered: tiers[0].rate
|
|
7
|
+
* - lookup: first price value
|
|
8
8
|
*/
|
|
9
9
|
const getRateFromUnit = (unit: PricingUnit): number | undefined => {
|
|
10
10
|
switch (unit.strategy) {
|
|
@@ -39,9 +39,9 @@ export const getUnitRateByName = (
|
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Get text input unit rate from pricing
|
|
42
|
-
* - fixed
|
|
43
|
-
* - tiered
|
|
44
|
-
* - lookup
|
|
42
|
+
* - fixed: rate
|
|
43
|
+
* - tiered: tiers[0].rate
|
|
44
|
+
* - lookup: Object.values(lookup.prices)[0]
|
|
45
45
|
*/
|
|
46
46
|
export function getTextInputUnitRate(pricing?: Pricing): number | undefined {
|
|
47
47
|
return getUnitRateByName(pricing, 'textInput');
|
package/src/app/[variants]/(main)/agent/profile/features/Header/AgentPublishButton/PublishButton.tsx
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { Button } from '@lobehub/ui';
|
|
2
2
|
import { ShapesUploadIcon } from '@lobehub/ui/icons';
|
|
3
|
+
import { Popconfirm } from 'antd';
|
|
4
|
+
import isEqual from 'fast-deep-equal';
|
|
3
5
|
import { memo, useCallback, useMemo, useState } from 'react';
|
|
4
6
|
import { useTranslation } from 'react-i18next';
|
|
5
7
|
|
|
6
8
|
import { message } from '@/components/AntdStaticMethods';
|
|
7
9
|
import { useMarketAuth } from '@/layout/AuthProvider/MarketAuth';
|
|
8
10
|
import { resolveMarketAuthError } from '@/layout/AuthProvider/MarketAuth/errors';
|
|
11
|
+
import { useAgentStore } from '@/store/agent';
|
|
12
|
+
import { agentSelectors } from '@/store/agent/selectors';
|
|
9
13
|
|
|
10
14
|
import ForkConfirmModal from './ForkConfirmModal';
|
|
11
15
|
import type { MarketPublishAction } from './types';
|
|
@@ -25,10 +29,17 @@ const PublishButton = memo<MarketPublishButtonProps>(({ action, onPublishSuccess
|
|
|
25
29
|
onSuccess: onPublishSuccess,
|
|
26
30
|
});
|
|
27
31
|
|
|
32
|
+
// Agent data for validation
|
|
33
|
+
const meta = useAgentStore(agentSelectors.currentAgentMeta, isEqual);
|
|
34
|
+
const systemRole = useAgentStore(agentSelectors.currentAgentSystemRole);
|
|
35
|
+
|
|
28
36
|
// Fork confirmation modal state
|
|
29
37
|
const [showForkModal, setShowForkModal] = useState(false);
|
|
30
38
|
const [originalAgentInfo, setOriginalAgentInfo] = useState<OriginalAgentInfo | null>(null);
|
|
31
39
|
|
|
40
|
+
// Publish confirmation popconfirm state
|
|
41
|
+
const [confirmOpened, setConfirmOpened] = useState(false);
|
|
42
|
+
|
|
32
43
|
const buttonConfig = useMemo(() => {
|
|
33
44
|
if (action === 'upload') {
|
|
34
45
|
return {
|
|
@@ -60,7 +71,25 @@ const PublishButton = memo<MarketPublishButtonProps>(({ action, onPublishSuccess
|
|
|
60
71
|
await publish();
|
|
61
72
|
}, [checkOwnership, publish]);
|
|
62
73
|
|
|
63
|
-
const handleButtonClick = useCallback(
|
|
74
|
+
const handleButtonClick = useCallback(() => {
|
|
75
|
+
// Validate name and systemRole
|
|
76
|
+
if (!meta?.title || meta.title.trim() === '') {
|
|
77
|
+
message.error({ content: t('marketPublish.validation.emptyName') });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!systemRole || systemRole.trim() === '') {
|
|
82
|
+
message.error({ content: t('marketPublish.validation.emptySystemRole') });
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Open popconfirm for user confirmation
|
|
87
|
+
setConfirmOpened(true);
|
|
88
|
+
}, [meta?.title, systemRole, t]);
|
|
89
|
+
|
|
90
|
+
const handleConfirmPublish = useCallback(async () => {
|
|
91
|
+
setConfirmOpened(false);
|
|
92
|
+
|
|
64
93
|
if (!isAuthenticated) {
|
|
65
94
|
try {
|
|
66
95
|
await signIn();
|
|
@@ -98,14 +127,29 @@ const PublishButton = memo<MarketPublishButtonProps>(({ action, onPublishSuccess
|
|
|
98
127
|
|
|
99
128
|
return (
|
|
100
129
|
<>
|
|
101
|
-
<
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
130
|
+
<Popconfirm
|
|
131
|
+
arrow={false}
|
|
132
|
+
okButtonProps={{ type: 'primary' }}
|
|
133
|
+
onCancel={() => setConfirmOpened(false)}
|
|
134
|
+
onConfirm={handleConfirmPublish}
|
|
135
|
+
onOpenChange={(open) => {
|
|
136
|
+
if (!open) {
|
|
137
|
+
setConfirmOpened(false);
|
|
138
|
+
}
|
|
139
|
+
}}
|
|
140
|
+
open={confirmOpened}
|
|
141
|
+
placement="bottomRight"
|
|
142
|
+
title={t('marketPublish.validation.confirmPublish')}
|
|
106
143
|
>
|
|
107
|
-
|
|
108
|
-
|
|
144
|
+
<Button
|
|
145
|
+
icon={ShapesUploadIcon}
|
|
146
|
+
loading={loading}
|
|
147
|
+
onClick={handleButtonClick}
|
|
148
|
+
title={buttonTitle}
|
|
149
|
+
>
|
|
150
|
+
{t('publishToCommunity')}
|
|
151
|
+
</Button>
|
|
152
|
+
</Popconfirm>
|
|
109
153
|
<ForkConfirmModal
|
|
110
154
|
loading={isPublishing}
|
|
111
155
|
onCancel={handleForkCancel}
|
|
@@ -75,7 +75,7 @@ const Header = memo<{ mobile?: boolean }>(({ mobile: isMobile }) => {
|
|
|
75
75
|
// Fetch favorite status
|
|
76
76
|
const { data: favoriteStatus, mutate: mutateFavorite } = useSWR(
|
|
77
77
|
identifier && isAuthenticated ? ['favorite-status', 'agent', identifier] : null,
|
|
78
|
-
() => socialService.checkFavoriteStatus('agent', identifier!),
|
|
78
|
+
() => socialService.checkFavoriteStatus('agent-group', identifier!),
|
|
79
79
|
{ revalidateOnFocus: false },
|
|
80
80
|
);
|
|
81
81
|
|
|
@@ -100,10 +100,10 @@ const Header = memo<{ mobile?: boolean }>(({ mobile: isMobile }) => {
|
|
|
100
100
|
setFavoriteLoading(true);
|
|
101
101
|
try {
|
|
102
102
|
if (isFavorited) {
|
|
103
|
-
await socialService.removeFavorite('agent', identifier);
|
|
103
|
+
await socialService.removeFavorite('agent-group', identifier);
|
|
104
104
|
message.success(t('assistant.unfavoriteSuccess'));
|
|
105
105
|
} else {
|
|
106
|
-
await socialService.addFavorite('agent', identifier);
|
|
106
|
+
await socialService.addFavorite('agent-group', identifier);
|
|
107
107
|
message.success(t('assistant.favoriteSuccess'));
|
|
108
108
|
}
|
|
109
109
|
await mutateFavorite();
|
|
@@ -13,6 +13,8 @@ export interface UserDetailContextConfig {
|
|
|
13
13
|
agentCount: number;
|
|
14
14
|
agentGroups?: DiscoverGroupAgentItem[];
|
|
15
15
|
agents: DiscoverAssistantItem[];
|
|
16
|
+
favoriteAgentGroups?: DiscoverGroupAgentItem[];
|
|
17
|
+
favoriteAgents?: DiscoverAssistantItem[];
|
|
16
18
|
forkedAgentGroups?: DiscoverGroupAgentItem[];
|
|
17
19
|
forkedAgents?: DiscoverAssistantItem[];
|
|
18
20
|
groupCount: number;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Select } from 'antd';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
|
|
7
|
+
export type StatusFilterValue = 'published' | 'unpublished' | 'deprecated' | 'archived' | 'forked' | 'favorite';
|
|
8
|
+
|
|
9
|
+
interface StatusFilterProps {
|
|
10
|
+
onChange: (value: StatusFilterValue) => void;
|
|
11
|
+
value: StatusFilterValue;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const StatusFilter = memo<StatusFilterProps>(({ value, onChange }) => {
|
|
15
|
+
const { t } = useTranslation('discover');
|
|
16
|
+
|
|
17
|
+
const options = [
|
|
18
|
+
{ label: t('user.statusFilter.published'), value: 'published' as const },
|
|
19
|
+
{ label: t('user.statusFilter.unpublished'), value: 'unpublished' as const },
|
|
20
|
+
{ label: t('user.statusFilter.deprecated'), value: 'deprecated' as const },
|
|
21
|
+
{ label: t('user.statusFilter.archived'), value: 'archived' as const },
|
|
22
|
+
{ label: t('user.statusFilter.forked'), value: 'forked' as const },
|
|
23
|
+
{ label: t('user.statusFilter.favorite'), value: 'favorite' as const },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<Select
|
|
28
|
+
onChange={onChange}
|
|
29
|
+
options={options}
|
|
30
|
+
style={{ minWidth: 120 }}
|
|
31
|
+
value={value}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export default StatusFilter;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { Flexbox, Grid, Tag, Text } from '@lobehub/ui';
|
|
4
|
-
import { Pagination } from 'antd';
|
|
4
|
+
import { Input, Pagination } from 'antd';
|
|
5
5
|
import { memo, useMemo, useState } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
|
|
8
8
|
import AssistantEmpty from '../../../features/AssistantEmpty';
|
|
9
9
|
import { useUserDetailContext } from './DetailProvider';
|
|
10
|
+
import StatusFilter, { type StatusFilterValue } from './StatusFilter';
|
|
10
11
|
import UserAgentCard from './UserAgentCard';
|
|
11
12
|
|
|
12
13
|
interface UserAgentListProps {
|
|
@@ -14,27 +15,82 @@ interface UserAgentListProps {
|
|
|
14
15
|
rows?: number;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
const UserAgentList = memo<UserAgentListProps>(({ rows = 4, pageSize =
|
|
18
|
+
const UserAgentList = memo<UserAgentListProps>(({ rows = 4, pageSize = 8 }) => {
|
|
18
19
|
const { t } = useTranslation('discover');
|
|
19
|
-
const { agents, agentCount } = useUserDetailContext();
|
|
20
|
+
const { agents, agentCount, forkedAgents = [], favoriteAgents = [], isOwner } = useUserDetailContext();
|
|
20
21
|
const [currentPage, setCurrentPage] = useState(1);
|
|
22
|
+
const [statusFilter, setStatusFilter] = useState<StatusFilterValue>('published');
|
|
23
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
24
|
+
|
|
25
|
+
// Combine agents and forked agents, then filter based on status and search
|
|
26
|
+
const filteredAgents = useMemo(() => {
|
|
27
|
+
let allAgents = [...agents];
|
|
28
|
+
|
|
29
|
+
if (statusFilter === 'forked') {
|
|
30
|
+
// Show only forked agents (those with forkedFromAgentId)
|
|
31
|
+
allAgents = forkedAgents;
|
|
32
|
+
} else if (statusFilter === 'favorite') {
|
|
33
|
+
// Show only favorited agents
|
|
34
|
+
allAgents = favoriteAgents;
|
|
35
|
+
} else {
|
|
36
|
+
// Filter by status for non-forked agents
|
|
37
|
+
allAgents = allAgents.filter((agent) => {
|
|
38
|
+
return agent.status === statusFilter;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Apply search filter
|
|
43
|
+
if (searchQuery.trim()) {
|
|
44
|
+
const query = searchQuery.toLowerCase();
|
|
45
|
+
allAgents = allAgents.filter((agent) => {
|
|
46
|
+
console.log('agent', agent);
|
|
47
|
+
const name = agent?.title?.toLowerCase() || '';
|
|
48
|
+
const description = agent?.description?.toLowerCase() || '';
|
|
49
|
+
return name.includes(query) || description.includes(query);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return allAgents;
|
|
54
|
+
}, [agents, forkedAgents, statusFilter, searchQuery]);
|
|
21
55
|
|
|
22
56
|
const paginatedAgents = useMemo(() => {
|
|
23
57
|
const startIndex = (currentPage - 1) * pageSize;
|
|
24
|
-
return
|
|
25
|
-
}, [
|
|
58
|
+
return filteredAgents.slice(startIndex, startIndex + pageSize);
|
|
59
|
+
}, [filteredAgents, currentPage, pageSize]);
|
|
60
|
+
|
|
61
|
+
// Reset to page 1 when filter or search changes
|
|
62
|
+
useMemo(() => {
|
|
63
|
+
setCurrentPage(1);
|
|
64
|
+
}, [statusFilter, searchQuery]);
|
|
26
65
|
|
|
27
|
-
if (agents.length === 0) return <AssistantEmpty />;
|
|
66
|
+
if (agents.length === 0 && forkedAgents.length === 0) return <AssistantEmpty />;
|
|
28
67
|
|
|
29
|
-
const showPagination =
|
|
68
|
+
const showPagination = filteredAgents.length > pageSize;
|
|
30
69
|
|
|
31
70
|
return (
|
|
32
71
|
<Flexbox gap={16}>
|
|
33
|
-
<Flexbox align={'center'} gap={8} horizontal>
|
|
34
|
-
<
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
|
|
72
|
+
<Flexbox align={'center'} gap={8} horizontal justify={'space-between'}>
|
|
73
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
|
74
|
+
<Text fontSize={16} weight={500}>
|
|
75
|
+
{t('user.publishedAgents')}
|
|
76
|
+
</Text>
|
|
77
|
+
{agentCount > 0 && <Tag>{filteredAgents.length}</Tag>}
|
|
78
|
+
</Flexbox>
|
|
79
|
+
{isOwner && (
|
|
80
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
|
81
|
+
<Input.Search
|
|
82
|
+
allowClear
|
|
83
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
84
|
+
placeholder={t('user.searchPlaceholder')}
|
|
85
|
+
style={{ width: 200 }}
|
|
86
|
+
value={searchQuery}
|
|
87
|
+
/>
|
|
88
|
+
<StatusFilter
|
|
89
|
+
onChange={(value) => setStatusFilter(value)}
|
|
90
|
+
value={statusFilter}
|
|
91
|
+
/>
|
|
92
|
+
</Flexbox>
|
|
93
|
+
)}
|
|
38
94
|
</Flexbox>
|
|
39
95
|
<Grid rows={rows} width={'100%'}>
|
|
40
96
|
{paginatedAgents.map((item, index) => (
|
|
@@ -48,7 +104,7 @@ const UserAgentList = memo<UserAgentListProps>(({ rows = 4, pageSize = 10 }) =>
|
|
|
48
104
|
onChange={(page) => setCurrentPage(page)}
|
|
49
105
|
pageSize={pageSize}
|
|
50
106
|
showSizeChanger={false}
|
|
51
|
-
total={
|
|
107
|
+
total={filteredAgents.length}
|
|
52
108
|
/>
|
|
53
109
|
</Flexbox>
|
|
54
110
|
)}
|
|
@@ -3,25 +3,14 @@
|
|
|
3
3
|
import { Flexbox } from '@lobehub/ui';
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
|
|
6
|
-
import { useUserDetailContext } from './DetailProvider';
|
|
7
6
|
import UserAgentList from './UserAgentList';
|
|
8
|
-
import UserFavoriteAgents from './UserFavoriteAgents';
|
|
9
|
-
import UserFavoritePlugins from './UserFavoritePlugins';
|
|
10
|
-
import UserForkedAgentGroups from './UserForkedAgentGroups';
|
|
11
|
-
import UserForkedAgents from './UserForkedAgents';
|
|
12
7
|
import UserGroupList from './UserGroupList';
|
|
13
8
|
|
|
14
9
|
const UserContent = memo(() => {
|
|
15
|
-
const { forkedAgents, forkedAgentGroups } = useUserDetailContext();
|
|
16
|
-
|
|
17
10
|
return (
|
|
18
11
|
<Flexbox gap={32}>
|
|
19
12
|
<UserAgentList />
|
|
20
13
|
<UserGroupList />
|
|
21
|
-
<UserForkedAgents agents={forkedAgents} />
|
|
22
|
-
<UserForkedAgentGroups agentGroups={forkedAgentGroups} />
|
|
23
|
-
<UserFavoriteAgents />
|
|
24
|
-
<UserFavoritePlugins />
|
|
25
14
|
</Flexbox>
|
|
26
15
|
);
|
|
27
16
|
});
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { Flexbox, Grid, Tag, Text } from '@lobehub/ui';
|
|
4
|
-
import { Pagination } from 'antd';
|
|
4
|
+
import { Input, Pagination } from 'antd';
|
|
5
5
|
import { memo, useMemo, useState } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
|
|
8
8
|
import { useUserDetailContext } from './DetailProvider';
|
|
9
|
+
import StatusFilter, { type StatusFilterValue } from './StatusFilter';
|
|
9
10
|
import UserGroupCard from './UserGroupCard';
|
|
10
11
|
|
|
11
12
|
interface UserGroupListProps {
|
|
@@ -13,28 +14,81 @@ interface UserGroupListProps {
|
|
|
13
14
|
rows?: number;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
const UserGroupList = memo<UserGroupListProps>(({ rows = 4, pageSize =
|
|
17
|
+
const UserGroupList = memo<UserGroupListProps>(({ rows = 4, pageSize = 8 }) => {
|
|
17
18
|
const { t } = useTranslation('discover');
|
|
18
|
-
const { agentGroups, groupCount } = useUserDetailContext();
|
|
19
|
+
const { agentGroups = [], groupCount, forkedAgentGroups = [], favoriteAgentGroups = [], isOwner } = useUserDetailContext();
|
|
19
20
|
const [currentPage, setCurrentPage] = useState(1);
|
|
21
|
+
const [statusFilter, setStatusFilter] = useState<StatusFilterValue>('published');
|
|
22
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
23
|
+
|
|
24
|
+
// Combine groups and forked groups, then filter based on status and search
|
|
25
|
+
const filteredGroups = useMemo(() => {
|
|
26
|
+
let allGroups = [...agentGroups];
|
|
27
|
+
|
|
28
|
+
if (statusFilter === 'forked') {
|
|
29
|
+
// Show only forked groups (those with forkedFromAgentId)
|
|
30
|
+
allGroups = forkedAgentGroups;
|
|
31
|
+
} else if (statusFilter === 'favorite') {
|
|
32
|
+
// Show only favorited groups
|
|
33
|
+
allGroups = favoriteAgentGroups;
|
|
34
|
+
} else {
|
|
35
|
+
// Filter by status for non-forked groups
|
|
36
|
+
allGroups = allGroups.filter((group) => {
|
|
37
|
+
return group.status === statusFilter;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Apply search filter
|
|
42
|
+
if (searchQuery.trim()) {
|
|
43
|
+
const query = searchQuery.toLowerCase();
|
|
44
|
+
allGroups = allGroups.filter((group) => {
|
|
45
|
+
const name = group?.title?.toLowerCase() || '';
|
|
46
|
+
const description = group?.description?.toLowerCase() || '';
|
|
47
|
+
return name.includes(query) || description.includes(query);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return allGroups;
|
|
52
|
+
}, [agentGroups, forkedAgentGroups, statusFilter, searchQuery]);
|
|
20
53
|
|
|
21
54
|
const paginatedGroups = useMemo(() => {
|
|
22
|
-
if (!agentGroups) return [];
|
|
23
55
|
const startIndex = (currentPage - 1) * pageSize;
|
|
24
|
-
return
|
|
25
|
-
}, [
|
|
56
|
+
return filteredGroups.slice(startIndex, startIndex + pageSize);
|
|
57
|
+
}, [filteredGroups, currentPage, pageSize]);
|
|
58
|
+
|
|
59
|
+
// Reset to page 1 when filter or search changes
|
|
60
|
+
useMemo(() => {
|
|
61
|
+
setCurrentPage(1);
|
|
62
|
+
}, [statusFilter, searchQuery]);
|
|
26
63
|
|
|
27
|
-
if (
|
|
64
|
+
if (agentGroups.length === 0 && forkedAgentGroups.length === 0) return null;
|
|
28
65
|
|
|
29
|
-
const showPagination =
|
|
66
|
+
const showPagination = filteredGroups.length > pageSize;
|
|
30
67
|
|
|
31
68
|
return (
|
|
32
69
|
<Flexbox gap={16}>
|
|
33
|
-
<Flexbox align={'center'} gap={8} horizontal>
|
|
34
|
-
<
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
|
|
70
|
+
<Flexbox align={'center'} gap={8} horizontal justify={'space-between'}>
|
|
71
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
|
72
|
+
<Text fontSize={16} weight={500}>
|
|
73
|
+
{t('user.publishedGroups', { defaultValue: '创作的群组' })}
|
|
74
|
+
</Text>
|
|
75
|
+
{groupCount > 0 && <Tag>{filteredGroups.length}</Tag>}
|
|
76
|
+
</Flexbox>
|
|
77
|
+
{isOwner && (
|
|
78
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
|
79
|
+
<Input.Search
|
|
80
|
+
allowClear
|
|
81
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
82
|
+
placeholder={t('user.searchPlaceholder')}
|
|
83
|
+
style={{ width: 200 }}
|
|
84
|
+
value={searchQuery}
|
|
85
|
+
/>
|
|
86
|
+
<StatusFilter
|
|
87
|
+
onChange={(value) => setStatusFilter(value)}
|
|
88
|
+
value={statusFilter}
|
|
89
|
+
/>
|
|
90
|
+
</Flexbox>
|
|
91
|
+
)}
|
|
38
92
|
</Flexbox>
|
|
39
93
|
<Grid rows={rows} width={'100%'}>
|
|
40
94
|
{paginatedGroups.map((item, index) => (
|
|
@@ -48,7 +102,7 @@ const UserGroupList = memo<UserGroupListProps>(({ rows = 4, pageSize = 10 }) =>
|
|
|
48
102
|
onChange={(page) => setCurrentPage(page)}
|
|
49
103
|
pageSize={pageSize}
|
|
50
104
|
showSizeChanger={false}
|
|
51
|
-
total={
|
|
105
|
+
total={filteredGroups.length}
|
|
52
106
|
/>
|
|
53
107
|
</Flexbox>
|
|
54
108
|
)}
|
|
@@ -61,12 +61,14 @@ const UserDetailPage = memo<UserDetailPageProps>(({ mobile }) => {
|
|
|
61
61
|
|
|
62
62
|
const contextConfig = useMemo(() => {
|
|
63
63
|
if (!data || !data.user) return null;
|
|
64
|
-
const { user, agents, agentGroups, forkedAgents, forkedAgentGroups } = data;
|
|
64
|
+
const { user, agents, agentGroups, forkedAgents, forkedAgentGroups, favoriteAgents, favoriteAgentGroups } = data;
|
|
65
65
|
const totalInstalls = agents.reduce((sum, agent) => sum + (agent.installCount || 0), 0);
|
|
66
66
|
return {
|
|
67
67
|
agentCount: agents.length,
|
|
68
68
|
agentGroups: agentGroups || [],
|
|
69
69
|
agents,
|
|
70
|
+
favoriteAgentGroups: favoriteAgentGroups || [],
|
|
71
|
+
favoriteAgents: favoriteAgents || [],
|
|
70
72
|
forkedAgentGroups: forkedAgentGroups || [],
|
|
71
73
|
forkedAgents: forkedAgents || [],
|
|
72
74
|
groupCount: agentGroups?.length || 0,
|
|
@@ -56,6 +56,7 @@ const styles = createStaticStyles(({ css, cssVar }) => {
|
|
|
56
56
|
const AssistantItem = memo<DiscoverAssistantItem>(
|
|
57
57
|
({
|
|
58
58
|
createdAt,
|
|
59
|
+
updatedAt,
|
|
59
60
|
author,
|
|
60
61
|
avatar,
|
|
61
62
|
title,
|
|
@@ -225,7 +226,7 @@ const AssistantItem = memo<DiscoverAssistantItem>(
|
|
|
225
226
|
<Icon icon={ClockIcon} size={14} />
|
|
226
227
|
<PublishedTime
|
|
227
228
|
className={styles.secondaryDesc}
|
|
228
|
-
date={createdAt}
|
|
229
|
+
date={updatedAt || createdAt}
|
|
229
230
|
template={'MMM DD, YYYY'}
|
|
230
231
|
/>
|
|
231
232
|
</Flexbox>
|
package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/PublishButton.tsx
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { Button } from '@lobehub/ui';
|
|
2
2
|
import { ShapesUploadIcon } from '@lobehub/ui/icons';
|
|
3
|
+
import { Popconfirm } from 'antd';
|
|
4
|
+
import isEqual from 'fast-deep-equal';
|
|
3
5
|
import { memo, useCallback, useMemo, useState } from 'react';
|
|
4
6
|
import { useTranslation } from 'react-i18next';
|
|
5
7
|
|
|
6
8
|
import { message } from '@/components/AntdStaticMethods';
|
|
7
9
|
import { useMarketAuth } from '@/layout/AuthProvider/MarketAuth';
|
|
8
10
|
import { resolveMarketAuthError } from '@/layout/AuthProvider/MarketAuth/errors';
|
|
11
|
+
import { useAgentGroupStore } from '@/store/agentGroup';
|
|
12
|
+
import { agentGroupSelectors } from '@/store/agentGroup/selectors';
|
|
9
13
|
|
|
10
14
|
import GroupForkConfirmModal from './GroupForkConfirmModal';
|
|
11
15
|
import type { MarketPublishAction, OriginalGroupInfo } from './types';
|
|
@@ -25,10 +29,17 @@ const PublishButton = memo<GroupPublishButtonProps>(({ action, onPublishSuccess
|
|
|
25
29
|
onSuccess: onPublishSuccess,
|
|
26
30
|
});
|
|
27
31
|
|
|
32
|
+
// Group data for validation
|
|
33
|
+
const currentGroupMeta = useAgentGroupStore(agentGroupSelectors.currentGroupMeta, isEqual);
|
|
34
|
+
const currentGroup = useAgentGroupStore(agentGroupSelectors.currentGroup);
|
|
35
|
+
|
|
28
36
|
// Fork confirmation modal state
|
|
29
37
|
const [showForkModal, setShowForkModal] = useState(false);
|
|
30
38
|
const [originalGroupInfo, setOriginalGroupInfo] = useState<OriginalGroupInfo | null>(null);
|
|
31
39
|
|
|
40
|
+
// Publish confirmation popconfirm state
|
|
41
|
+
const [confirmOpened, setConfirmOpened] = useState(false);
|
|
42
|
+
|
|
32
43
|
const buttonConfig = useMemo(() => {
|
|
33
44
|
if (action === 'upload') {
|
|
34
45
|
return {
|
|
@@ -60,7 +71,25 @@ const PublishButton = memo<GroupPublishButtonProps>(({ action, onPublishSuccess
|
|
|
60
71
|
await publish();
|
|
61
72
|
}, [checkOwnership, publish]);
|
|
62
73
|
|
|
63
|
-
const handleButtonClick = useCallback(
|
|
74
|
+
const handleButtonClick = useCallback(() => {
|
|
75
|
+
// Validate name and systemRole (stored in content)
|
|
76
|
+
if (!currentGroupMeta?.title || currentGroupMeta.title.trim() === '') {
|
|
77
|
+
message.error({ content: t('marketPublish.validation.emptyName') });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!currentGroup?.content || currentGroup.content.trim() === '') {
|
|
82
|
+
message.error({ content: t('marketPublish.validation.emptySystemRole') });
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Open popconfirm for user confirmation
|
|
87
|
+
setConfirmOpened(true);
|
|
88
|
+
}, [currentGroupMeta?.title, currentGroup?.content, t]);
|
|
89
|
+
|
|
90
|
+
const handleConfirmPublish = useCallback(async () => {
|
|
91
|
+
setConfirmOpened(false);
|
|
92
|
+
|
|
64
93
|
if (!isAuthenticated) {
|
|
65
94
|
try {
|
|
66
95
|
await signIn();
|
|
@@ -98,14 +127,29 @@ const PublishButton = memo<GroupPublishButtonProps>(({ action, onPublishSuccess
|
|
|
98
127
|
|
|
99
128
|
return (
|
|
100
129
|
<>
|
|
101
|
-
<
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
130
|
+
<Popconfirm
|
|
131
|
+
arrow={false}
|
|
132
|
+
okButtonProps={{ type: 'primary' }}
|
|
133
|
+
onCancel={() => setConfirmOpened(false)}
|
|
134
|
+
onConfirm={handleConfirmPublish}
|
|
135
|
+
onOpenChange={(open) => {
|
|
136
|
+
if (!open) {
|
|
137
|
+
setConfirmOpened(false);
|
|
138
|
+
}
|
|
139
|
+
}}
|
|
140
|
+
open={confirmOpened}
|
|
141
|
+
placement="bottomRight"
|
|
142
|
+
title={t('marketPublish.validation.confirmPublish')}
|
|
106
143
|
>
|
|
107
|
-
|
|
108
|
-
|
|
144
|
+
<Button
|
|
145
|
+
icon={ShapesUploadIcon}
|
|
146
|
+
loading={loading}
|
|
147
|
+
onClick={handleButtonClick}
|
|
148
|
+
title={buttonTitle}
|
|
149
|
+
>
|
|
150
|
+
{t('publishToCommunity')}
|
|
151
|
+
</Button>
|
|
152
|
+
</Popconfirm>
|
|
109
153
|
<GroupForkConfirmModal
|
|
110
154
|
loading={isPublishing}
|
|
111
155
|
onCancel={handleForkCancel}
|
|
@@ -891,6 +891,18 @@ export default {
|
|
|
891
891
|
|
|
892
892
|
'user.publishedAgents': 'Created Agents',
|
|
893
893
|
|
|
894
|
+
'user.publishedGroups': 'Created Groups',
|
|
895
|
+
|
|
896
|
+
'user.searchPlaceholder': 'Search by name or description...',
|
|
897
|
+
|
|
898
|
+
'user.statusFilter.all': 'All',
|
|
899
|
+
'user.statusFilter.archived': 'Archived',
|
|
900
|
+
'user.statusFilter.deprecated': 'Deprecated',
|
|
901
|
+
'user.statusFilter.favorite': 'Favorite',
|
|
902
|
+
'user.statusFilter.forked': 'Forked',
|
|
903
|
+
'user.statusFilter.published': 'Published',
|
|
904
|
+
'user.statusFilter.unpublished': 'Under Review',
|
|
905
|
+
|
|
894
906
|
'user.tabs.favorites': 'Favorites',
|
|
895
907
|
|
|
896
908
|
'user.tabs.forkedAgents': 'Forked',
|
|
@@ -294,6 +294,9 @@ export default {
|
|
|
294
294
|
'marketPublish.upload.button': 'Publish New Version',
|
|
295
295
|
'marketPublish.upload.tooltip': 'Publish a new version to Agent Community',
|
|
296
296
|
'marketPublish.uploadGroup.tooltip': 'Publish a new version to Group Community',
|
|
297
|
+
'marketPublish.validation.confirmPublish': 'Are you sure you want to publish to the market?',
|
|
298
|
+
'marketPublish.validation.emptyName': 'Cannot publish: Name is required',
|
|
299
|
+
'marketPublish.validation.emptySystemRole': 'Cannot publish: System Role is required',
|
|
297
300
|
'memory.enabled.desc':
|
|
298
301
|
'Allow LobeHub to extract preferences and info from conversations and use them later. You can view, edit, or clear memory anytime.',
|
|
299
302
|
'memory.enabled.title': 'Enable Memory',
|
|
@@ -17,7 +17,7 @@ const socialPublicProcedure = publicProcedure
|
|
|
17
17
|
.use(marketSDK);
|
|
18
18
|
|
|
19
19
|
// Schema definitions
|
|
20
|
-
const targetTypeSchema = z.enum(['agent', 'plugin']);
|
|
20
|
+
const targetTypeSchema = z.enum(['agent', 'plugin', 'agent-group']);
|
|
21
21
|
|
|
22
22
|
const paginationSchema = z.object({
|
|
23
23
|
limit: z.number().optional(),
|
|
@@ -745,6 +745,7 @@ export class DiscoverService {
|
|
|
745
745
|
title: item.name || item.identifier,
|
|
746
746
|
tokenUsage: item.tokenUsage || 0,
|
|
747
747
|
type: item.type,
|
|
748
|
+
updatedAt: item.updatedAt,
|
|
748
749
|
userName: normalizedAuthor.userName,
|
|
749
750
|
};
|
|
750
751
|
});
|
|
@@ -1710,6 +1711,8 @@ export class DiscoverService {
|
|
|
1710
1711
|
locale,
|
|
1711
1712
|
})) as UserInfoResponse & {
|
|
1712
1713
|
agentGroups?: any[];
|
|
1714
|
+
favoriteAgentGroups?: any[];
|
|
1715
|
+
favoriteAgents?: any[];
|
|
1713
1716
|
forkedAgentGroups?: any[];
|
|
1714
1717
|
forkedAgents?: any[];
|
|
1715
1718
|
};
|
|
@@ -1719,7 +1722,7 @@ export class DiscoverService {
|
|
|
1719
1722
|
return undefined;
|
|
1720
1723
|
}
|
|
1721
1724
|
|
|
1722
|
-
const { user, agents, agentGroups, forkedAgents, forkedAgentGroups } = response;
|
|
1725
|
+
const { user, agents, agentGroups, forkedAgents, forkedAgentGroups, favoriteAgents, favoriteAgentGroups } = response;
|
|
1723
1726
|
|
|
1724
1727
|
// Transform agents to DiscoverAssistantItem format
|
|
1725
1728
|
const transformedAgents: DiscoverAssistantItem[] = (agents || []).map((agent: any) => ({
|
|
@@ -1811,9 +1814,59 @@ export class DiscoverService {
|
|
|
1811
1814
|
updatedAt: group.updatedAt,
|
|
1812
1815
|
}));
|
|
1813
1816
|
|
|
1817
|
+
// Transform favoriteAgents to DiscoverAssistantItem format
|
|
1818
|
+
const transformedFavoriteAgents: DiscoverAssistantItem[] = (favoriteAgents || []).map(
|
|
1819
|
+
(agent: any) => ({
|
|
1820
|
+
author: agent.author || '',
|
|
1821
|
+
avatar: agent.avatar || '',
|
|
1822
|
+
category: agent.category as any,
|
|
1823
|
+
config: {} as any,
|
|
1824
|
+
createdAt: agent.createdAt,
|
|
1825
|
+
description: agent.description || '',
|
|
1826
|
+
forkCount: agent.forkCount || 0,
|
|
1827
|
+
forkedFromAgentId: agent.forkedFromAgentId || null,
|
|
1828
|
+
homepage: `https://lobehub.com/discover/assistant/${agent.identifier}`,
|
|
1829
|
+
identifier: agent.identifier,
|
|
1830
|
+
installCount: agent.installCount,
|
|
1831
|
+
isValidated: agent.isValidated,
|
|
1832
|
+
knowledgeCount: agent.knowledgeCount || 0,
|
|
1833
|
+
pluginCount: agent.pluginCount || 0,
|
|
1834
|
+
schemaVersion: 1,
|
|
1835
|
+
status: agent.status,
|
|
1836
|
+
tags: agent.tags || [],
|
|
1837
|
+
title: agent.name || agent.identifier,
|
|
1838
|
+
tokenUsage: agent.tokenUsage || 0,
|
|
1839
|
+
}),
|
|
1840
|
+
);
|
|
1841
|
+
|
|
1842
|
+
// Transform favoriteAgentGroups to DiscoverGroupAgentItem format
|
|
1843
|
+
const transformedFavoriteAgentGroups = (favoriteAgentGroups || []).map((group: any) => ({
|
|
1844
|
+
author: group.author || '',
|
|
1845
|
+
avatar: group.avatar || '👥',
|
|
1846
|
+
category: group.category as any,
|
|
1847
|
+
createdAt: group.createdAt,
|
|
1848
|
+
description: group.description || '',
|
|
1849
|
+
forkCount: group.forkCount || 0,
|
|
1850
|
+
forkedFromGroupId: group.forkedFromGroupId || null,
|
|
1851
|
+
homepage: `https://lobehub.com/discover/group_agent/${group.identifier}`,
|
|
1852
|
+
identifier: group.identifier,
|
|
1853
|
+
installCount: group.installCount || 0,
|
|
1854
|
+
isFeatured: group.isFeatured || false,
|
|
1855
|
+
isOfficial: group.isOfficial || false,
|
|
1856
|
+
isValidated: group.isValidated,
|
|
1857
|
+
memberCount: 0, // Will be populated from memberAgents in detail view
|
|
1858
|
+
schemaVersion: 1,
|
|
1859
|
+
status: group.status,
|
|
1860
|
+
tags: group.tags || [],
|
|
1861
|
+
title: group.name || group.identifier,
|
|
1862
|
+
updatedAt: group.updatedAt,
|
|
1863
|
+
}));
|
|
1864
|
+
|
|
1814
1865
|
const result: DiscoverUserProfile = {
|
|
1815
1866
|
agentGroups: transformedAgentGroups,
|
|
1816
1867
|
agents: transformedAgents,
|
|
1868
|
+
favoriteAgentGroups: transformedFavoriteAgentGroups,
|
|
1869
|
+
favoriteAgents: transformedFavoriteAgents,
|
|
1817
1870
|
forkedAgentGroups: transformedForkedAgentGroups,
|
|
1818
1871
|
forkedAgents: transformedForkedAgents,
|
|
1819
1872
|
user: {
|
|
@@ -1833,11 +1886,13 @@ export class DiscoverService {
|
|
|
1833
1886
|
};
|
|
1834
1887
|
|
|
1835
1888
|
log(
|
|
1836
|
-
'getUserInfo: returning user profile with %d agents, %d groups, %d forked agents, %d forked groups',
|
|
1889
|
+
'getUserInfo: returning user profile with %d agents, %d groups, %d forked agents, %d forked groups, %d favorite agents, %d favorite groups',
|
|
1837
1890
|
result.agents.length,
|
|
1838
1891
|
result.agentGroups?.length || 0,
|
|
1839
1892
|
result.forkedAgents?.length || 0,
|
|
1840
1893
|
result.forkedAgentGroups?.length || 0,
|
|
1894
|
+
result.favoriteAgents?.length || 0,
|
|
1895
|
+
result.favoriteAgentGroups?.length || 0,
|
|
1841
1896
|
);
|
|
1842
1897
|
return result;
|
|
1843
1898
|
} catch (error) {
|
package/src/services/models.ts
CHANGED
|
@@ -75,7 +75,6 @@ export class ModelsService {
|
|
|
75
75
|
const runtimeProvider = resolveRuntimeProvider(provider);
|
|
76
76
|
const enableFetchOnClient = isEnableFetchOnClient(provider);
|
|
77
77
|
|
|
78
|
-
console.log('enableFetchOnClient:', enableFetchOnClient);
|
|
79
78
|
let res: Response;
|
|
80
79
|
if (enableFetchOnClient) {
|
|
81
80
|
const agentRuntime = await initializeWithClientStore({
|
package/src/services/social.ts
CHANGED