@lobehub/lobehub 2.0.0-next.251 → 2.0.0-next.253

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 (66) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/apps/desktop/build/entitlements.mac.plist +9 -0
  3. package/apps/desktop/resources/locales/zh-CN/dialog.json +5 -1
  4. package/apps/desktop/resources/locales/zh-CN/menu.json +7 -0
  5. package/apps/desktop/src/main/controllers/SystemCtr.ts +186 -94
  6. package/apps/desktop/src/main/controllers/__tests__/SystemCtr.test.ts +200 -31
  7. package/apps/desktop/src/main/core/browser/Browser.ts +9 -0
  8. package/apps/desktop/src/main/locales/default/dialog.ts +7 -2
  9. package/apps/desktop/src/main/locales/default/menu.ts +7 -0
  10. package/apps/desktop/src/main/menus/impls/macOS.ts +44 -1
  11. package/apps/desktop/src/main/utils/fullDiskAccess.ts +121 -0
  12. package/changelog/v1.json +14 -0
  13. package/package.json +1 -1
  14. package/packages/builtin-tool-notebook/src/client/Render/CreateDocument/DocumentCard.tsx +0 -2
  15. package/packages/database/migrations/meta/_journal.json +1 -1
  16. package/packages/database/src/models/__tests__/topics/topic.create.test.ts +37 -8
  17. package/packages/database/src/models/topic.ts +71 -4
  18. package/packages/database/src/schemas/agentCronJob.ts +1 -2
  19. package/packages/electron-client-ipc/src/events/system.ts +1 -0
  20. package/packages/memory-user-memory/src/extractors/context.ts +1 -4
  21. package/packages/memory-user-memory/src/extractors/experience.ts +2 -8
  22. package/packages/memory-user-memory/src/extractors/preference.ts +2 -8
  23. package/packages/memory-user-memory/src/prompts/gatekeeper.ts +123 -123
  24. package/packages/memory-user-memory/src/prompts/layers/context.ts +152 -152
  25. package/packages/memory-user-memory/src/prompts/layers/experience.ts +159 -159
  26. package/packages/memory-user-memory/src/prompts/layers/identity.ts +213 -213
  27. package/packages/memory-user-memory/src/prompts/layers/preference.ts +160 -160
  28. package/packages/memory-user-memory/src/services/extractExecutor.ts +33 -30
  29. package/packages/memory-user-memory/src/types.ts +10 -8
  30. package/packages/types/src/topic/topic.ts +9 -0
  31. package/src/app/[variants]/(desktop)/desktop-onboarding/features/PermissionsStep.tsx +16 -30
  32. package/src/app/[variants]/(desktop)/desktop-onboarding/index.tsx +19 -9
  33. package/src/app/[variants]/(desktop)/desktop-onboarding/storage.ts +49 -0
  34. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Body.tsx +4 -1
  35. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/CronTopicList/CronTopicGroup.tsx +74 -0
  36. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/CronTopicList/CronTopicItem.tsx +40 -0
  37. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/CronTopicList/index.tsx +140 -0
  38. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/index.tsx +1 -1
  39. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/TopicListContent/index.tsx +1 -1
  40. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/index.tsx +1 -1
  41. package/src/app/[variants]/(main)/chat/cron/[cronId]/index.tsx +664 -0
  42. package/src/app/[variants]/(main)/chat/profile/features/AgentCronJobs/CronJobCards.tsx +160 -0
  43. package/src/app/[variants]/(main)/chat/profile/features/AgentCronJobs/CronJobForm.tsx +202 -0
  44. package/src/app/[variants]/(main)/chat/profile/features/AgentCronJobs/CronJobList.tsx +137 -0
  45. package/src/app/[variants]/(main)/chat/profile/features/AgentCronJobs/hooks/useAgentCronJobs.ts +138 -0
  46. package/src/app/[variants]/(main)/chat/profile/features/AgentCronJobs/index.tsx +130 -0
  47. package/src/app/[variants]/(main)/chat/profile/features/ProfileEditor/index.tsx +33 -3
  48. package/src/app/[variants]/router/desktopRouter.config.tsx +7 -0
  49. package/src/features/ChatInput/ActionBar/Params/Controls.tsx +7 -6
  50. package/src/hooks/useFetchCronTopics.ts +29 -0
  51. package/src/hooks/useFetchCronTopicsWithJobInfo.ts +56 -0
  52. package/src/hooks/useFetchTopics.ts +4 -1
  53. package/src/locales/default/setting.ts +44 -1
  54. package/src/server/routers/lambda/agentCronJob.ts +367 -0
  55. package/src/server/routers/lambda/image/index.test.ts +2 -2
  56. package/src/server/routers/lambda/index.ts +2 -0
  57. package/src/server/routers/lambda/topic.ts +15 -3
  58. package/src/server/services/aiAgent/index.ts +18 -1
  59. package/src/server/services/memory/userMemory/extract.ts +14 -6
  60. package/src/services/agentCronJob.ts +95 -0
  61. package/src/services/topic/index.ts +1 -0
  62. package/src/store/chat/slices/topic/action.ts +53 -2
  63. package/src/store/chat/slices/topic/initialState.ts +1 -0
  64. package/src/store/chat/slices/topic/selectors.ts +14 -6
  65. package/src/tools/placeholders.ts +1 -4
  66. package/apps/desktop/src/main/controllers/scripts/full-disk-access.applescript +0 -85
