@lobehub/lobehub 2.0.0-next.286 → 2.0.0-next.288

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 (72) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/apps/desktop/src/main/const/theme.ts +0 -3
  3. package/apps/desktop/src/main/core/browser/Browser.ts +1 -1
  4. package/apps/desktop/src/main/core/browser/WindowThemeManager.ts +3 -2
  5. package/apps/desktop/src/main/core/browser/__tests__/Browser.test.ts +0 -1
  6. package/apps/desktop/src/main/core/browser/__tests__/WindowThemeManager.test.ts +8 -5
  7. package/changelog/v1.json +14 -0
  8. package/locales/en-US/plugin.json +3 -5
  9. package/locales/zh-CN/plugin.json +3 -5
  10. package/locales/zh-CN/tool.json +2 -0
  11. package/package.json +1 -1
  12. package/packages/builtin-agents/src/agents/group-supervisor/index.ts +12 -1
  13. package/packages/builtin-agents/src/agents/group-supervisor/systemRole.ts +0 -7
  14. package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/EditLocalFile/index.tsx +93 -0
  15. package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/GlobLocalFiles/index.tsx +73 -0
  16. package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/GrepContent/index.tsx +69 -0
  17. package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/ListLocalFiles/index.tsx +68 -0
  18. package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/ReadLocalFile/index.tsx +74 -0
  19. package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/SearchLocalFiles/index.tsx +70 -0
  20. package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/WriteLocalFile/index.tsx +57 -0
  21. package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/index.ts +14 -0
  22. package/packages/builtin-tool-cloud-sandbox/src/client/Render/WriteFile/index.tsx +54 -35
  23. package/packages/builtin-tool-cloud-sandbox/src/client/components/FilePathDisplay.tsx +52 -0
  24. package/packages/builtin-tool-group-management/src/client/Inspector/ExecuteTasks/index.tsx +90 -0
  25. package/packages/builtin-tool-group-management/src/client/Inspector/index.ts +2 -0
  26. package/packages/builtin-tool-group-management/src/client/Intervention/ExecuteTasks.tsx +237 -0
  27. package/packages/builtin-tool-group-management/src/client/Intervention/index.ts +4 -1
  28. package/packages/builtin-tool-group-management/src/client/Render/index.ts +1 -1
  29. package/packages/builtin-tool-group-management/src/client/Streaming/ExecuteTask/index.tsx +69 -0
  30. package/packages/builtin-tool-group-management/src/client/Streaming/ExecuteTasks/index.tsx +87 -0
  31. package/packages/builtin-tool-group-management/src/client/Streaming/index.ts +4 -0
  32. package/packages/builtin-tool-group-management/src/executor.test.ts +8 -311
  33. package/packages/builtin-tool-group-management/src/executor.ts +5 -160
  34. package/packages/builtin-tool-group-management/src/manifest.ts +50 -94
  35. package/packages/builtin-tool-group-management/src/systemRole.ts +251 -172
  36. package/packages/builtin-tool-group-management/src/types.ts +29 -40
  37. package/packages/context-engine/src/engine/messages/MessagesEngine.ts +6 -4
  38. package/packages/context-engine/src/engine/messages/types.ts +4 -4
  39. package/packages/context-engine/src/processors/GroupRoleTransform.ts +261 -0
  40. package/packages/context-engine/src/processors/__tests__/GroupRoleTransform.test.ts +553 -0
  41. package/packages/context-engine/src/processors/index.ts +2 -2
  42. package/packages/context-engine/src/providers/__tests__/GroupContextInjector.test.ts +4 -16
  43. package/packages/context-engine/src/providers/__tests__/__snapshots__/GroupContextInjector.test.ts.snap +23 -28
  44. package/packages/desktop-bridge/src/index.ts +3 -0
  45. package/packages/prompts/src/prompts/agentGroup/__snapshots__/index.test.ts.snap +0 -7
  46. package/packages/prompts/src/prompts/agentGroup/groupContext.ts +0 -7
  47. package/src/app/[variants]/(main)/group/features/Conversation/AgentWelcome/OpeningQuestions.tsx +4 -8
  48. package/src/app/[variants]/(main)/group/features/Conversation/MainChatInput/GroupChat.tsx +0 -3
  49. package/src/app/[variants]/(main)/group/features/Conversation/useGroupContext.ts +3 -0
  50. package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +15 -2
  51. package/src/features/ChatInput/Desktop/index.tsx +1 -3
  52. package/src/features/Conversation/store/slices/message/action/crud.ts +2 -2
  53. package/src/features/ElectronTitlebar/Connection/ConnectionMode.tsx +2 -2
  54. package/src/features/ElectronTitlebar/SimpleTitleBar.tsx +1 -2
  55. package/src/features/ElectronTitlebar/index.tsx +2 -2
  56. package/src/hooks/useUserAvatar.test.ts +23 -4
  57. package/src/locales/default/plugin.ts +3 -5
  58. package/src/locales/default/tool.ts +3 -0
  59. package/src/services/chat/mecha/agentConfigResolver.test.ts +160 -0
  60. package/src/services/chat/mecha/agentConfigResolver.ts +15 -3
  61. package/src/services/chat/mecha/contextEngineering.ts +2 -1
  62. package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +4 -2
  63. package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +2 -0
  64. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +1 -18
  65. package/src/store/chat/slices/message/selectors/displayMessage.test.ts +24 -0
  66. package/src/store/chat/slices/message/selectors/displayMessage.ts +6 -1
  67. package/src/store/chat/slices/topic/action.test.ts +10 -4
  68. package/src/store/chat/slices/topic/action.ts +3 -2
  69. package/src/store/electron/selectors/sync.ts +17 -1
  70. package/packages/context-engine/src/processors/GroupMessageSender.ts +0 -138
  71. package/packages/context-engine/src/processors/__tests__/GroupMessageSender.test.ts +0 -274
  72. package/src/features/ElectronTitlebar/const.ts +0 -1
