@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.
Files changed (143) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +14 -0
  3. package/e2e/CLAUDE.md +34 -73
  4. package/e2e/docs/local-setup.md +67 -219
  5. package/e2e/scripts/setup.ts +529 -0
  6. package/e2e/src/features/home/sidebarAgent.feature +62 -0
  7. package/e2e/src/features/home/sidebarGroup.feature +62 -0
  8. package/e2e/src/steps/home/sidebarAgent.steps.ts +373 -0
  9. package/e2e/src/steps/home/sidebarGroup.steps.ts +168 -0
  10. package/e2e/src/steps/hooks.ts +2 -0
  11. package/locales/ar/chat.json +1 -0
  12. package/locales/ar/modelProvider.json +20 -0
  13. package/locales/ar/models.json +33 -10
  14. package/locales/ar/plugin.json +1 -0
  15. package/locales/ar/providers.json +1 -0
  16. package/locales/ar/setting.json +2 -0
  17. package/locales/bg-BG/chat.json +1 -0
  18. package/locales/bg-BG/modelProvider.json +20 -0
  19. package/locales/bg-BG/models.json +27 -7
  20. package/locales/bg-BG/plugin.json +1 -0
  21. package/locales/bg-BG/providers.json +1 -0
  22. package/locales/bg-BG/setting.json +2 -0
  23. package/locales/de-DE/chat.json +1 -0
  24. package/locales/de-DE/modelProvider.json +20 -0
  25. package/locales/de-DE/models.json +44 -10
  26. package/locales/de-DE/plugin.json +1 -0
  27. package/locales/de-DE/providers.json +1 -0
  28. package/locales/de-DE/setting.json +2 -0
  29. package/locales/en-US/chat.json +1 -0
  30. package/locales/en-US/modelProvider.json +20 -0
  31. package/locales/en-US/models.json +10 -10
  32. package/locales/en-US/providers.json +1 -0
  33. package/locales/en-US/setting.json +2 -1
  34. package/locales/es-ES/chat.json +1 -0
  35. package/locales/es-ES/modelProvider.json +20 -0
  36. package/locales/es-ES/models.json +53 -10
  37. package/locales/es-ES/plugin.json +1 -0
  38. package/locales/es-ES/providers.json +1 -0
  39. package/locales/es-ES/setting.json +2 -0
  40. package/locales/fa-IR/chat.json +1 -0
  41. package/locales/fa-IR/modelProvider.json +20 -0
  42. package/locales/fa-IR/models.json +33 -10
  43. package/locales/fa-IR/plugin.json +1 -0
  44. package/locales/fa-IR/providers.json +1 -0
  45. package/locales/fa-IR/setting.json +2 -0
  46. package/locales/fr-FR/chat.json +1 -0
  47. package/locales/fr-FR/modelProvider.json +20 -0
  48. package/locales/fr-FR/models.json +27 -7
  49. package/locales/fr-FR/plugin.json +1 -0
  50. package/locales/fr-FR/providers.json +1 -0
  51. package/locales/fr-FR/setting.json +2 -0
  52. package/locales/it-IT/chat.json +1 -0
  53. package/locales/it-IT/modelProvider.json +20 -0
  54. package/locales/it-IT/models.json +10 -10
  55. package/locales/it-IT/plugin.json +1 -0
  56. package/locales/it-IT/providers.json +1 -0
  57. package/locales/it-IT/setting.json +2 -0
  58. package/locales/ja-JP/chat.json +1 -0
  59. package/locales/ja-JP/modelProvider.json +20 -0
  60. package/locales/ja-JP/models.json +5 -10
  61. package/locales/ja-JP/plugin.json +1 -0
  62. package/locales/ja-JP/providers.json +1 -0
  63. package/locales/ja-JP/setting.json +2 -0
  64. package/locales/ko-KR/chat.json +1 -0
  65. package/locales/ko-KR/modelProvider.json +20 -0
  66. package/locales/ko-KR/models.json +36 -10
  67. package/locales/ko-KR/plugin.json +1 -0
  68. package/locales/ko-KR/providers.json +1 -0
  69. package/locales/ko-KR/setting.json +2 -0
  70. package/locales/nl-NL/chat.json +1 -0
  71. package/locales/nl-NL/modelProvider.json +20 -0
  72. package/locales/nl-NL/models.json +35 -4
  73. package/locales/nl-NL/plugin.json +1 -0
  74. package/locales/nl-NL/providers.json +1 -0
  75. package/locales/nl-NL/setting.json +2 -0
  76. package/locales/pl-PL/chat.json +1 -0
  77. package/locales/pl-PL/modelProvider.json +20 -0
  78. package/locales/pl-PL/models.json +37 -7
  79. package/locales/pl-PL/plugin.json +1 -0
  80. package/locales/pl-PL/providers.json +1 -0
  81. package/locales/pl-PL/setting.json +2 -0
  82. package/locales/pt-BR/chat.json +1 -0
  83. package/locales/pt-BR/modelProvider.json +20 -0
  84. package/locales/pt-BR/models.json +51 -9
  85. package/locales/pt-BR/plugin.json +1 -0
  86. package/locales/pt-BR/providers.json +1 -0
  87. package/locales/pt-BR/setting.json +2 -0
  88. package/locales/ru-RU/chat.json +1 -0
  89. package/locales/ru-RU/modelProvider.json +20 -0
  90. package/locales/ru-RU/models.json +48 -7
  91. package/locales/ru-RU/plugin.json +1 -0
  92. package/locales/ru-RU/providers.json +1 -0
  93. package/locales/ru-RU/setting.json +2 -0
  94. package/locales/tr-TR/chat.json +1 -0
  95. package/locales/tr-TR/modelProvider.json +20 -0
  96. package/locales/tr-TR/models.json +48 -7
  97. package/locales/tr-TR/plugin.json +1 -0
  98. package/locales/tr-TR/providers.json +1 -0
  99. package/locales/tr-TR/setting.json +2 -0
  100. package/locales/vi-VN/chat.json +1 -0
  101. package/locales/vi-VN/modelProvider.json +20 -0
  102. package/locales/vi-VN/models.json +5 -5
  103. package/locales/vi-VN/plugin.json +1 -0
  104. package/locales/vi-VN/providers.json +1 -0
  105. package/locales/vi-VN/setting.json +2 -0
  106. package/locales/zh-CN/modelProvider.json +20 -20
  107. package/locales/zh-CN/models.json +49 -8
  108. package/locales/zh-CN/providers.json +1 -0
  109. package/locales/zh-CN/setting.json +2 -1
  110. package/locales/zh-TW/chat.json +1 -0
  111. package/locales/zh-TW/modelProvider.json +20 -0
  112. package/locales/zh-TW/models.json +29 -10
  113. package/locales/zh-TW/plugin.json +1 -0
  114. package/locales/zh-TW/providers.json +1 -0
  115. package/locales/zh-TW/setting.json +2 -0
  116. package/package.json +3 -3
  117. package/packages/utils/src/multimodalContent.test.ts +302 -0
  118. package/packages/utils/src/server/__tests__/sse.test.ts +353 -0
  119. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Body.tsx +1 -1
  120. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/CronTopicGroup.tsx +84 -0
  121. package/src/app/[variants]/(main)/agent/_layout/Sidebar/{Topic/CronTopicList → Cron}/CronTopicItem.tsx +1 -1
  122. package/src/app/[variants]/(main)/agent/_layout/Sidebar/{Topic/CronTopicList → Cron}/index.tsx +23 -33
  123. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/List/Item/Editing.tsx +12 -49
  124. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/List/index.tsx +3 -1
  125. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/Editing.tsx +12 -40
  126. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/hooks/useTopicNavigation.ts +5 -1
  127. package/src/app/[variants]/(main)/agent/profile/features/AgentCronJobs/CronJobCards.tsx +1 -1
  128. package/src/app/[variants]/(main)/agent/profile/features/AgentCronJobs/CronJobForm.tsx +1 -1
  129. package/src/app/[variants]/(main)/group/_layout/Sidebar/AddGroupMemberModal/AvailableAgentList.tsx +0 -1
  130. package/src/app/[variants]/(main)/group/_layout/Sidebar/AddGroupMemberModal/index.tsx +5 -1
  131. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentGroupItem/Editing.tsx +4 -11
  132. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentGroupItem/index.tsx +3 -3
  133. package/src/components/InlineRename/index.tsx +121 -0
  134. package/src/features/ChatInput/ActionBar/Params/Controls.tsx +42 -7
  135. package/src/features/NavPanel/components/NavItem.tsx +1 -1
  136. package/src/locales/default/setting.ts +2 -0
  137. package/src/store/agent/slices/cron/action.ts +108 -0
  138. package/src/store/agent/slices/cron/index.ts +1 -0
  139. package/src/store/agent/store.ts +3 -0
  140. package/src/store/home/slices/sidebarUI/action.ts +9 -0
  141. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/CronTopicList/CronTopicGroup.tsx +0 -74
  142. package/src/app/[variants]/(main)/group/features/ChangelogModal.tsx +0 -11
  143. 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
- ? baseItems
300
- : baseItems.map(({ tag, ...item }) => ({
301
- ...item,
302
- desc: <Tag size={'small'}>{tag}</Tag>,
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 || 'LobeHub'}
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';
@@ -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();
@@ -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
- };