@lobehub/lobehub 2.0.0-next.276 → 2.0.0-next.277
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 +26 -0
- package/changelog/v1.json +9 -0
- package/locales/en-US/setting.json +11 -0
- package/locales/zh-CN/setting.json +11 -0
- package/package.json +1 -1
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/BatchCreateAgents/index.tsx +2 -2
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/UpdateGroup/index.tsx +56 -56
- package/packages/builtin-tool-group-agent-builder/src/client/Render/BatchCreateAgents.tsx +3 -2
- package/packages/builtin-tool-group-agent-builder/src/executor.ts +2 -1
- package/packages/types/src/agentCronJob/index.ts +19 -23
- package/packages/types/src/serverConfig.ts +1 -0
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/Actions.tsx +31 -0
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/CronTopicGroup.tsx +10 -6
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/index.tsx +7 -11
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/useDropdownMenu.tsx +102 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/CronConfig.ts +179 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobContentEditor.tsx +111 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobHeader.tsx +45 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobSaveButton.tsx +31 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobScheduleConfig.tsx +213 -0
- package/src/app/[variants]/(main)/agent/cron/[cronId]/index.tsx +186 -344
- package/src/app/[variants]/(main)/agent/profile/features/AgentCronJobs/index.tsx +42 -97
- package/src/app/[variants]/(main)/agent/profile/features/ProfileEditor/index.tsx +4 -20
- package/src/app/[variants]/(main)/community/features/UserAvatar/index.tsx +15 -5
- package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/AgentProfilePopup.tsx +1 -6
- package/src/server/globalConfig/index.ts +1 -0
- package/src/services/chatGroup/index.ts +1 -4
- package/src/store/serverConfig/selectors.ts +1 -0
|
@@ -2,38 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const';
|
|
4
4
|
import { Flexbox } from '@lobehub/ui';
|
|
5
|
-
import {
|
|
5
|
+
import { Typography } from 'antd';
|
|
6
6
|
import { Clock } from 'lucide-react';
|
|
7
|
-
import { memo,
|
|
7
|
+
import { memo, useCallback } from 'react';
|
|
8
8
|
import { useTranslation } from 'react-i18next';
|
|
9
|
+
import urlJoin from 'url-join';
|
|
9
10
|
|
|
11
|
+
import { useQueryRoute } from '@/hooks/useQueryRoute';
|
|
10
12
|
import { useAgentStore } from '@/store/agent';
|
|
11
13
|
|
|
12
14
|
import CronJobCards from './CronJobCards';
|
|
13
|
-
import CronJobForm from './CronJobForm';
|
|
14
15
|
import { useAgentCronJobs } from './hooks/useAgentCronJobs';
|
|
15
16
|
|
|
16
17
|
const { Title } = Typography;
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
onFormModalChange?: (show: boolean) => void;
|
|
20
|
-
showFormModal?: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const AgentCronJobs = memo<AgentCronJobsProps>(({ showFormModal, onFormModalChange }) => {
|
|
19
|
+
const AgentCronJobs = memo(() => {
|
|
24
20
|
const { t } = useTranslation('setting');
|
|
25
21
|
const agentId = useAgentStore((s) => s.activeAgentId);
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
const formRef = useRef<any>(null);
|
|
22
|
+
const router = useQueryRoute();
|
|
23
|
+
|
|
24
|
+
const { cronJobs, loading, deleteCronJob } = useAgentCronJobs(agentId);
|
|
30
25
|
|
|
31
|
-
//
|
|
32
|
-
const
|
|
33
|
-
|
|
26
|
+
// Edit: Navigate to cron job detail page
|
|
27
|
+
const handleEdit = useCallback(
|
|
28
|
+
(jobId: string) => {
|
|
29
|
+
if (!agentId) return;
|
|
30
|
+
router.push(urlJoin('/agent', agentId, 'cron', jobId));
|
|
31
|
+
},
|
|
32
|
+
[agentId, router],
|
|
33
|
+
);
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
// Delete: Keep the existing delete logic
|
|
36
|
+
const handleDelete = useCallback(
|
|
37
|
+
async (jobId: string) => {
|
|
38
|
+
await deleteCronJob(jobId);
|
|
39
|
+
},
|
|
40
|
+
[deleteCronJob],
|
|
41
|
+
);
|
|
37
42
|
|
|
38
43
|
if (!ENABLE_BUSINESS_FEATURES) return null;
|
|
39
44
|
|
|
@@ -41,89 +46,29 @@ const AgentCronJobs = memo<AgentCronJobsProps>(({ showFormModal, onFormModalChan
|
|
|
41
46
|
return null;
|
|
42
47
|
}
|
|
43
48
|
|
|
44
|
-
const handleCreate = async (data: any) => {
|
|
45
|
-
setSubmitting(true);
|
|
46
|
-
try {
|
|
47
|
-
await createCronJob(data);
|
|
48
|
-
setShowForm(false);
|
|
49
|
-
} finally {
|
|
50
|
-
setSubmitting(false);
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const handleEdit = (jobId: string) => {
|
|
55
|
-
setEditingJob(jobId);
|
|
56
|
-
setShowForm(true);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const handleUpdate = async (data: any) => {
|
|
60
|
-
if (editingJob) {
|
|
61
|
-
setSubmitting(true);
|
|
62
|
-
try {
|
|
63
|
-
await updateCronJob(editingJob, data);
|
|
64
|
-
setShowForm(false);
|
|
65
|
-
setEditingJob(null);
|
|
66
|
-
} finally {
|
|
67
|
-
setSubmitting(false);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const handleCancel = () => {
|
|
73
|
-
setShowForm(false);
|
|
74
|
-
setEditingJob(null);
|
|
75
|
-
formRef.current?.resetFields();
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const handleModalOk = () => {
|
|
79
|
-
formRef.current?.submit();
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const handleDelete = async (jobId: string) => {
|
|
83
|
-
await deleteCronJob(jobId);
|
|
84
|
-
};
|
|
85
|
-
|
|
86
49
|
const hasCronJobs = cronJobs && cronJobs.length > 0;
|
|
87
50
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
<Flexbox gap={12} style={{ marginBottom: 16, marginTop: 16 }}>
|
|
93
|
-
<Title level={5} style={{ margin: 0 }}>
|
|
94
|
-
<Flexbox align="center" gap={8} horizontal>
|
|
95
|
-
<Clock size={16} />
|
|
96
|
-
{t('agentCronJobs.title')}
|
|
97
|
-
</Flexbox>
|
|
98
|
-
</Title>
|
|
51
|
+
// Only show if there are jobs
|
|
52
|
+
if (!hasCronJobs) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
99
55
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
56
|
+
return (
|
|
57
|
+
<Flexbox gap={12} style={{ marginBottom: 16, marginTop: 16 }}>
|
|
58
|
+
<Title level={5} style={{ margin: 0 }}>
|
|
59
|
+
<Flexbox align="center" gap={8} horizontal>
|
|
60
|
+
<Clock size={16} />
|
|
61
|
+
{t('agentCronJobs.title')}
|
|
106
62
|
</Flexbox>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
title={editingJob ? t('agentCronJobs.editJob') : t('agentCronJobs.addJob')}
|
|
117
|
-
width={640}
|
|
118
|
-
>
|
|
119
|
-
<CronJobForm
|
|
120
|
-
editingJob={editingJob ? cronJobs?.find((job) => job.id === editingJob) : undefined}
|
|
121
|
-
formRef={formRef}
|
|
122
|
-
onCancel={handleCancel}
|
|
123
|
-
onSubmit={editingJob ? handleUpdate : handleCreate}
|
|
124
|
-
/>
|
|
125
|
-
</Modal>
|
|
126
|
-
</>
|
|
63
|
+
</Title>
|
|
64
|
+
|
|
65
|
+
<CronJobCards
|
|
66
|
+
cronJobs={cronJobs}
|
|
67
|
+
loading={loading}
|
|
68
|
+
onDelete={handleDelete}
|
|
69
|
+
onEdit={handleEdit}
|
|
70
|
+
/>
|
|
71
|
+
</Flexbox>
|
|
127
72
|
);
|
|
128
73
|
});
|
|
129
74
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const';
|
|
4
4
|
import { Button, Flexbox } from '@lobehub/ui';
|
|
5
|
-
import { Divider
|
|
5
|
+
import { Divider } from 'antd';
|
|
6
6
|
import isEqual from 'fast-deep-equal';
|
|
7
7
|
import { Clock, PlayIcon } from 'lucide-react';
|
|
8
8
|
import React, { memo, useCallback } from 'react';
|
|
@@ -11,7 +11,6 @@ import urlJoin from 'url-join';
|
|
|
11
11
|
|
|
12
12
|
import ModelSelect from '@/features/ModelSelect';
|
|
13
13
|
import { useQueryRoute } from '@/hooks/useQueryRoute';
|
|
14
|
-
import { agentCronJobService } from '@/services/agentCronJob';
|
|
15
14
|
import { useAgentStore } from '@/store/agent';
|
|
16
15
|
import { agentSelectors } from '@/store/agent/selectors';
|
|
17
16
|
import { useChatStore } from '@/store/chat';
|
|
@@ -29,25 +28,10 @@ const ProfileEditor = memo(() => {
|
|
|
29
28
|
const switchTopic = useChatStore((s) => s.switchTopic);
|
|
30
29
|
const router = useQueryRoute();
|
|
31
30
|
|
|
32
|
-
const handleCreateCronJob = useCallback(
|
|
31
|
+
const handleCreateCronJob = useCallback(() => {
|
|
33
32
|
if (!agentId) return;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
agentId,
|
|
37
|
-
content: t('agentCronJobs.form.content.placeholder') || 'This is a cron job',
|
|
38
|
-
cronPattern: '*/30 * * * *',
|
|
39
|
-
enabled: true,
|
|
40
|
-
name: t('agentCronJobs.addJob') || 'Cron Job Task',
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
if (result.success) {
|
|
44
|
-
router.push(urlJoin('/agent', agentId, 'cron', result.data.id));
|
|
45
|
-
}
|
|
46
|
-
} catch (error) {
|
|
47
|
-
console.error('Failed to create cron job:', error);
|
|
48
|
-
message.error('Failed to create scheduled task');
|
|
49
|
-
}
|
|
50
|
-
}, [agentId, router, t]);
|
|
33
|
+
router.push(urlJoin('/agent', agentId, 'cron', 'new'));
|
|
34
|
+
}, [agentId, router]);
|
|
51
35
|
|
|
52
36
|
return (
|
|
53
37
|
<>
|
|
@@ -16,7 +16,14 @@ import { serverConfigSelectors } from '@/store/serverConfig/selectors';
|
|
|
16
16
|
*/
|
|
17
17
|
const checkNeedsProfileSetup = (
|
|
18
18
|
enableMarketTrustedClient: boolean,
|
|
19
|
-
userProfile:
|
|
19
|
+
userProfile:
|
|
20
|
+
| {
|
|
21
|
+
avatarUrl: string | null;
|
|
22
|
+
bannerUrl: string | null;
|
|
23
|
+
socialLinks: { github?: string; twitter?: string; website?: string } | null;
|
|
24
|
+
}
|
|
25
|
+
| null
|
|
26
|
+
| undefined,
|
|
20
27
|
): boolean => {
|
|
21
28
|
if (!enableMarketTrustedClient) return false;
|
|
22
29
|
if (!userProfile) return true;
|
|
@@ -33,7 +40,9 @@ const UserAvatar = memo(() => {
|
|
|
33
40
|
const [loading, setLoading] = useState(false);
|
|
34
41
|
const { isAuthenticated, isLoading, getCurrentUserInfo, signIn } = useMarketAuth();
|
|
35
42
|
|
|
36
|
-
const enableMarketTrustedClient = useServerConfigStore(
|
|
43
|
+
const enableMarketTrustedClient = useServerConfigStore(
|
|
44
|
+
serverConfigSelectors.enableMarketTrustedClient,
|
|
45
|
+
);
|
|
37
46
|
|
|
38
47
|
const userInfo = getCurrentUserInfo();
|
|
39
48
|
const username = userInfo?.sub;
|
|
@@ -70,8 +79,9 @@ const UserAvatar = memo(() => {
|
|
|
70
79
|
return <Skeleton.Avatar active shape={'square'} size={28} style={{ borderRadius: 6 }} />;
|
|
71
80
|
}
|
|
72
81
|
|
|
73
|
-
//
|
|
74
|
-
|
|
82
|
+
// 如果启用了 trustedClient,不显示"成为创作者"按钮,直接显示头像
|
|
83
|
+
// 否则,未认证或需要完善资料时,显示登录按钮
|
|
84
|
+
if (!enableMarketTrustedClient && (!isAuthenticated || needsProfileSetup)) {
|
|
75
85
|
return (
|
|
76
86
|
<Button
|
|
77
87
|
icon={UserCircleIcon}
|
|
@@ -92,7 +102,7 @@ const UserAvatar = memo(() => {
|
|
|
92
102
|
|
|
93
103
|
return (
|
|
94
104
|
<Avatar
|
|
95
|
-
avatar={avatarUrl || userProfile?.userName}
|
|
105
|
+
avatar={avatarUrl || userProfile?.userName || username}
|
|
96
106
|
onClick={handleAvatarClick}
|
|
97
107
|
shape={'square'}
|
|
98
108
|
size={28}
|
|
@@ -136,12 +136,7 @@ const AgentProfilePopup = memo<AgentProfilePopupProps>(({ agent, groupId, childr
|
|
|
136
136
|
</Text>
|
|
137
137
|
|
|
138
138
|
{/* Settings Button */}
|
|
139
|
-
<Flexbox
|
|
140
|
-
align="center"
|
|
141
|
-
horizontal
|
|
142
|
-
justify="flex-end"
|
|
143
|
-
style={{ paddingBlockStart: 0 }}
|
|
144
|
-
>
|
|
139
|
+
<Flexbox align="center" horizontal justify="flex-end" style={{ paddingBlockStart: 0 }}>
|
|
145
140
|
<ActionIcon
|
|
146
141
|
icon={Settings}
|
|
147
142
|
onClick={handleSettings}
|
|
@@ -74,6 +74,7 @@ export const getServerGlobalConfig = async () => {
|
|
|
74
74
|
defaultAgent: {
|
|
75
75
|
config: parseAgentConfig(DEFAULT_AGENT_CONFIG),
|
|
76
76
|
},
|
|
77
|
+
enableBusinessFeatures: ENABLE_BUSINESS_FEATURES,
|
|
77
78
|
enableEmailVerification: authEnv.AUTH_EMAIL_VERIFICATION,
|
|
78
79
|
enableKlavis: !!klavisEnv.KLAVIS_API_KEY,
|
|
79
80
|
enableLobehubSkill: !!(appEnv.MARKET_TRUSTED_CLIENT_SECRET && appEnv.MARKET_TRUSTED_CLIENT_ID),
|
|
@@ -89,10 +89,7 @@ class ChatGroupService {
|
|
|
89
89
|
* Batch create virtual agents and add them to an existing group.
|
|
90
90
|
* This is more efficient than calling createAgentOnly multiple times.
|
|
91
91
|
*/
|
|
92
|
-
batchCreateAgentsInGroup = (
|
|
93
|
-
groupId: string,
|
|
94
|
-
agents: GroupMemberConfig[],
|
|
95
|
-
) => {
|
|
92
|
+
batchCreateAgentsInGroup = (groupId: string, agents: GroupMemberConfig[]) => {
|
|
96
93
|
return lambdaClient.group.batchCreateAgentsInGroup.mutate({
|
|
97
94
|
agents: agents as Partial<AgentItem>[],
|
|
98
95
|
groupId,
|
|
@@ -3,6 +3,7 @@ import { type ServerConfigStore } from './store';
|
|
|
3
3
|
export const featureFlagsSelectors = (s: ServerConfigStore) => s.featureFlags;
|
|
4
4
|
|
|
5
5
|
export const serverConfigSelectors = {
|
|
6
|
+
enableBusinessFeatures: (s: ServerConfigStore) => s.serverConfig.enableBusinessFeatures || false,
|
|
6
7
|
enableEmailVerification: (s: ServerConfigStore) =>
|
|
7
8
|
s.serverConfig.enableEmailVerification || false,
|
|
8
9
|
enableKlavis: (s: ServerConfigStore) => s.serverConfig.enableKlavis || false,
|