@@ -0,0 +1,237 @@
1
+ 'use client';
2
+
3
+ import { DEFAULT_AVATAR } from '@lobechat/const';
4
+ import { BuiltinInterventionProps } from '@lobechat/types';
5
+ import { Avatar, Flexbox, Icon, Tooltip } from '@lobehub/ui';
6
+ import { Collapse, Input, InputNumber } from 'antd';
7
+ import { createStaticStyles, useTheme } from 'antd-style';
8
+ import isEqual from 'fast-deep-equal';
9
+ import { Clock, Trash2 } from 'lucide-react';
10
+ import { ChangeEvent, memo, useCallback, useEffect, useState } from 'react';
11
+ import { useTranslation } from 'react-i18next';
12
+
13
+ import { useAgentGroupStore } from '@/store/agentGroup';
14
+ import { agentGroupSelectors } from '@/store/agentGroup/selectors';
15
+
16
+ import type { ExecuteTasksParams, TaskItem } from '../../types';
17
+
18
+ const styles = createStaticStyles(({ css, cssVar }) => ({
19
+ agentTitle: css`
20
+ font-size: 14px;
21
+ font-weight: 500;
22
+ color: ${cssVar.colorText};
23
+ `,
24
+ container: css`
25
+ padding-block: 12px;
26
+ border-radius: ${cssVar.borderRadius};
27
+ `,
28
+ deleteButton: css`
29
+ cursor: pointer;
30
+ color: ${cssVar.colorTextTertiary};
31
+ transition: color 0.2s;
32
+
33
+ &:hover {
34
+ color: ${cssVar.colorError};
35
+ }
36
+ `,
37
+ taskCard: css`
38
+ .ant-collapse-header {
39
+ padding-block: 8px !important;
40
+ padding-inline: 12px !important;
41
+ }
42
+
43
+ .ant-collapse-content-box {
44
+ padding: 12px !important;
45
+ }
46
+ `,
47
+ taskTitle: css`
48
+ font-size: 13px;
49
+ font-weight: 500;
50
+ color: ${cssVar.colorText};
51
+ `,
52
+ timeoutInput: css`
53
+ width: 100px;
54
+ `,
55
+ }));
56
+
57
+ const DEFAULT_TIMEOUT = 1_800_000; // 30 minutes
58
+
59
+ interface TaskEditorProps {
60
+ index: number;
61
+ onChange: (index: number, updates: Partial<TaskItem>) => void;
62
+ onDelete: (index: number) => void;
63
+ task: TaskItem;
64
+ }
65
+
66
+ const TaskEditor = memo<TaskEditorProps>(({ task, index, onChange, onDelete }) => {
67
+ const { t } = useTranslation('tool');
68
+ const theme = useTheme();
69
+
70
+ // Get agent info from store
71
+ const activeGroupId = useAgentGroupStore(agentGroupSelectors.activeGroupId);
72
+ const agent = useAgentGroupStore((s) =>
73
+ task.agentId && activeGroupId
74
+ ? agentGroupSelectors.getAgentByIdFromGroup(activeGroupId, task.agentId)(s)
75
+ : undefined,
76
+ );
77
+
78
+ const handleTitleChange = useCallback(
79
+ (e: ChangeEvent<HTMLInputElement>) => {
80
+ onChange(index, { title: e.target.value });
81
+ },
82
+ [index, onChange],
83
+ );
84
+
85
+ const handleInstructionChange = useCallback(
86
+ (e: ChangeEvent<HTMLTextAreaElement>) => {
87
+ onChange(index, { instruction: e.target.value });
88
+ },
89
+ [index, onChange],
90
+ );
91
+
92
+ const handleTimeoutChange = useCallback(
93
+ (value: number | null) => {
94
+ if (value !== null) {
95
+ onChange(index, { timeout: value * 60 * 1000 });
96
+ }
97
+ },
98
+ [index, onChange],
99
+ );
100
+
101
+ const handleDelete = useCallback(() => {
102
+ onDelete(index);
103
+ }, [index, onDelete]);
104
+
105
+ const header = (
106
+ <Flexbox align={'center'} gap={8} horizontal justify={'space-between'}>
107
+ <Flexbox align={'center'} flex={1} gap={8} horizontal style={{ minWidth: 0 }}>
108
+ <Avatar
109
+ avatar={agent?.avatar || DEFAULT_AVATAR}
110
+ background={agent?.backgroundColor || theme.colorBgContainer}
111
+ shape={'square'}
112
+ size={24}
113
+ />
114
+ <span className={styles.taskTitle}>{task.title || agent?.title || 'Task'}</span>
115
+ </Flexbox>
116
+ <Flexbox align={'center'} gap={8} horizontal onClick={(e) => e.stopPropagation()}>
117
+ <Tooltip title={t('agentGroupManagement.executeTask.intervention.timeout')}>
118
+ <Clock size={14} />
119
+ </Tooltip>
120
+ <InputNumber
121
+ className={styles.timeoutInput}
122
+ max={120}
123
+ min={1}
124
+ onChange={handleTimeoutChange}
125
+ size={'small'}
126
+ suffix={t('agentGroupManagement.executeTask.intervention.timeoutUnit')}
127
+ value={Math.round((task.timeout || DEFAULT_TIMEOUT) / 60_000)}
128
+ variant={'filled'}
129
+ />
130
+ <Icon
131
+ className={styles.deleteButton}
132
+ icon={Trash2}
133
+ onClick={handleDelete}
134
+ size={{ size: 16 }}
135
+ />
136
+ </Flexbox>
137
+ </Flexbox>
138
+ );
139
+
140
+ return (
141
+ <Collapse
142
+ className={styles.taskCard}
143
+ defaultActiveKey={[index]}
144
+ items={[
145
+ {
146
+ children: (
147
+ <Flexbox gap={12}>
148
+ <Input
149
+ onChange={handleTitleChange}
150
+ placeholder={t('agentGroupManagement.executeTasks.intervention.titlePlaceholder')}
151
+ value={task.title}
152
+ />
153
+ <Input.TextArea
154
+ autoSize={{ maxRows: 8, minRows: 4 }}
155
+ onChange={handleInstructionChange}
156
+ placeholder={t(
157
+ 'agentGroupManagement.executeTasks.intervention.instructionPlaceholder',
158
+ )}
159
+ value={task.instruction}
160
+ />
161
+ </Flexbox>
162
+ ),
163
+ key: index,
164
+ label: header,
165
+ },
166
+ ]}
167
+ />
168
+ );
169
+ });
170
+
171
+ /**
172
+ * ExecuteTasks Intervention Component
173
+ *
174
+ * Allows users to review and modify multiple tasks before execution.
175
+ */
176
+ const ExecuteTasksIntervention = memo<BuiltinInterventionProps<ExecuteTasksParams>>(
177
+ ({ args, onArgsChange, registerBeforeApprove }) => {
178
+ // Local state
179
+ const [tasks, setTasks] = useState<TaskItem[]>(args?.tasks || []);
180
+ const [hasChanges, setHasChanges] = useState(false);
181
+
182
+ // Sync local state when args change externally
183
+ useEffect(() => {
184
+ if (!hasChanges) {
185
+ setTasks(args?.tasks || []);
186
+ }
187
+ }, [args?.tasks, hasChanges]);
188
+
189
+ // Handle task change
190
+ const handleTaskChange = useCallback((index: number, updates: Partial<TaskItem>) => {
191
+ setTasks((prev) => {
192
+ const newTasks = [...prev];
193
+ newTasks[index] = { ...newTasks[index], ...updates };
194
+ return newTasks;
195
+ });
196
+ setHasChanges(true);
197
+ }, []);
198
+
199
+ // Handle task delete
200
+ const handleTaskDelete = useCallback((index: number) => {
201
+ setTasks((prev) => prev.filter((_, i) => i !== index));
202
+ setHasChanges(true);
203
+ }, []);
204
+
205
+ // Save changes before approval
206
+ useEffect(() => {
207
+ if (!registerBeforeApprove) return;
208
+
209
+ const cleanup = registerBeforeApprove('executeTasks', async () => {
210
+ if (hasChanges && onArgsChange) {
211
+ await onArgsChange({ ...args, tasks });
212
+ }
213
+ });
214
+
215
+ return cleanup;
216
+ }, [registerBeforeApprove, hasChanges, tasks, args, onArgsChange]);
217
+
218
+ return (
219
+ <Flexbox className={styles.container} gap={12}>
220
+ {tasks.map((task, index) => (
221
+ <TaskEditor
222
+ index={index}
223
+ key={task.agentId || index}
224
+ onChange={handleTaskChange}
225
+ onDelete={handleTaskDelete}
226
+ task={task}
227
+ />
228
+ ))}
229
+ </Flexbox>
230
+ );
231
+ },
232
+ isEqual,
233
+ );
234
+
235
+ ExecuteTasksIntervention.displayName = 'ExecuteTasksIntervention';
236
+
237
+ export default ExecuteTasksIntervention;
@@ -2,6 +2,7 @@ import { BuiltinIntervention } from '@lobechat/types';
2
2
 
