@lobehub/lobehub 2.0.13 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v2.json +18 -0
  3. package/docker-compose/deploy/.env.example +35 -0
  4. package/docker-compose/deploy/.env.zh-CN.example +31 -0
  5. package/docker-compose/deploy/bucket.config.json +18 -0
  6. package/docker-compose/deploy/docker-compose.yml +148 -0
  7. package/docker-compose/deploy/searxng-settings.yml +2582 -0
  8. package/docker-compose/setup.sh +37 -88
  9. package/docs/self-hosting/advanced/auth/providers/casdoor.mdx +110 -0
  10. package/docs/self-hosting/advanced/auth/providers/casdoor.zh-CN.mdx +165 -0
  11. package/docs/self-hosting/platform/docker-compose.mdx +43 -561
  12. package/docs/self-hosting/platform/docker-compose.zh-CN.mdx +40 -537
  13. package/locales/en-US/setting.json +16 -0
  14. package/locales/zh-CN/setting.json +16 -0
  15. package/package.json +1 -1
  16. package/packages/const/src/url.ts +1 -1
  17. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/index.tsx +4 -2
  18. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobContentEditor.tsx +39 -44
  19. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobHeader.tsx +27 -20
  20. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobSaveButton.tsx +4 -2
  21. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobScheduleConfig.tsx +183 -145
  22. package/src/app/[variants]/(main)/agent/profile/features/AgentCronJobs/hooks/useAgentCronJobs.ts +3 -4
  23. package/src/app/[variants]/(main)/agent/profile/features/AgentCronJobs/index.tsx +4 -3
  24. package/src/app/[variants]/(main)/agent/profile/features/ProfileEditor/index.tsx +4 -3
  25. package/src/features/Conversation/Messages/AssistantGroup/components/MessageContent.tsx +6 -1
  26. package/src/locales/default/setting.ts +16 -0
  27. package/src/store/agent/slices/cron/action.ts +6 -4
@@ -1,17 +1,62 @@
1
- import { Flexbox, Tag, Text } from '@lobehub/ui';
2
- import { Card, InputNumber, Select, TimePicker } from 'antd';
1
+ 'use client';
2
+
3
+ import { Checkbox, Flexbox, FormGroup, LobeSelect as Select, Text } from '@lobehub/ui';
4
+ import { Divider, InputNumber, TimePicker } from 'antd';
5
+ import { createStaticStyles, cx } from 'antd-style';
3
6
  import type { Dayjs } from 'dayjs';
4
7
  import dayjs from 'dayjs';
5
- import { memo, useMemo } from 'react';
8
+ import { memo } from 'react';
6
9
  import { useTranslation } from 'react-i18next';
7
10
 
8
- import {
9
- SCHEDULE_TYPE_OPTIONS,
10
- type ScheduleType,
11
- TIMEZONE_OPTIONS,
12
- WEEKDAY_LABELS,
13
- WEEKDAY_OPTIONS,
14
- } from '../CronConfig';
11
+ import { SCHEDULE_TYPE_OPTIONS, type ScheduleType, TIMEZONE_OPTIONS } from '../CronConfig';
12
+
13
+ const styles = createStaticStyles(({ css, cssVar }) => ({
14
+ label: css`
15
+ flex-shrink: 0;
16
+ width: 120px;
17
+ `,
18
+ row: css`
19
+ min-height: 48px;
20
+ padding-block: 12px;
21
+ padding-inline: 0;
22
+ `,
23
+ weekdayButton: css`
24
+ cursor: pointer;
25
+
26
+ display: flex;
27
+ align-items: center;
28
+ justify-content: center;
29
+
30
+ width: 40px;
31
+ height: 32px;
32
+ border: 1px solid ${cssVar.colorBorder};
33
+ border-radius: 6px;
34
+
35
+ font-size: 12px;
36
+ font-weight: 500;
37
+ color: ${cssVar.colorTextSecondary};
38
+
39
+ background: transparent;
40
+
41
+ transition: all 0.15s ease;
42
+
43
+ &:hover {
44
+ border-color: ${cssVar.colorPrimary};
45
+ color: ${cssVar.colorPrimary};
46
+ }
47
+ `,
48
+ weekdayButtonActive: css`
49
+ border-color: ${cssVar.colorPrimary};
50
+ color: ${cssVar.colorTextLightSolid};
51
+ background: ${cssVar.colorPrimary};
52
+
53
+ &:hover {
54
+ border-color: ${cssVar.colorPrimaryHover};
55
+ color: ${cssVar.colorTextLightSolid};
56
+ background: ${cssVar.colorPrimaryHover};
57
+ }
58
+ `,
59
+ }));
15
60
 