@@ -38,6 +38,11 @@ const n = setNamespace('t');
38
38
 
39
39
  const SWR_USE_FETCH_TOPIC = 'SWR_USE_FETCH_TOPIC';
40
40
  const SWR_USE_SEARCH_TOPIC = 'SWR_USE_SEARCH_TOPIC';
41
+ type CronTopicsGroupWithJobInfo = {
42
+ cronJob: unknown;
43
+ cronJobId: string;
44
+ topics: ChatTopic[];
45
+ };
41
46
 
42
47
  /**
43
48
  * Options for switchTopic action
@@ -91,6 +96,7 @@ export interface ChatTopicAction {
91
96
  enable: boolean,
92
97
  params: {
93
98
  agentId?: string;
99
+ excludeTriggers?: string[];
94
100
  groupId?: string;
95
101
  isInbox?: boolean;
96
102
  pageSize?: number;
@@ -282,7 +288,34 @@ export const chatTopic: StateCreator<
282
288
  });
283
289
  },
284
290
  favoriteTopic: async (id, favorite) => {
291
+ const { activeAgentId } = get();
285
292
  await get().internal_updateTopic(id, { favorite });
293
+
294
+ if (!activeAgentId) return;
295
+
296
+ await mutate(
297
+ ['cronTopicsWithJobInfo', activeAgentId],
298
+ (groups?: CronTopicsGroupWithJobInfo[]) => {
299
+ if (!groups) return groups;
300
+
301
+ let updated = false;
302
+ const next = groups.map((group) => {
303
+ let groupUpdated = false;
304
+ const topics = group.topics.map((topic) => {
305
+ if (topic.id !== id) return topic;
306
+ if (topic.favorite === favorite) return topic;
307
+ groupUpdated = true;
308
+ updated = true;
309
+ return { ...topic, favorite };
310
+ });
311
+
312
+ return groupUpdated ? { ...group, topics } : group;
313
+ });
314
+
315
+ return updated ? next : groups;
316
+ },
317
+ { revalidate: false },
318
+ );
286
319
  },
287
320
 
288
321
  updateTopicMetadata: async (id, metadata) => {
@@ -314,15 +347,28 @@ export const chatTopic: StateCreator<
314
347
  },
315
348
 
316
349
  // query
317
- useFetchTopics: (enable, { agentId, groupId, pageSize: customPageSize, isInbox }) => {
350
+ useFetchTopics: (
351
+ enable,
352
+ { agentId, excludeTriggers, groupId, pageSize: customPageSize, isInbox },
353
+ ) => {
318
354
  const pageSize = customPageSize || 20;
355
+ const effectiveExcludeTriggers =
356
+ excludeTriggers && excludeTriggers.length > 0 ? excludeTriggers : undefined;
319
357
  // Use topicMapKey to generate the container key for topic data map
320
358
  const containerKey = topicMapKey({ agentId, groupId });
321
359
  const hasValidContainer = !!(groupId || agentId);
322
360
 
323
361
  return useClientDataSWRWithSync<{ items: ChatTopic[]; total: number }>(
324
362
  enable && hasValidContainer
325
- ? [SWR_USE_FETCH_TOPIC, containerKey, { isInbox, pageSize }]
363
+ ? [
364
+ SWR_USE_FETCH_TOPIC,
365
+ containerKey,
366
+ {
367
+ isInbox,
368
+ pageSize,
369
+ ...(effectiveExcludeTriggers ? { excludeTriggers: effectiveExcludeTriggers } : {}),
370
+ },
371
+ ]
326
372
  : null,
327
373
  async () => {
328
374
  // agentId, groupId, isInbox, pageSize come from the outer scope closure
@@ -343,6 +389,7 @@ export const chatTopic: StateCreator<
343
389
  const result = await topicService.getTopics({
344
390
  agentId,
345
391
  current: 0,
392
+ excludeTriggers: effectiveExcludeTriggers,
346
393
  groupId,
347
394
  isInbox,
348
395
  pageSize,
@@ -374,6 +421,7 @@ export const chatTopic: StateCreator<
374
421
  ...get().topicDataMap,
375
422
  [containerKey]: {
376
423
  currentPage: 0,
424
+ excludeTriggers: effectiveExcludeTriggers,
377
425
  hasMore,
378
426
  isExpandingPageSize: false,
379
427
  items: topics,
@@ -413,9 +461,11 @@ export const chatTopic: StateCreator<
413
461
 
414
462
  try {
415
463
  const pageSize = useGlobalStore.getState().status.topicPageSize || 20;
464
+ const excludeTriggers = currentData?.excludeTriggers;
416
465
  const result = await topicService.getTopics({
417
466
  agentId: activeAgentId,
418
467
  current: nextPage,
468
+ excludeTriggers,
419
469
  groupId: activeGroupId,
420
470
  pageSize,
421
471
  });
@@ -429,6 +479,7 @@ export const chatTopic: StateCreator<
429
479
  ...get().topicDataMap,
430
480
  [key]: {
431
481
  currentPage: nextPage,
482
+ excludeTriggers,
432
483
  hasMore,
433
484
  isLoadingMore: false,
434
485
  items: [...currentTopics, ...result.items],
@@ -5,6 +5,7 @@ import { type ChatTopic } from '@/types/topic';
5
5
  */