3
3
  import { GroupManagementApiName } from '../../types';
4
4
  import ExecuteTaskIntervention from './ExecuteTask';
5
+ import ExecuteTasksIntervention from './ExecuteTasks';
5
6
 
6
7
  /**
7
8
  * Group Management Tool Intervention Components Registry
@@ -10,7 +11,9 @@ import ExecuteTaskIntervention from './ExecuteTask';
10
11
  * before the tool is executed.
11
12
  */
12
13
  export const GroupManagementInterventions: Record<string, BuiltinIntervention> = {
13
- [GroupManagementApiName.executeTask]: ExecuteTaskIntervention as BuiltinIntervention,
14
+ [GroupManagementApiName.executeAgentTask]: ExecuteTaskIntervention as BuiltinIntervention,
15
+ [GroupManagementApiName.executeAgentTasks]: ExecuteTasksIntervention as BuiltinIntervention,
14
16
  };
15
17
 
16
18
  export { default as ExecuteTaskIntervention } from './ExecuteTask';
19
+ export { default as ExecuteTasksIntervention } from './ExecuteTasks';
@@ -8,7 +8,7 @@ import SpeakRender from './Speak';
8
8
  */
9
9
  export const GroupManagementRenders = {
10
10
  [GroupManagementApiName.broadcast]: BroadcastRender,
11
- [GroupManagementApiName.executeTask]: ExecuteTaskRender,
11
+ [GroupManagementApiName.executeAgentTask]: ExecuteTaskRender,
12
12
  [GroupManagementApiName.speak]: SpeakRender,
13
13
  };