16
61
  interface CronJobScheduleConfigProps {
17
62
  hourlyInterval?: number;
@@ -30,6 +75,16 @@ interface CronJobScheduleConfigProps {
30
75
  weekdays: number[];
31
76
  }
32
77
 
78
+ const WEEKDAYS = [
79
+ { key: 1, label: 'agentCronJobs.weekdays.mon' },
80
+ { key: 2, label: 'agentCronJobs.weekdays.tue' },
81
+ { key: 3, label: 'agentCronJobs.weekdays.wed' },
82
+ { key: 4, label: 'agentCronJobs.weekdays.thu' },
83
+ { key: 5, label: 'agentCronJobs.weekdays.fri' },
84
+ { key: 6, label: 'agentCronJobs.weekdays.sat' },
85
+ { key: 0, label: 'agentCronJobs.weekdays.sun' },
86
+ ];
87
+
33
88
  const CronJobScheduleConfig = memo<CronJobScheduleConfigProps>(
34
89
  ({
35
90
  hourlyInterval,
@@ -42,172 +97,155 @@ const CronJobScheduleConfig = memo<CronJobScheduleConfigProps>(
42
97
  }) => {
43
98
  const { t } = useTranslation('setting');
44
99
 
45
- // Compute summary tags
46
- const summaryTags = useMemo(() => {
47
- const result: Array<{ key: string; label: string }> = [];
48
-
49
- // Schedule type
50
- const scheduleTypeLabel = SCHEDULE_TYPE_OPTIONS.find(
51
- (opt) => opt.value === scheduleType,
52
- )?.label;
53
- if (scheduleTypeLabel) {
54
- result.push({
55
- key: 'scheduleType',
56
- label: t(scheduleTypeLabel as any),
57
- });
58
- }
59
-
60
- // Trigger time
61
- if (scheduleType === 'hourly') {
62
- const minute = triggerTime.minute();
63
- result.push({
64
- key: 'interval',
65
- label: `Every ${hourlyInterval || 1} hour(s) at :${minute.toString().padStart(2, '0')}`,
66
- });
67
- } else {
68
- result.push({
69
- key: 'triggerTime',
70
- label: triggerTime.format('HH:mm'),
71
- });
72
- }
73
-
74
- // Timezone
75
- result.push({
76
- key: 'timezone',
77
- label: timezone,
78
- });
79
-
80
- // Weekdays for weekly schedule
81
- if (scheduleType === 'weekly' && weekdays.length > 0) {
82
- result.push({
83
- key: 'weekdays',
84
- label: weekdays.map((day) => t(WEEKDAY_LABELS[day] as any)).join(', '),
85
- });
86
- }
87
-
88
- return result;
89
- }, [scheduleType, triggerTime, timezone, weekdays, hourlyInterval, t]);
100
+ const toggleWeekday = (day: number) => {
101
+ const newWeekdays = weekdays.includes(day)
102
+ ? weekdays.filter((d) => d !== day)
103
+ : [...weekdays, day];
104
+ onScheduleChange({ weekdays: newWeekdays });
105
+ };
106
+
107
+ const isUnlimited = maxExecutions === null || maxExecutions === undefined;
90
108
 
91
109
  return (
92
- <Card size="small" style={{ borderRadius: 12 }} styles={{ body: { padding: 12 } }}>
93
- <Flexbox gap={12}>
94
- {/* Summary Tags */}
95
- {summaryTags.length > 0 && (
96
- <Flexbox align="center" gap={8} horizontal style={{ flexWrap: 'wrap' }}>
97
- {summaryTags.map((tag) => (
98
- <Tag key={tag.key} variant={'filled'}>
99
- {tag.label}
100
- </Tag>
101
- ))}
102
- </Flexbox>
103
- )}
104
- {/* Schedule Configuration - All in one row */}
105
- <Flexbox align="center" gap={8} horizontal style={{ flexWrap: 'wrap' }}>
106
- <Tag variant={'borderless'}>{t('agentCronJobs.schedule')}</Tag>
107
- <Select
108
- onChange={(value: ScheduleType) =>
109
- onScheduleChange({
110
- scheduleType: value,
111
- weekdays: value === 'weekly' ? [0, 1, 2, 3, 4, 5, 6] : [],
112
- })
113
- }
114
- options={SCHEDULE_TYPE_OPTIONS.map((opt) => ({
115
- label: t(opt.label as any),
116
- value: opt.value,
117
- }))}
118
- size="small"
119
- style={{ minWidth: 120 }}
120
- value={scheduleType}
121
- />
110
+ <FormGroup title={t('agentCronJobs.schedule')} variant="filled">
111
+ {/* Frequency Row */}
112
+ <Flexbox align="center" className={styles.row} gap={24} horizontal>
113
+ <Text className={styles.label}>{t('agentCronJobs.form.frequency')}</Text>
114
+ <Select
115
+ onChange={(value: ScheduleType) =>
116
+ onScheduleChange({
117
+ scheduleType: value,
118
+ weekdays: value === 'weekly' ? [1, 2, 3, 4, 5] : [],
119
+ })
120
+ }
121
+ options={SCHEDULE_TYPE_OPTIONS.map((opt) => ({
122
+ label: t(opt.label as any),
123
+ value: opt.value,
124
+ }))}
125
+ style={{ width: 140 }}
126
+ value={scheduleType}
127
+ variant="outlined"
128
+ />
129
+ </Flexbox>
122
130
 
123
- {/* Weekdays - show only for weekly */}
124
- {scheduleType === 'weekly' && (
125
- <Select
126
- maxTagCount="responsive"
127
- mode="multiple"
128
- onChange={(values: number[]) => onScheduleChange({ weekdays: values })}
129
- options={WEEKDAY_OPTIONS.map((opt) => ({
130
- label: t(opt.label as any),
131
- value: opt.value,
132
- }))}
133
- placeholder="Select days"
134
- size="small"
135
- style={{ minWidth: 150 }}
136
- value={weekdays}
137
- />
138
- )}
131
+ <Divider style={{ margin: 0 }} />
139
132
 
140
- {/* Trigger Time - show for daily and weekly */}
141
- {scheduleType !== 'hourly' && (
133
+ {/* Time Row (for daily/weekly) */}
134
+ {scheduleType !== 'hourly' && (
135
+ <>
136
+ <Flexbox align="center" className={styles.row} gap={24} horizontal>
137
+ <Text className={styles.label}>{t('agentCronJobs.form.time')}</Text>
142
138
  <TimePicker
143
139
  format="HH:mm"
144
- minuteStep={30}
140
+ minuteStep={15}
145
141
  onChange={(value) => {
146
142
  if (value) onScheduleChange({ triggerTime: value });
147
143
  }}
148
- size="small"
149
- style={{ minWidth: 120 }}
150
- value={triggerTime ?? dayjs().hour(0).minute(0)}
144
+ style={{ width: 120 }}
145
+ value={triggerTime ?? dayjs().hour(9).minute(0)}
151
146
  />
152
- )}
153
-
154
- {/* Hourly Interval - show only for hourly */}
155
- {scheduleType === 'hourly' && (
156
- <>
157
- <Tag variant={'borderless'}>Every</Tag>
147
+ </Flexbox>
148
+ <Divider style={{ margin: 0 }} />
149
+ </>
150
+ )}
151
+
152
+ {/* Hourly Interval Row */}
153
+ {scheduleType === 'hourly' && (
154
+ <>
155
+ <Flexbox align="center" className={styles.row} gap={24} horizontal>
156
+ <Text className={styles.label}>{t('agentCronJobs.form.every')}</Text>
157
+ <Flexbox align="center" gap={8} horizontal>
158
158
  <InputNumber
159
159
  max={24}
160
160
  min={1}
161
- onChange={(value: number | null) =>
162
- onScheduleChange({ hourlyInterval: value ?? 1 })
163
- }
164
- size="small"
165
- style={{ width: 80 }}
161
+ onChange={(value) => onScheduleChange({ hourlyInterval: value ?? 1 })}
162
+ style={{ width: 70 }}
166
163
  value={hourlyInterval ?? 1}
167
164
  />
168
- <Text type="secondary">hour(s) at</Text>
165
+ <Text type="secondary">{t('agentCronJobs.form.hours')}</Text>
166
+ <Text type="secondary">{t('agentCronJobs.form.at')}</Text>
169
167
  <Select
170
168
  onChange={(value: number) =>
171
169
  onScheduleChange({ triggerTime: dayjs().hour(0).minute(value) })
172
170
  }
173
171
  options={[
174
172
  { label: ':00', value: 0 },
173
+ { label: ':15', value: 15 },
175
174
  { label: ':30', value: 30 },
175
+ { label: ':45', value: 45 },
176
176
  ]}
177
- size="small"
178
- style={{ width: 80 }}
177
+ style={{ width: '80px' }}
179
178
  value={triggerTime?.minute() ?? 0}
179
+ variant="outlined"
180
180
  />
181
- </>
182
- )}
183
-
184
- {/* Timezone */}
185
- <Select
186
- onChange={(value: string) => onScheduleChange({ timezone: value })}
187
- options={TIMEZONE_OPTIONS}
188
- showSearch
189
- size="small"
190
- style={{ maxWidth: 300, minWidth: 200 }}
191
- value={timezone}
192
- />
193
- </Flexbox>
181
+ </Flexbox>
182
+ </Flexbox>
183
+ <Divider style={{ margin: 0 }} />
184
+ </>
185
+ )}
186
+
187
+ {/* Weekday Selector (only for weekly) */}
188
+ {scheduleType === 'weekly' && (
189
+ <>
190
+ <Flexbox align="center" className={styles.row} gap={24} horizontal>
191
+ <Text className={styles.label}>{t('agentCronJobs.weekdays')}</Text>
192
+ <Flexbox gap={6} horizontal>
193
+ {WEEKDAYS.map(({ key, label }) => (
194
+ <div
195
+ className={cx(
196
+ styles.weekdayButton,
197
+ weekdays.includes(key) && styles.weekdayButtonActive,
198
+ )}
199
+ key={key}
200
+ onClick={() => toggleWeekday(key)}
201
+ >
202
+ {t(label as any)}
203
+ </div>
204
+ ))}
205
+ </Flexbox>
206
+ </Flexbox>
207
+ <Divider style={{ margin: 0 }} />
208
+ </>
209
+ )}
210
+
211
+ {/* Timezone Row */}
212
+ <Flexbox align="center" className={styles.row} gap={24} horizontal>
213
+ <Text className={styles.label}>{t('agentCronJobs.form.timezone')}</Text>
214
+ <Select
215
+ onChange={(value: string) => onScheduleChange({ timezone: value })}
216
+ options={TIMEZONE_OPTIONS}
217
+ popupMatchSelectWidth={false}
218
+ showSearch
219
+ style={{ minWidth: '200px', width: 'fit-content' }}
220
+ value={timezone}
221
+ variant="outlined"
222
+ />
223
+ </Flexbox>
224
+
225
+ <Divider style={{ margin: 0 }} />
194
226
 
195
- {/* Max Executions */}
196
- <Flexbox align="center" gap={8} horizontal style={{ flexWrap: 'wrap' }}>
197
- <Tag variant={'borderless'}>{t('agentCronJobs.maxExecutions')}</Tag>
227
+ {/* Execution Limit Row */}
228
+ <Flexbox align="center" className={styles.row} gap={24} horizontal>
229
+ <Text className={styles.label}>{t('agentCronJobs.maxExecutions')}</Text>
230
+ <Flexbox align="center" gap={12} horizontal>
198
231
  <InputNumber
232
+ disabled={isUnlimited}
199
233
  min={1}
200
- onChange={(value: number | null) =>
201
- onScheduleChange({ maxExecutions: value ?? null })
202
- }
203
- placeholder={t('agentCronJobs.form.maxExecutions.placeholder')}
204
- size="small"
205
- style={{ width: 160 }}
206
- value={maxExecutions ?? null}
234
+ onChange={(value) => onScheduleChange({ maxExecutions: value })}
235
+ placeholder="100"
236
+ style={{ width: 100 }}
237
+ value={maxExecutions ?? undefined}
207
238
  />
239
+ <Text type="secondary">{t('agentCronJobs.form.times')}</Text>
240
+ <Checkbox
241
+ checked={isUnlimited}
242
+ onChange={(checked) => onScheduleChange({ maxExecutions: checked ? null : 100 })}
243
+ >
244
+ {t('agentCronJobs.form.unlimited')}
245
+ </Checkbox>
208
246
  </Flexbox>
209
247
  </Flexbox>
210
- </Card>
248
+ </FormGroup>
211
249
  );
212
250
  },
213
251
  );
@@ -1,4 +1,3 @@
1
- import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const';
2
1
  import { message } from 'antd';
3
2
  import { useCallback } from 'react';
4
3
  import { useTranslation } from 'react-i18next';
@@ -10,7 +9,7 @@ import type {
10
9
  } from '@/database/schemas/agentCronJob';
11
10
  import { agentCronJobService } from '@/services/agentCronJob';
12
11
 
13
- export const useAgentCronJobs = (agentId?: string) => {
12
+ export const useAgentCronJobs = (agentId?: string, enabled: boolean = true) => {
14
13
  const { t } = useTranslation('setting');
15
14
 
16
15
  // Fetch cron jobs for the agent
@@ -20,8 +19,8 @@ export const useAgentCronJobs = (agentId?: string) => {
20
19
  isLoading: loading,
21
20
  mutate,
22
21
  } = useSWR(
23
- ENABLE_BUSINESS_FEATURES && agentId ? `/api/agent-cron-jobs/${agentId}` : null,
24
- ENABLE_BUSINESS_FEATURES && agentId ? () => agentCronJobService.getByAgentId(agentId) : null,
22
+ enabled && agentId ? `/api/agent-cron-jobs/${agentId}` : null,
23
+ enabled && agentId ? () => agentCronJobService.getByAgentId(agentId) : null,
25
24
  {
26
25
  onError: (error) => {
27
26
  console.error('Failed to fetch cron jobs:', error);
@@ -1,6 +1,5 @@
1
1
  'use client';
2
2
 
3
- import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const';
4
3
  import { Flexbox } from '@lobehub/ui';
5
4
  import { Typography } from 'antd';
6
5
  import { Clock } from 'lucide-react';
@@ -10,6 +9,7 @@ import urlJoin from 'url-join';
10
9
 
11
10
  import { useQueryRoute } from '@/hooks/useQueryRoute';
12
11
  import { useAgentStore } from '@/store/agent';
12
+ import { serverConfigSelectors, useServerConfigStore } from '@/store/serverConfig';
13
13
 
14
14
  import CronJobCards from './CronJobCards';
15
15
  import { useAgentCronJobs } from './hooks/useAgentCronJobs';
@@ -20,8 +20,9 @@ const AgentCronJobs = memo(() => {
20
20
  const { t } = useTranslation('setting');
21
21
  const agentId = useAgentStore((s) => s.activeAgentId);
22
22
  const router = useQueryRoute();
23
+ const enableBusinessFeatures = useServerConfigStore(serverConfigSelectors.enableBusinessFeatures);
23
24
 
24
- const { cronJobs, loading, deleteCronJob } = useAgentCronJobs(agentId);
25
+ const { cronJobs, loading, deleteCronJob } = useAgentCronJobs(agentId, enableBusinessFeatures);
25
26
 
26
27
  // Edit: Navigate to cron job detail page
27
28
  const handleEdit = useCallback(
@@ -40,7 +41,7 @@ const AgentCronJobs = memo(() => {
40
41
  [deleteCronJob],
41
42
  );
42
43
 
43
- if (!ENABLE_BUSINESS_FEATURES) return null;
44
+ if (!enableBusinessFeatures) return null;
44
45
 
45
46
  if (!agentId) {
46
47
  return null;
@@ -1,6 +1,5 @@
1
1
  'use client';
2
2
 
3
- import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const';
4
3
  import { Button, Flexbox } from '@lobehub/ui';
5
4
  import { Divider } from 'antd';
6
5
  import { useTheme } from 'antd-style';
@@ -15,6 +14,7 @@ import { useQueryRoute } from '@/hooks/useQueryRoute';
15
14
  import { useAgentStore } from '@/store/agent';
16
15
  import { agentSelectors } from '@/store/agent/selectors';
17
16
  import { useChatStore } from '@/store/chat';
17
+ import { serverConfigSelectors, useServerConfigStore } from '@/store/serverConfig';
18
18
 
19
19
  import AgentCronJobs from '../AgentCronJobs';
20
20
  import AgentSettings from '../AgentSettings';
@@ -31,6 +31,7 @@ const ProfileEditor = memo(() => {
31
31
  const agentId = useAgentStore((s) => s.activeAgentId);
32
32
  const switchTopic = useChatStore((s) => s.switchTopic);
33
33
  const router = useQueryRoute();
34
+ const enableBusinessFeatures = useServerConfigStore(serverConfigSelectors.enableBusinessFeatures);
34
35
 
35
36
  const handleCreateCronJob = useCallback(() => {
36
37
  if (!agentId) return;
@@ -95,7 +96,7 @@ const ProfileEditor = memo(() => {
95
96
  {t('startConversation')}
96
97
  </Button>
97
98
  <AgentPublishButton />
98
- {ENABLE_BUSINESS_FEATURES && (
99
+ {enableBusinessFeatures && (
99
100
  <Button icon={Clock} onClick={handleCreateCronJob}>
100
101
  {t('agentCronJobs.addJob')}
101
102
  </Button>
@@ -106,7 +107,7 @@ const ProfileEditor = memo(() => {
106
107
  {/* Main Content: Prompt Editor */}
107
108
  <EditorCanvas />
108
109
  {/* Agent Cron Jobs Display (only show if jobs exist) */}
109
- {ENABLE_BUSINESS_FEATURES && <AgentCronJobs />}
110
+ {enableBusinessFeatures && <AgentCronJobs />}
110
111
  {/* Advanced Settings Modal */}
111
112
  <AgentSettings />
112
113
  </>
@@ -31,9 +31,14 @@ const MessageContent = memo<ContentBlockProps>(({ content, hasTools, id }) => {
31
31
  return <ContentLoading id={id} />;
32
32
  }
33
33
 
34
+ const isSingleLine = (message || '').split('\n').length <= 2;
35
+
34
36
  return (
35
37
  content && (
36
- <MarkdownMessage {...markdownProps} className={cx(hasTools && styles.pWithTool)}>
38
+ <MarkdownMessage
39
+ {...markdownProps}
40
+ className={cx(hasTools && isSingleLine && styles.pWithTool)}
41
+ >
37
42
  {message}
38
43
  </MarkdownMessage>
39
44
  )
@@ -37,11 +37,20 @@ export default {
37
37
  'agentCronJobs.empty.description': 'Create your first scheduled task to automate your agent',
38
38
  'agentCronJobs.empty.title': 'No scheduled tasks yet',
39
39
  'agentCronJobs.enable': 'Enable',
40
+ 'agentCronJobs.form.at': 'at',
40
41
  'agentCronJobs.form.content.placeholder': 'Enter the prompt or instruction for the agent',
42
+ 'agentCronJobs.form.every': 'Every',
43
+ 'agentCronJobs.form.frequency': 'Frequency',
44
+ 'agentCronJobs.form.hours': 'hour(s)',
45
+ 'agentCronJobs.form.maxExecutions': 'Stop after',
41
46
  'agentCronJobs.form.maxExecutions.placeholder': 'Leave empty for unlimited',
42
47
  'agentCronJobs.form.name.placeholder': 'Enter task name',
48
+ 'agentCronJobs.form.time': 'Time',
43
49
  'agentCronJobs.form.timeRange.end': 'End Time',
44
50
  'agentCronJobs.form.timeRange.start': 'Start Time',
51
+ 'agentCronJobs.form.times': 'times',
52
+ 'agentCronJobs.form.timezone': 'Timezone',
53
+ 'agentCronJobs.form.unlimited': 'Run continuously',
45
54
  'agentCronJobs.form.validation.contentRequired': 'Task content is required',
46
55
  'agentCronJobs.form.validation.invalidTimeRange': 'Start time must be before end time',
47
56
  'agentCronJobs.form.validation.nameRequired': 'Task name is required',
@@ -86,6 +95,13 @@ export default {
86
95
  'agentCronJobs.weekday.tuesday': 'Tuesday',
87
96
  'agentCronJobs.weekday.wednesday': 'Wednesday',
88
97
  'agentCronJobs.weekdays': 'Weekdays',
98
+ 'agentCronJobs.weekdays.fri': 'Fri',
99
+ 'agentCronJobs.weekdays.mon': 'Mon',
100
+ 'agentCronJobs.weekdays.sat': 'Sat',
101
+ 'agentCronJobs.weekdays.sun': 'Sun',
102
+ 'agentCronJobs.weekdays.thu': 'Thu',
103
+ 'agentCronJobs.weekdays.tue': 'Tue',
104
+ 'agentCronJobs.weekdays.wed': 'Wed',
89
105
  'agentInfoDescription.basic.avatar': 'Avatar',
90
106
  'agentInfoDescription.basic.description': 'Description',
91
107
  'agentInfoDescription.basic.name': 'Name',
@@ -1,4 +1,3 @@
1
- import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const';
2
1
  import type { SWRResponse } from 'swr';
3
2
  import { type StateCreator } from 'zustand/vanilla';
4
3
 
@@ -33,7 +32,10 @@ export interface CronTopicGroupWithJobInfo {
33
32
  export interface CronSliceAction {
34
33
  createAgentCronJob: () => Promise<string | null>;
35
34
  internal_refreshCronTopics: () => Promise<void>;
36
- useFetchCronTopicsWithJobInfo: (agentId?: string) => SWRResponse<CronTopicGroupWithJobInfo[]>;
35
+ useFetchCronTopicsWithJobInfo: (
36
+ agentId?: string,
37
+ enabled?: boolean,
38
+ ) => SWRResponse<CronTopicGroupWithJobInfo[]>;
37
39
  }
38
40
 
39
41
  export const createCronSlice: StateCreator<
@@ -69,9 +71,9 @@ export const createCronSlice: StateCreator<
69
71
  await mutate([FETCH_CRON_TOPICS_WITH_JOB_INFO_KEY, get().activeAgentId]);
70
72
  },
71
73
 
72
- useFetchCronTopicsWithJobInfo: (agentId) =>
74
+ useFetchCronTopicsWithJobInfo: (agentId, enabled = true) =>
73
75
  useClientDataSWR<CronTopicGroupWithJobInfo[]>(
74
- ENABLE_BUSINESS_FEATURES && agentId ? [FETCH_CRON_TOPICS_WITH_JOB_INFO_KEY, agentId] : null,
76
+ enabled && agentId ? [FETCH_CRON_TOPICS_WITH_JOB_INFO_KEY, agentId] : null,
75
77
  async ([, id]: [string, string]) => {
76
78
  const [cronJobsResult, cronTopicsGroups] = await Promise.all([
77
79
  lambdaClient.agentCronJob.findByAgent.query({ agentId: id }),