@lobehub/lobehub 2.0.0-next.265 → 2.0.0-next.266
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 +25 -0
- package/changelog/v1.json +9 -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 +1 -1
- 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/components/InlineRename/index.tsx +121 -0
- 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/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
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Input, type InputProps, Popover } from '@lobehub/ui';
|
|
4
|
+
import type { InputRef, PopoverProps } from 'antd';
|
|
5
|
+
import { KeyboardEvent, memo, useCallback, useEffect, useRef, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
function FocusableInput(props: InputProps) {
|
|
8
|
+
const ref = useRef<InputRef>(null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
queueMicrotask(() => {
|
|
11
|
+
ref.current?.input?.focus();
|
|
12
|
+
});
|
|
13
|
+
}, []);
|
|
14
|
+
return <Input {...props} ref={ref} />;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface InlineRenameProps {
|
|
18
|
+
/**
|
|
19
|
+
* Callback when editing is cancelled (Escape key)
|
|
20
|
+
*/
|
|
21
|
+
onCancel?: () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Callback when open state changes
|
|
24
|
+
*/
|
|
25
|
+
onOpenChange: (open: boolean) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Callback to save the new title
|
|
28
|
+
*/
|
|
29
|
+
onSave: (newTitle: string) => void | Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Whether the popover is open (editing mode)
|
|
32
|
+
*/
|
|
33
|
+
open: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Popover placement
|
|
36
|
+
*/
|
|
37
|
+
placement?: PopoverProps['placement'];
|
|
38
|
+
/**
|
|
39
|
+
* Current title
|
|
40
|
+
*/
|
|
41
|
+
title: string;
|
|
42
|
+
/**
|
|
43
|
+
* Popover width
|
|
44
|
+
*/
|
|
45
|
+
width?: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const InlineRename = memo<InlineRenameProps>(
|
|
49
|
+
({ open, title, onOpenChange, onSave, onCancel, placement = 'bottomLeft', width = 320 }) => {
|
|
50
|
+
const [newTitle, setNewTitle] = useState(title);
|
|
51
|
+
const savedRef = useRef(false);
|
|
52
|
+
|
|
53
|
+
// Reset state when opening
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (open) {
|
|
56
|
+
setNewTitle(title);
|
|
57
|
+
savedRef.current = false;
|
|
58
|
+
}
|
|
59
|
+
}, [open, title]);
|
|
60
|
+
|
|
61
|
+
const handleSave = useCallback(async () => {
|
|
62
|
+
if (savedRef.current) return;
|
|
63
|
+
|
|
64
|
+
if (newTitle && title !== newTitle) {
|
|
65
|
+
savedRef.current = true;
|
|
66
|
+
await onSave(newTitle);
|
|
67
|
+
}
|
|
68
|
+
}, [newTitle, title, onSave]);
|
|
69
|
+
|
|
70
|
+
const handleClose = useCallback(() => {
|
|
71
|
+
onOpenChange(false);
|
|
72
|
+
}, [onOpenChange]);
|
|
73
|
+
|
|
74
|
+
const handleKeyDown = useCallback(
|
|
75
|
+
(e: KeyboardEvent) => {
|
|
76
|
+
if (e.key === 'Escape') {
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
e.stopPropagation();
|
|
79
|
+
onCancel?.();
|
|
80
|
+
handleClose();
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
[onCancel, handleClose],
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<Popover
|
|
88
|
+
content={
|
|
89
|
+
<FocusableInput
|
|
90
|
+
defaultValue={title}
|
|
91
|
+
onBlur={handleSave}
|
|
92
|
+
onChange={(e) => setNewTitle(e.target.value)}
|
|
93
|
+
onClick={(e) => e.stopPropagation()}
|
|
94
|
+
onKeyDown={handleKeyDown}
|
|
95
|
+
onPressEnter={() => {
|
|
96
|
+
handleSave();
|
|
97
|
+
handleClose();
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
}
|
|
101
|
+
onOpenChange={(nextOpen) => {
|
|
102
|
+
if (!nextOpen) handleSave();
|
|
103
|
+
onOpenChange(nextOpen);
|
|
104
|
+
}}
|
|
105
|
+
open={open}
|
|
106
|
+
placement={placement}
|
|
107
|
+
styles={{
|
|
108
|
+
content: {
|
|
109
|
+
padding: 4,
|
|
110
|
+
width,
|
|
111
|
+
},
|
|
112
|
+
}}
|
|
113
|
+
trigger="click"
|
|
114
|
+
>
|
|
115
|
+
<div />
|
|
116
|
+
</Popover>
|
|
117
|
+
);
|
|
118
|
+
},
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
export default InlineRename;
|
|
@@ -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
|
});
|
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
|
-
};
|