14
14
 
@@ -0,0 +1,69 @@
1
+ 'use client';
2
+
3
+ import { DEFAULT_AVATAR } from '@lobechat/const';
4
+ import type { BuiltinStreamingProps } from '@lobechat/types';
5
+ import { Avatar, Flexbox, Markdown } from '@lobehub/ui';
6
+ import { createStaticStyles, useTheme } from 'antd-style';
7
+ import { memo } from 'react';
8
+
9
+ import { useAgentGroupStore } from '@/store/agentGroup';
10
+ import { agentGroupSelectors } from '@/store/agentGroup/selectors';
11
+
12
+ import type { ExecuteTaskParams } from '../../../types';
13
+
14
+ const styles = createStaticStyles(({ css, cssVar }) => ({
15
+ agentTitle: css`
16
+ font-size: 14px;
17
+ font-weight: 500;
18
+ color: ${cssVar.colorText};
19
+ `,
20
+ container: css`
21
+ padding: 12px;
22
+ border-radius: 8px;
23
+ background: ${cssVar.colorFillQuaternary};
24
+ `,
25
+ task: css`
26
+ font-size: 13px;
27
+ color: ${cssVar.colorTextSecondary};
28
+ `,
29
+ }));
30
+
31
+ export const ExecuteTaskStreaming = memo<BuiltinStreamingProps<ExecuteTaskParams>>(({ args }) => {
32
+ const { agentId, task } = args || {};
33
+ const theme = useTheme();
34
+
35
+ // Get active group ID and agent from store
36
+ const activeGroupId = useAgentGroupStore(agentGroupSelectors.activeGroupId);
37
+ const agent = useAgentGroupStore((s) =>
38
+ activeGroupId && agentId
39
+ ? agentGroupSelectors.getAgentByIdFromGroup(activeGroupId, agentId)(s)
40
+ : undefined,
41
+ );
42
+
43
+ if (!task) return null;
44
+
45
+ return (
46
+ <div className={styles.container}>
47
+ <Flexbox gap={8}>
48
+ <Flexbox align={'center'} gap={8} horizontal>
49
+ <Avatar
50
+ avatar={agent?.avatar || DEFAULT_AVATAR}
51
+ background={agent?.backgroundColor || theme.colorBgContainer}
52
+ shape={'square'}
53
+ size={24}
54
+ />
55
+ <span className={styles.agentTitle}>{agent?.title || 'Agent'}</span>
56
+ </Flexbox>
57
+ <div className={styles.task}>
58
+ <Markdown animated variant={'chat'}>
59
+ {task}
60
+ </Markdown>
61
+ </div>
62
+ </Flexbox>
63
+ </div>
64
+ );
65
+ });
66
+
67
+ ExecuteTaskStreaming.displayName = 'ExecuteTaskStreaming';
68
+
69
+ export default ExecuteTaskStreaming;
@@ -0,0 +1,87 @@
1
+ 'use client';
2
+
3
+ import { DEFAULT_AVATAR } from '@lobechat/const';
4
+ import type { AgentGroupMember, BuiltinStreamingProps } from '@lobechat/types';
5
+ import { Avatar, Flexbox, Markdown } from '@lobehub/ui';
6
+ import { createStaticStyles, useTheme } from 'antd-style';
7
+ import { memo, useMemo } from 'react';
8
+
9
+ import { useAgentGroupStore } from '@/store/agentGroup';
10
+ import { agentGroupSelectors } from '@/store/agentGroup/selectors';
11
+
12
+ import type { ExecuteTasksParams } from '../../../types';
13
+
14
+ const styles = createStaticStyles(({ css, cssVar }) => ({
15
+ container: css`
16
+ display: flex;
17
+ flex-direction: column;
18
+ gap: 12px;
19
+ `,
20
+ instruction: css`
21
+ font-size: 13px;
22
+ color: ${cssVar.colorTextSecondary};
23
+ `,
24
+ taskCard: css`
25
+ padding: 12px;
26
+ border-radius: 8px;
27
+ background: ${cssVar.colorFillQuaternary};
28
+ `,
29
+ taskTitle: css`
30
+ font-size: 13px;
31
+ font-weight: 500;
32
+ color: ${cssVar.colorText};
33
+ `,
34
+ }));
35
+
36
+ export const ExecuteTasksStreaming = memo<BuiltinStreamingProps<ExecuteTasksParams>>(({ args }) => {
37
+ const { tasks } = args || {};
38
+ const theme = useTheme();
39
+
40
+ // Get active group ID and agents from store
41
+ const activeGroupId = useAgentGroupStore(agentGroupSelectors.activeGroupId);
42
+ const groupAgents = useAgentGroupStore((s) =>
43
+ activeGroupId ? agentGroupSelectors.getGroupAgents(activeGroupId)(s) : [],
44
+ );
45
+
46
+ // Get agent details for each task
47
+ const tasksWithAgents = useMemo(() => {
48
+ if (!tasks?.length || !groupAgents.length) return [];
49
+ return tasks.map((task) => ({
50
+ ...task,
51
+ agent: groupAgents.find((agent) => agent.id === task.agentId) as AgentGroupMember | undefined,
52
+ }));
53
+ }, [tasks, groupAgents]);
54
+
55
+ if (!tasksWithAgents.length) return null;
56
+
57
+ return (
58
+ <div className={styles.container}>
59
+ {tasksWithAgents.map((task, index) => (
60
+ <div className={styles.taskCard} key={task.agentId || index}>
61
+ <Flexbox gap={8}>
62
+ <Flexbox align={'center'} gap={8} horizontal>
63
+ <Avatar
64
+ avatar={task.agent?.avatar || DEFAULT_AVATAR}
65
+ background={task.agent?.backgroundColor || theme.colorBgContainer}
66
+ shape={'square'}
67
+ size={20}
68
+ />
69
+ <span className={styles.taskTitle}>{task.title || task.agent?.title || 'Task'}</span>
70
+ </Flexbox>
71
+ {task.instruction && (
72
+ <div className={styles.instruction}>
73
+ <Markdown animated variant={'chat'}>
74
+ {task.instruction}
75
+ </Markdown>
76
+ </div>
77
+ )}
78
+ </Flexbox>
79
+ </div>
80
+ ))}
81
+ </div>
82
+ );
83
+ });
84
+
85
+ ExecuteTasksStreaming.displayName = 'ExecuteTasksStreaming';
86
+
87
+ export default ExecuteTasksStreaming;
@@ -2,6 +2,8 @@ import type { BuiltinStreaming } from '@lobechat/types';
2
2
 
3
3
  import { GroupManagementApiName } from '../../types';
4
4
  import { BroadcastStreaming } from './Broadcast';
5
+ import { ExecuteTaskStreaming } from './ExecuteTask';
6
+ import { ExecuteTasksStreaming } from './ExecuteTasks';
5
7
  import { SpeakStreaming } from './Speak';
6
8
 
7
9
  /**
@@ -12,5 +14,7 @@ import { SpeakStreaming } from './Speak';
12
14
  */
13
15
  export const GroupManagementStreamings: Record<string, BuiltinStreaming> = {
14
16
  [GroupManagementApiName.broadcast]: BroadcastStreaming as BuiltinStreaming,
17
+ [GroupManagementApiName.executeAgentTask]: ExecuteTaskStreaming as BuiltinStreaming,
18
+ [GroupManagementApiName.executeAgentTasks]: ExecuteTasksStreaming as BuiltinStreaming,
15
19
  [GroupManagementApiName.speak]: SpeakStreaming as BuiltinStreaming,
16
20
  };