@lobehub/lobehub 2.0.0-next.265 → 2.0.0-next.267
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +14 -0
- package/e2e/CLAUDE.md +34 -73
- package/e2e/docs/local-setup.md +67 -219
- package/e2e/scripts/setup.ts +529 -0
- package/e2e/src/features/home/sidebarAgent.feature +62 -0
- package/e2e/src/features/home/sidebarGroup.feature +62 -0
- package/e2e/src/steps/home/sidebarAgent.steps.ts +373 -0
- package/e2e/src/steps/home/sidebarGroup.steps.ts +168 -0
- package/e2e/src/steps/hooks.ts +2 -0
- package/locales/ar/chat.json +1 -0
- package/locales/ar/modelProvider.json +20 -0
- package/locales/ar/models.json +33 -10
- package/locales/ar/plugin.json +1 -0
- package/locales/ar/providers.json +1 -0
- package/locales/ar/setting.json +2 -0
- package/locales/bg-BG/chat.json +1 -0
- package/locales/bg-BG/modelProvider.json +20 -0
- package/locales/bg-BG/models.json +27 -7
- package/locales/bg-BG/plugin.json +1 -0
- package/locales/bg-BG/providers.json +1 -0
- package/locales/bg-BG/setting.json +2 -0
- package/locales/de-DE/chat.json +1 -0
- package/locales/de-DE/modelProvider.json +20 -0
- package/locales/de-DE/models.json +44 -10
- package/locales/de-DE/plugin.json +1 -0
- package/locales/de-DE/providers.json +1 -0
- package/locales/de-DE/setting.json +2 -0
- package/locales/en-US/chat.json +1 -0
- package/locales/en-US/modelProvider.json +20 -0
- package/locales/en-US/models.json +10 -10
- package/locales/en-US/providers.json +1 -0
- package/locales/en-US/setting.json +2 -1
- package/locales/es-ES/chat.json +1 -0
- package/locales/es-ES/modelProvider.json +20 -0
- package/locales/es-ES/models.json +53 -10
- package/locales/es-ES/plugin.json +1 -0
- package/locales/es-ES/providers.json +1 -0
- package/locales/es-ES/setting.json +2 -0
- package/locales/fa-IR/chat.json +1 -0
- package/locales/fa-IR/modelProvider.json +20 -0
- package/locales/fa-IR/models.json +33 -10
- package/locales/fa-IR/plugin.json +1 -0
- package/locales/fa-IR/providers.json +1 -0
- package/locales/fa-IR/setting.json +2 -0
- package/locales/fr-FR/chat.json +1 -0
- package/locales/fr-FR/modelProvider.json +20 -0
- package/locales/fr-FR/models.json +27 -7
- package/locales/fr-FR/plugin.json +1 -0
- package/locales/fr-FR/providers.json +1 -0
- package/locales/fr-FR/setting.json +2 -0
- package/locales/it-IT/chat.json +1 -0
- package/locales/it-IT/modelProvider.json +20 -0
- package/locales/it-IT/models.json +10 -10
- package/locales/it-IT/plugin.json +1 -0
- package/locales/it-IT/providers.json +1 -0
- package/locales/it-IT/setting.json +2 -0
- package/locales/ja-JP/chat.json +1 -0
- package/locales/ja-JP/modelProvider.json +20 -0
- package/locales/ja-JP/models.json +5 -10
- package/locales/ja-JP/plugin.json +1 -0
- package/locales/ja-JP/providers.json +1 -0
- package/locales/ja-JP/setting.json +2 -0
- package/locales/ko-KR/chat.json +1 -0
- package/locales/ko-KR/modelProvider.json +20 -0
- package/locales/ko-KR/models.json +36 -10
- package/locales/ko-KR/plugin.json +1 -0
- package/locales/ko-KR/providers.json +1 -0
- package/locales/ko-KR/setting.json +2 -0
- package/locales/nl-NL/chat.json +1 -0
- package/locales/nl-NL/modelProvider.json +20 -0
- package/locales/nl-NL/models.json +35 -4
- package/locales/nl-NL/plugin.json +1 -0
- package/locales/nl-NL/providers.json +1 -0
- package/locales/nl-NL/setting.json +2 -0
- package/locales/pl-PL/chat.json +1 -0
- package/locales/pl-PL/modelProvider.json +20 -0
- package/locales/pl-PL/models.json +37 -7
- package/locales/pl-PL/plugin.json +1 -0
- package/locales/pl-PL/providers.json +1 -0
- package/locales/pl-PL/setting.json +2 -0
- package/locales/pt-BR/chat.json +1 -0
- package/locales/pt-BR/modelProvider.json +20 -0
- package/locales/pt-BR/models.json +51 -9
- package/locales/pt-BR/plugin.json +1 -0
- package/locales/pt-BR/providers.json +1 -0
- package/locales/pt-BR/setting.json +2 -0
- package/locales/ru-RU/chat.json +1 -0
- package/locales/ru-RU/modelProvider.json +20 -0
- package/locales/ru-RU/models.json +48 -7
- package/locales/ru-RU/plugin.json +1 -0
- package/locales/ru-RU/providers.json +1 -0
- package/locales/ru-RU/setting.json +2 -0
- package/locales/tr-TR/chat.json +1 -0
- package/locales/tr-TR/modelProvider.json +20 -0
- package/locales/tr-TR/models.json +48 -7
- package/locales/tr-TR/plugin.json +1 -0
- package/locales/tr-TR/providers.json +1 -0
- package/locales/tr-TR/setting.json +2 -0
- package/locales/vi-VN/chat.json +1 -0
- package/locales/vi-VN/modelProvider.json +20 -0
- package/locales/vi-VN/models.json +5 -5
- package/locales/vi-VN/plugin.json +1 -0
- package/locales/vi-VN/providers.json +1 -0
- package/locales/vi-VN/setting.json +2 -0
- package/locales/zh-CN/modelProvider.json +20 -20
- package/locales/zh-CN/models.json +49 -8
- package/locales/zh-CN/providers.json +1 -0
- package/locales/zh-CN/setting.json +2 -1
- package/locales/zh-TW/chat.json +1 -0
- package/locales/zh-TW/modelProvider.json +20 -0
- package/locales/zh-TW/models.json +29 -10
- package/locales/zh-TW/plugin.json +1 -0
- package/locales/zh-TW/providers.json +1 -0
- package/locales/zh-TW/setting.json +2 -0
- package/package.json +3 -3
- package/packages/utils/src/multimodalContent.test.ts +302 -0
- package/packages/utils/src/server/__tests__/sse.test.ts +353 -0
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Body.tsx +1 -1
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/CronTopicGroup.tsx +84 -0
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/{Topic/CronTopicList → Cron}/CronTopicItem.tsx +1 -1
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/{Topic/CronTopicList → Cron}/index.tsx +23 -33
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/List/Item/Editing.tsx +12 -49
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/List/index.tsx +3 -1
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/Editing.tsx +12 -40
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/hooks/useTopicNavigation.ts +5 -1
- package/src/app/[variants]/(main)/agent/profile/features/AgentCronJobs/CronJobCards.tsx +1 -1
- package/src/app/[variants]/(main)/agent/profile/features/AgentCronJobs/CronJobForm.tsx +1 -1
- package/src/app/[variants]/(main)/group/_layout/Sidebar/AddGroupMemberModal/AvailableAgentList.tsx +0 -1
- package/src/app/[variants]/(main)/group/_layout/Sidebar/AddGroupMemberModal/index.tsx +5 -1
- package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentGroupItem/Editing.tsx +4 -11
- package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentGroupItem/index.tsx +3 -3
- package/src/components/InlineRename/index.tsx +121 -0
- package/src/features/ChatInput/ActionBar/Params/Controls.tsx +42 -7
- package/src/features/NavPanel/components/NavItem.tsx +1 -1
- package/src/locales/default/setting.ts +2 -0
- package/src/store/agent/slices/cron/action.ts +108 -0
- package/src/store/agent/slices/cron/index.ts +1 -0
- package/src/store/agent/store.ts +3 -0
- package/src/store/home/slices/sidebarUI/action.ts +9 -0
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/CronTopicList/CronTopicGroup.tsx +0 -74
- package/src/app/[variants]/(main)/group/features/ChangelogModal.tsx +0 -11
- package/src/hooks/useFetchCronTopicsWithJobInfo.ts +0 -56
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Form, type FormItemProps, Tag } from '@lobehub/ui';
|
|
1
|
+
import { Form, type FormItemProps, SliderWithInput, Tag } from '@lobehub/ui';
|
|
2
2
|
import { Checkbox, Flexbox } from '@lobehub/ui';
|
|
3
|
-
import { Form as AntdForm } from 'antd';
|
|
3
|
+
import { Form as AntdForm, Switch } from 'antd';
|
|
4
4
|
import { createStaticStyles } from 'antd-style';
|
|
5
5
|
import { debounce } from 'es-toolkit/compat';
|
|
6
6
|
import isEqual from 'fast-deep-equal';
|
|
@@ -151,6 +151,7 @@ const Controls = memo<ControlsProps>(({ setUpdating }) => {
|
|
|
151
151
|
const config = useAgentStore((s) => agentByIdSelectors.getAgentConfigById(agentId)(s), isEqual);
|
|
152
152
|
const [form] = Form.useForm();
|
|
153
153
|
|
|
154
|
+
const enableMaxTokens = AntdForm.useWatch(['chatConfig', 'enableMaxTokens'], form);
|
|
154
155
|
const { frequency_penalty, presence_penalty, temperature, top_p } = config.params ?? {};
|
|
155
156
|
|
|
156
157
|
const lastValuesRef = useRef<Record<ParamKey, number | undefined>>({
|
|
@@ -289,6 +290,40 @@ const Controls = memo<ControlsProps>(({ setUpdating }) => {
|
|
|
289
290
|
} satisfies FormItemProps;
|
|
290
291
|
});
|
|
291
292
|
|
|
293
|
+
// MaxTokens items
|
|
294
|
+
const maxTokensItems: FormItemProps[] = [
|
|
295
|
+
{
|
|
296
|
+
children: <Switch />,
|
|
297
|
+
label: (
|
|
298
|
+
<Flexbox align={'center'} className={styles.label} gap={8} horizontal>
|
|
299
|
+
{t('settingModel.enableMaxTokens.title')}
|
|
300
|
+
</Flexbox>
|
|
301
|
+
),
|
|
302
|
+
name: ['chatConfig', 'enableMaxTokens'],
|
|
303
|
+
tag: 'max_tokens',
|
|
304
|
+
valuePropName: 'checked',
|
|
305
|
+
},
|
|
306
|
+
...(enableMaxTokens
|
|
307
|
+
? [
|
|
308
|
+
{
|
|
309
|
+
children: (
|
|
310
|
+
<SliderWithInput max={32_000} min={0} step={100} unlimitedInput />
|
|
311
|
+
),
|
|
312
|
+
label: (
|
|
313
|
+
<Flexbox align={'center'} className={styles.label} gap={8} horizontal>
|
|
314
|
+
{t('settingModel.maxTokens.title')}
|
|
315
|
+
<InfoTooltip title={t('settingModel.maxTokens.desc')} />
|
|
316
|
+
</Flexbox>
|
|
317
|
+
),
|
|
318
|
+
name: ['params', 'max_tokens'],
|
|
319
|
+
tag: 'max_tokens',
|
|
320
|
+
} satisfies FormItemProps,
|
|
321
|
+
]
|
|
322
|
+
: []),
|
|
323
|
+
];
|
|
324
|
+
|
|
325
|
+
const allItems = [...baseItems, ...maxTokensItems];
|
|
326
|
+
|
|
292
327
|
return (
|
|
293
328
|
<Form
|
|
294
329
|
form={form}
|
|
@@ -296,11 +331,11 @@ const Controls = memo<ControlsProps>(({ setUpdating }) => {
|
|
|
296
331
|
itemMinWidth={220}
|
|
297
332
|
items={
|
|
298
333
|
mobile
|
|
299
|
-
?
|
|
300
|
-
:
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
334
|
+
? allItems
|
|
335
|
+
: allItems.map(({ tag, ...item }) => ({
|
|
336
|
+
...item,
|
|
337
|
+
desc: <Tag size={'small'}>{tag}</Tag>,
|
|
338
|
+
}))
|
|
304
339
|
}
|
|
305
340
|
itemsType={'flat'}
|
|
306
341
|
onValuesChange={handleValuesChange}
|
|
@@ -98,7 +98,7 @@ const NavItem = memo<NavItemProps>(
|
|
|
98
98
|
|
|
99
99
|
<Flexbox align={'center'} flex={1} gap={8} horizontal style={{ overflow: 'hidden' }}>
|
|
100
100
|
<Text color={textColor} ellipsis style={{ flex: 1 }}>
|
|
101
|
-
{title
|
|
101
|
+
{title}
|
|
102
102
|
</Text>
|
|
103
103
|
<Flexbox
|
|
104
104
|
align={'center'}
|
|
@@ -33,6 +33,7 @@ export default {
|
|
|
33
33
|
'agentCronJobs.maxExecutions': 'Max Executions',
|
|
34
34
|
'agentCronJobs.name': 'Task Name',
|
|
35
35
|
'agentCronJobs.never': 'Never',
|
|
36
|
+
'agentCronJobs.noExecutionResults': 'No execution results',
|
|
36
37
|
'agentCronJobs.remainingExecutions': 'Remaining: {{count}}',
|
|
37
38
|
'agentCronJobs.save': 'Save',
|
|
38
39
|
'agentCronJobs.schedule': 'Schedule',
|
|
@@ -42,6 +43,7 @@ export default {
|
|
|
42
43
|
'agentCronJobs.timeRange': 'Time Range',
|
|
43
44
|
'agentCronJobs.title': 'Scheduled Tasks',
|
|
44
45
|
'agentCronJobs.unlimited': 'Unlimited',
|
|
46
|
+
'agentCronJobs.unnamedTask': 'Unnamed Task',
|
|
45
47
|
'agentCronJobs.updateSuccess': 'Scheduled task updated successfully',
|
|
46
48
|
'agentCronJobs.weekdays': 'Weekdays',
|
|
47
49
|
'agentInfoDescription.basic.avatar': 'Avatar',
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const';
|
|
2
|
+
import type { SWRResponse } from 'swr';
|
|
3
|
+
import { type StateCreator } from 'zustand/vanilla';
|
|
4
|
+
|
|
5
|
+
import type { AgentCronJob } from '@/database/schemas/agentCronJob';
|
|
6
|
+
import { mutate, useClientDataSWR } from '@/libs/swr';
|
|
7
|
+
import { lambdaClient } from '@/libs/trpc/client/lambda';
|
|
8
|
+
import { agentCronJobService } from '@/services/agentCronJob';
|
|
9
|
+
|
|
10
|
+
import type { AgentStore } from '../../store';
|
|
11
|
+
|
|
12
|
+
const FETCH_CRON_TOPICS_WITH_JOB_INFO_KEY = 'cronTopicsWithJobInfo';
|
|
13
|
+
|
|
14
|
+
export interface CronTopicGroupWithJobInfo {
|
|
15
|
+
cronJob: AgentCronJob | null;
|
|
16
|
+
cronJobId: string;
|
|
17
|
+
topics: Array<{
|
|
18
|
+
createdAt: Date | string;
|
|
19
|
+
favorite?: boolean | null;
|
|
20
|
+
historySummary?: string | null;
|
|
21
|
+
id: string;
|
|
22
|
+
metadata?: any;
|
|
23
|
+
title?: string | null;
|
|
24
|
+
trigger?: string | null;
|
|
25
|
+
updatedAt: Date | string;
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Cron Slice Actions
|
|
31
|
+
* Handles agent cron job operations
|
|
32
|
+
*/
|
|
33
|
+
export interface CronSliceAction {
|
|
34
|
+
createAgentCronJob: () => Promise<string | null>;
|
|
35
|
+
internal_refreshCronTopics: () => Promise<void>;
|
|
36
|
+
useFetchCronTopicsWithJobInfo: (agentId?: string) => SWRResponse<CronTopicGroupWithJobInfo[]>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const createCronSlice: StateCreator<
|
|
40
|
+
AgentStore,
|
|
41
|
+
[['zustand/devtools', never]],
|
|
42
|
+
[],
|
|
43
|
+
CronSliceAction
|
|
44
|
+
> = (set, get) => ({
|
|
45
|
+
createAgentCronJob: async () => {
|
|
46
|
+
const { activeAgentId, internal_refreshCronTopics } = get();
|
|
47
|
+
if (!activeAgentId) return null;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const result = await agentCronJobService.create({
|
|
51
|
+
agentId: activeAgentId,
|
|
52
|
+
content: '',
|
|
53
|
+
cronPattern: '*/30 * * * *',
|
|
54
|
+
enabled: false,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
if (result.success) {
|
|
58
|
+
await internal_refreshCronTopics();
|
|
59
|
+
return result.data.id;
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error('Failed to create cron job:', error);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
internal_refreshCronTopics: async () => {
|
|
69
|
+
await mutate([FETCH_CRON_TOPICS_WITH_JOB_INFO_KEY, get().activeAgentId]);
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
useFetchCronTopicsWithJobInfo: (agentId) =>
|
|
73
|
+
useClientDataSWR<CronTopicGroupWithJobInfo[]>(
|
|
74
|
+
ENABLE_BUSINESS_FEATURES && agentId ? [FETCH_CRON_TOPICS_WITH_JOB_INFO_KEY, agentId] : null,
|
|
75
|
+
async ([, id]: [string, string]) => {
|
|
76
|
+
const [cronJobsResult, cronTopicsGroups] = await Promise.all([
|
|
77
|
+
lambdaClient.agentCronJob.findByAgent.query({ agentId: id }),
|
|
78
|
+
lambdaClient.topic.getCronTopicsGroupedByCronJob.query({ agentId: id }),
|
|
79
|
+
]);
|
|
80
|
+
|
|
81
|
+
const cronJobs = cronJobsResult.success ? cronJobsResult.data : [];
|
|
82
|
+
const topicsByCronId = new Map(
|
|
83
|
+
cronTopicsGroups.map((group) => [group.cronJobId, group.topics]),
|
|
84
|
+
);
|
|
85
|
+
const cronJobIds = new Set(cronJobs.map((job) => job.id));
|
|
86
|
+
|
|
87
|
+
const groupsWithJobs = cronJobs.map((job) => ({
|
|
88
|
+
cronJob: job,
|
|
89
|
+
cronJobId: job.id,
|
|
90
|
+
topics: topicsByCronId.get(job.id) || [],
|
|
91
|
+
}));
|
|
92
|
+
|
|
93
|
+
const orphanGroups = cronTopicsGroups
|
|
94
|
+
.filter((group) => !cronJobIds.has(group.cronJobId))
|
|
95
|
+
.map((group) => ({
|
|
96
|
+
cronJob: null,
|
|
97
|
+
cronJobId: group.cronJobId,
|
|
98
|
+
topics: group.topics,
|
|
99
|
+
}));
|
|
100
|
+
|
|
101
|
+
return [...groupsWithJobs, ...orphanGroups];
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
fallbackData: [],
|
|
105
|
+
revalidateOnFocus: false,
|
|
106
|
+
},
|
|
107
|
+
),
|
|
108
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createCronSlice, type CronSliceAction } from './action';
|
package/src/store/agent/store.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { createDevtools } from '../middleware/createDevtools';
|
|
|
6
6
|
import { type AgentStoreState, initialState } from './initialState';
|
|
7
7
|
import { type AgentSliceAction, createAgentSlice } from './slices/agent';
|
|
8
8
|
import { type BuiltinAgentSliceAction, createBuiltinAgentSlice } from './slices/builtin';
|
|
9
|
+
import { type CronSliceAction, createCronSlice } from './slices/cron';
|
|
9
10
|
import { type KnowledgeSliceAction, createKnowledgeSlice } from './slices/knowledge';
|
|
10
11
|
import { type PluginSliceAction, createPluginSlice } from './slices/plugin';
|
|
11
12
|
|
|
@@ -15,6 +16,7 @@ export interface AgentStore
|
|
|
15
16
|
extends
|
|
16
17
|
AgentSliceAction,
|
|
17
18
|
BuiltinAgentSliceAction,
|
|
19
|
+
CronSliceAction,
|
|
18
20
|
KnowledgeSliceAction,
|
|
19
21
|
PluginSliceAction,
|
|
20
22
|
AgentStoreState {}
|
|
@@ -23,6 +25,7 @@ const createStore: StateCreator<AgentStore, [['zustand/devtools', never]]> = (..
|
|
|
23
25
|
...initialState,
|
|
24
26
|
...createAgentSlice(...parameters),
|
|
25
27
|
...createBuiltinAgentSlice(...parameters),
|
|
28
|
+
...createCronSlice(...parameters),
|
|
26
29
|
...createKnowledgeSlice(...parameters),
|
|
27
30
|
...createPluginSlice(...parameters),
|
|
28
31
|
});
|
|
@@ -40,6 +40,10 @@ export interface SidebarUIAction {
|
|
|
40
40
|
* Remove an agent group (group chat)
|
|
41
41
|
*/
|
|
42
42
|
removeAgentGroup: (groupId: string) => Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Rename an agent group (group chat)
|
|
45
|
+
*/
|
|
46
|
+
renameAgentGroup: (groupId: string, title: string) => Promise<void>;
|
|
43
47
|
/**
|
|
44
48
|
* Update agent's group
|
|
45
49
|
*/
|
|
@@ -162,6 +166,11 @@ export const createSidebarUISlice: StateCreator<
|
|
|
162
166
|
await get().refreshAgentList();
|
|
163
167
|
},
|
|
164
168
|
|
|
169
|
+
renameAgentGroup: async (groupId, title) => {
|
|
170
|
+
await chatGroupService.updateGroup(groupId, { title });
|
|
171
|
+
await get().refreshAgentList();
|
|
172
|
+
},
|
|
173
|
+
|
|
165
174
|
updateAgentGroup: async (agentId, groupId) => {
|
|
166
175
|
await homeService.updateAgentSessionGroupId(agentId, groupId === 'default' ? null : groupId);
|
|
167
176
|
await get().refreshAgentList();
|
package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/CronTopicList/CronTopicGroup.tsx
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Flexbox, Icon, Text } from '@lobehub/ui';
|
|
4
|
-
import { cssVar } from 'antd-style';
|
|
5
|
-
import { Clock } from 'lucide-react';
|
|
6
|
-
import { type MouseEvent, memo, useCallback } from 'react';
|
|
7
|
-
import { useParams } from 'react-router-dom';
|
|
8
|
-
|
|
9
|
-
import { useRouter } from '@/app/[variants]/(main)/hooks/useRouter';
|
|
10
|
-
import type { AgentCronJob } from '@/database/schemas/agentCronJob';
|
|
11
|
-
|
|
12
|
-
import CronTopicItem from './CronTopicItem';
|
|
13
|
-
|
|
14
|
-
interface CronTopicGroupProps {
|
|
15
|
-
cronJob: AgentCronJob | null;
|
|
16
|
-
cronJobId: string;
|
|
17
|
-
topics: Array<{
|
|
18
|
-
createdAt: Date | string;
|
|
19
|
-
favorite?: boolean | null;
|
|
20
|
-
historySummary?: string | null;
|
|
21
|
-
id: string;
|
|
22
|
-
metadata?: any;
|
|
23
|
-
title?: string | null;
|
|
24
|
-
trigger?: string | null;
|
|
25
|
-
updatedAt: Date | string;
|
|
26
|
-
}>;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const CronTopicGroup = memo<CronTopicGroupProps>(({ cronJob, cronJobId, topics }) => {
|
|
30
|
-
const { aid } = useParams<{ aid?: string }>();
|
|
31
|
-
const router = useRouter();
|
|
32
|
-
const handleOpenCronJob = useCallback(
|
|
33
|
-
(event: MouseEvent) => {
|
|
34
|
-
event.stopPropagation();
|
|
35
|
-
if (!aid) return;
|
|
36
|
-
router.push(`/agent/${aid}/cron/${cronJobId}`);
|
|
37
|
-
},
|
|
38
|
-
[aid, cronJobId, router],
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
const cronJobName = cronJob?.name || `Cron Job ${cronJobId.slice(-8)}`;
|
|
42
|
-
const isEnabled = cronJob?.enabled ?? false;
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<Flexbox gap={1}>
|
|
46
|
-
<Flexbox
|
|
47
|
-
align="center"
|
|
48
|
-
gap={6}
|
|
49
|
-
height={24}
|
|
50
|
-
horizontal
|
|
51
|
-
onClick={handleOpenCronJob}
|
|
52
|
-
paddingInline={8}
|
|
53
|
-
style={{ cursor: 'pointer', opacity: isEnabled ? 1 : 0.6, overflow: 'hidden' }}
|
|
54
|
-
>
|
|
55
|
-
<Icon icon={Clock} style={{ color: cssVar.colorTextDescription, opacity: 0.7 }} />
|
|
56
|
-
<Text ellipsis fontSize={12} style={{ flex: 1 }} type={'secondary'} weight={500}>
|
|
57
|
-
{cronJobName}
|
|
58
|
-
</Text>
|
|
59
|
-
{topics.length > 0 && (
|
|
60
|
-
<Text style={{ color: cssVar.colorTextDescription, fontSize: 11 }}>{topics.length}</Text>
|
|
61
|
-
)}
|
|
62
|
-
</Flexbox>
|
|
63
|
-
{topics.length > 0 && (
|
|
64
|
-
<Flexbox gap={1} paddingBlock={1}>
|
|
65
|
-
{topics.map((topic) => (
|
|
66
|
-
<CronTopicItem key={topic.id} topic={topic} />
|
|
67
|
-
))}
|
|
68
|
-
</Flexbox>
|
|
69
|
-
)}
|
|
70
|
-
</Flexbox>
|
|
71
|
-
);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
export default CronTopicGroup;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import ChangelogModal from '@/features/ChangelogModal';
|
|
2
|
-
import { ChangelogService } from '@/server/services/changelog';
|
|
3
|
-
|
|
4
|
-
const Changelog = async () => {
|
|
5
|
-
const service = new ChangelogService();
|
|
6
|
-
const id = await service.getLatestChangelogId();
|
|
7
|
-
|
|
8
|
-
return <ChangelogModal currentId={id} />;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export default Changelog;
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const';
|
|
2
|
-
import useSWR from 'swr';
|
|
3
|
-
|
|
4
|
-
import { lambdaClient } from '@/libs/trpc/client/lambda';
|
|
5
|
-
import { useAgentStore } from '@/store/agent';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Fetch cron topics grouped by cronJob with job information
|
|
9
|
-
*/
|
|
10
|
-
export const useFetchCronTopicsWithJobInfo = () => {
|
|
11
|
-
const agentId = useAgentStore((s) => s.activeAgentId);
|
|
12
|
-
|
|
13
|
-
const { data, isLoading, error, mutate } = useSWR(
|
|
14
|
-
ENABLE_BUSINESS_FEATURES && agentId ? ['cronTopicsWithJobInfo', agentId] : null,
|
|
15
|
-
async () => {
|
|
16
|
-
if (!agentId) return [];
|
|
17
|
-
|
|
18
|
-
const [cronJobsResult, cronTopicsGroups] = await Promise.all([
|
|
19
|
-
lambdaClient.agentCronJob.findByAgent.query({ agentId }),
|
|
20
|
-
lambdaClient.topic.getCronTopicsGroupedByCronJob.query({ agentId }),
|
|
21
|
-
]);
|
|
22
|
-
|
|
23
|
-
const cronJobs = cronJobsResult.success ? cronJobsResult.data : [];
|
|
24
|
-
const topicsByCronId = new Map(
|
|
25
|
-
cronTopicsGroups.map((group) => [group.cronJobId, group.topics]),
|
|
26
|
-
);
|
|
27
|
-
const cronJobIds = new Set(cronJobs.map((job) => job.id));
|
|
28
|
-
|
|
29
|
-
const groupsWithJobs = cronJobs.map((job) => ({
|
|
30
|
-
cronJob: job,
|
|
31
|
-
cronJobId: job.id,
|
|
32
|
-
topics: topicsByCronId.get(job.id) || [],
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
|
-
const orphanGroups = cronTopicsGroups
|
|
36
|
-
.filter((group) => !cronJobIds.has(group.cronJobId))
|
|
37
|
-
.map((group) => ({
|
|
38
|
-
cronJob: null,
|
|
39
|
-
cronJobId: group.cronJobId,
|
|
40
|
-
topics: group.topics,
|
|
41
|
-
}));
|
|
42
|
-
|
|
43
|
-
return [...groupsWithJobs, ...orphanGroups];
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
revalidateOnFocus: false,
|
|
47
|
-
},
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
cronTopicsGroupsWithJobInfo: data || [],
|
|
52
|
-
error,
|
|
53
|
-
isLoading,
|
|
54
|
-
mutate,
|
|
55
|
-
};
|
|
56
|
-
};
|