6
6
  export interface TopicData {
7
7
  currentPage: number;
8
+ excludeTriggers?: string[];
8
9
  hasMore: boolean;
9
10
  isExpandingPageSize?: boolean;
10
11
  isLoadingMore?: boolean;
@@ -18,27 +18,34 @@ const currentTopicData = (s: ChatStoreState): TopicData | undefined => {
18
18
 
19
19
  const currentTopics = (s: ChatStoreState): ChatTopic[] | undefined => currentTopicData(s)?.items;
20
20
 
21
+ // Get topics without cron-triggered ones
22
+ const currentTopicsWithoutCron = (s: ChatStoreState): ChatTopic[] | undefined => {
23
+ const topics = currentTopics(s);
24
+ if (!topics) return undefined;
25
+ return topics.filter((topic) => topic.trigger !== 'cron');
26
+ };
27
+
21
28
  const currentActiveTopic = (s: ChatStoreState): ChatTopic | undefined => {
22
29
  return currentTopics(s)?.find((topic) => topic.id === s.activeTopicId);
23
30
  };
24
31
  const searchTopics = (s: ChatStoreState): ChatTopic[] => s.searchTopics;
25
32
 
26
- const displayTopics = (s: ChatStoreState): ChatTopic[] | undefined => currentTopics(s);
33
+ const displayTopics = (s: ChatStoreState): ChatTopic[] | undefined => currentTopicsWithoutCron(s);
27
34
 
28
35
  const currentFavTopics = (s: ChatStoreState): ChatTopic[] =>
29
- currentTopics(s)?.filter((s) => s.favorite) || [];
36
+ currentTopicsWithoutCron(s)?.filter((s) => s.favorite) || [];
30
37
 
31
38
  const currentUnFavTopics = (s: ChatStoreState): ChatTopic[] =>
32
- currentTopics(s)?.filter((s) => !s.favorite) || [];
39
+ currentTopicsWithoutCron(s)?.filter((s) => !s.favorite) || [];
33
40
 
34
- const currentTopicLength = (s: ChatStoreState): number => currentTopicData(s)?.items?.length || 0;
41
+ const currentTopicLength = (s: ChatStoreState): number => currentTopicsWithoutCron(s)?.length || 0;
35
42
 
36
43
  const currentTopicCount = (s: ChatStoreState): number => currentTopicData(s)?.total || 0;
37
44
 
38
45
  const getTopicById =
39
46
  (id: string) =>
40
47
  (s: ChatStoreState): ChatTopic | undefined =>
41
- currentTopics(s)?.find((topic) => topic.id === id);
48
+ currentTopics(s)?.find((topic) => topic.id === id); // Don't filter here, need to access all topics by ID
42
49
 
43
50
  /**
44
51
  * Get topics by specific agentId (for AgentBuilder scenarios where agentId differs from activeAgentId)
@@ -79,7 +86,7 @@ const isSearchingTopic = (s: ChatStoreState) => s.isSearchingTopic;
79
86
  const displayTopicsForSidebar =
80
87
  (pageSize: number) =>
81
88
  (s: ChatStoreState): ChatTopic[] | undefined => {
82
- const topics = currentTopics(s);
89
+ const topics = currentTopicsWithoutCron(s);
83
90
  if (!topics) return undefined;
84
91
 
85
92
  // Return only the first page worth of topics for sidebar
@@ -143,6 +150,7 @@ export const topicSelectors = {
143
150
  currentTopicLength,
144
151
  currentTopicWorkingDirectory,
145
152
  currentTopics,
153
+ currentTopicsWithoutCron,
146
154
  currentUnFavTopics,
147
155
  displayTopics,
148
156
  displayTopicsForSidebar,
@@ -4,10 +4,7 @@ import {
4
4
  LocalSystemListFilesPlaceholder,
5
5
  LocalSystemSearchFilesPlaceholder,
6
6
  } from '@lobechat/builtin-tool-local-system/client';
7
- import {
8
- NotebookIdentifier,
9
- NotebookPlaceholders,
10
- } from '@lobechat/builtin-tool-notebook/client';
7
+ import { NotebookIdentifier, NotebookPlaceholders } from '@lobechat/builtin-tool-notebook/client';
11
8
  import {
12
9
  WebBrowsingManifest,
13
10
  WebBrowsingPlaceholders,
@@ -1,85 +0,0 @@
1
- on run argv
2
- set appBundlePath to item 1 of argv
3
-
4
- set settingsBundleIds to {"com.apple.SystemSettings", "com.apple.systempreferences"}
5
-
6
- -- Bring System Settings/Preferences to front (Ventura+ / older). If it doesn't exist, ignore.
7
- repeat with bundleId in settingsBundleIds
8
- try
9
- tell application id bundleId to activate
10
- exit repeat
11
- end try
12
- end repeat
13
-
14
- tell application "System Events"
15
- set settingsProcess to missing value
16
- repeat 30 times
17
- repeat with bundleId in settingsBundleIds
18
- try
19
- if exists (first process whose bundle identifier is bundleId) then
20
- set settingsProcess to first process whose bundle identifier is bundleId
21
- exit repeat
22
- end if
23
- end try
24
- end repeat
25
-
26
- if settingsProcess is not missing value then exit repeat
27
- delay 0.2
28
- end repeat
29
-
30
- if settingsProcess is missing value then return "no-settings-process"
31
-
32
- tell settingsProcess
33
- set frontmost to true
34
-
35
- repeat 30 times
36
- if exists window 1 then exit repeat
37
- delay 0.2
38
- end repeat
39
- if not (exists window 1) then return "no-window"
40
-
41
- -- Best-effort: find an "add" button in the front window and click it.
42
- set clickedAdd to false
43
- repeat 30 times
44
- try
45
- repeat with b in (buttons of window 1)
46
- set bDesc to ""
47
- set bName to ""
48
- set bTitle to ""
49
- try set bDesc to description of b end try
50
- try set bName to name of b end try
51
- try set bTitle to title of b end try
52
-
53
- if (bDesc is "Add") or (bTitle is "Add") or (bName is "+") or (bTitle is "+") then
54
- click b
55
- set clickedAdd to true
56
- exit repeat
57
- end if
58
- end repeat
59
- end try
60
-
61
- if clickedAdd is true then exit repeat
62
- delay 0.2
63
- end repeat
64
-
65
- if clickedAdd is false then return "no-add-button"
66
-
67
- -- Wait for open panel / sheet
68
- repeat 30 times
69
- if exists sheet 1 of window 1 then exit repeat
70
- delay 0.2
71
- end repeat
72
- if not (exists sheet 1 of window 1) then return "no-sheet"
73
-
74
- -- Open "Go to the folder" and input the app bundle path, then confirm.
75
- keystroke "G" using {command down, shift down}
76
- delay 0.3
77
- keystroke appBundlePath
78
- key code 36
79
- delay 0.6
80
- -- Confirm "Open" in the panel (Enter usually triggers default)
81
- key code 36
82
- return "ok"
83
- end tell
84
- end tell
85
- end run