@lobehub/lobehub 2.0.10 → 2.0.12

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 (101) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/Dockerfile +44 -52
  3. package/changelog/v2.json +18 -0
  4. package/locales/ar/chat.json +4 -0
  5. package/locales/ar/models.json +65 -0
  6. package/locales/bg-BG/chat.json +4 -0
  7. package/locales/bg-BG/models.json +10 -0
  8. package/locales/de-DE/chat.json +4 -0
  9. package/locales/de-DE/models.json +41 -0
  10. package/locales/en-US/chat.json +4 -0
  11. package/locales/es-ES/chat.json +4 -0
  12. package/locales/es-ES/models.json +50 -0
  13. package/locales/fa-IR/chat.json +4 -0
  14. package/locales/fa-IR/models.json +39 -0
  15. package/locales/fr-FR/chat.json +4 -0
  16. package/locales/fr-FR/models.json +9 -0
  17. package/locales/it-IT/chat.json +4 -0
  18. package/locales/it-IT/models.json +62 -0
  19. package/locales/ja-JP/chat.json +4 -0
  20. package/locales/ja-JP/models.json +40 -0
  21. package/locales/ko-KR/chat.json +4 -0
  22. package/locales/ko-KR/models.json +31 -0
  23. package/locales/nl-NL/chat.json +4 -0
  24. package/locales/nl-NL/models.json +52 -0
  25. package/locales/pl-PL/chat.json +4 -0
  26. package/locales/pl-PL/models.json +43 -0
  27. package/locales/pt-BR/chat.json +4 -0
  28. package/locales/pt-BR/models.json +92 -0
  29. package/locales/ru-RU/chat.json +4 -0
  30. package/locales/ru-RU/models.json +34 -0
  31. package/locales/tr-TR/chat.json +4 -0
  32. package/locales/tr-TR/models.json +55 -0
  33. package/locales/vi-VN/chat.json +4 -0
  34. package/locales/vi-VN/models.json +31 -0
  35. package/locales/zh-CN/chat.json +4 -0
  36. package/locales/zh-TW/chat.json +4 -0
  37. package/package.json +1 -1
  38. package/packages/agent-runtime/src/groupOrchestration/GroupOrchestrationSupervisor.ts +18 -1
  39. package/packages/agent-runtime/src/groupOrchestration/__tests__/GroupOrchestrationSupervisor.test.ts +76 -5
  40. package/packages/agent-runtime/src/groupOrchestration/types.ts +3 -3
  41. package/packages/builtin-tool-group-management/src/client/Intervention/ExecuteTask.tsx +11 -11
  42. package/packages/builtin-tool-group-management/src/client/Intervention/ExecuteTasks.tsx +78 -79
  43. package/packages/builtin-tool-group-management/src/client/Render/ExecuteTask/index.tsx +3 -3
  44. package/packages/builtin-tool-group-management/src/client/Render/ExecuteTasks/index.tsx +61 -63
  45. package/packages/builtin-tool-group-management/src/client/Streaming/ExecuteTask/index.tsx +3 -3
  46. package/packages/builtin-tool-group-management/src/executor.test.ts +7 -9
  47. package/packages/builtin-tool-group-management/src/executor.ts +3 -3
  48. package/packages/builtin-tool-group-management/src/manifest.ts +49 -50
  49. package/packages/builtin-tool-group-management/src/systemRole.ts +153 -5
  50. package/packages/builtin-tool-group-management/src/types.ts +3 -2
  51. package/packages/builtin-tool-gtd/src/systemRole.ts +4 -4
  52. package/packages/context-engine/src/processors/TasksFlatten.ts +7 -5
  53. package/packages/context-engine/src/processors/__tests__/TasksFlatten.test.ts +164 -0
  54. package/packages/conversation-flow/src/__tests__/fixtures/inputs/agentGroup/index.ts +4 -0
  55. package/packages/conversation-flow/src/__tests__/fixtures/inputs/agentGroup/supervisor-after-multi-tasks.json +91 -0
  56. package/packages/conversation-flow/src/__tests__/fixtures/inputs/agentGroup/supervisor-content-only.json +74 -0
  57. package/packages/conversation-flow/src/__tests__/parse.test.ts +37 -0
  58. package/packages/conversation-flow/src/transformation/FlatListBuilder.ts +70 -4
  59. package/packages/conversation-flow/src/transformation/__tests__/FlatListBuilder.test.ts +147 -0
  60. package/packages/database/src/repositories/agentGroup/index.ts +4 -0
  61. package/packages/types/src/message/ui/chat.ts +2 -0
  62. package/packages/types/src/tool/builtin.ts +5 -5
  63. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/ForkGroupAndChat.tsx +2 -1
  64. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/index.tsx +2 -2
  65. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/useMarketGroupPublish.ts +11 -12
  66. package/src/features/Conversation/ChatItem/components/Title.tsx +1 -1
  67. package/src/features/Conversation/ChatList/index.tsx +0 -1
  68. package/src/features/Conversation/Messages/GroupTasks/TaskItem/ClientTaskItem.tsx +183 -0
  69. package/src/features/Conversation/Messages/GroupTasks/TaskItem/ServerTaskItem.tsx +94 -0
  70. package/src/features/Conversation/Messages/GroupTasks/TaskItem/TaskTitle.tsx +177 -0
  71. package/src/features/Conversation/Messages/GroupTasks/TaskItem/index.tsx +26 -0
  72. package/src/features/Conversation/Messages/GroupTasks/TaskItem/useClientTaskStats.ts +93 -0
  73. package/src/features/Conversation/Messages/GroupTasks/index.tsx +151 -0
  74. package/src/features/Conversation/Messages/Supervisor/index.tsx +7 -1
  75. package/src/features/Conversation/Messages/Task/ClientTaskDetail/index.tsx +72 -91
  76. package/src/features/Conversation/Messages/Task/TaskDetailPanel/StatusContent.tsx +46 -17
  77. package/src/features/Conversation/Messages/Tasks/TaskItem/ClientTaskItem.tsx +9 -24
  78. package/src/features/Conversation/Messages/Tasks/TaskItem/ServerTaskItem.tsx +18 -38
  79. package/src/features/Conversation/Messages/Tasks/shared/ErrorState.tsx +45 -2
  80. package/src/features/Conversation/Messages/Tasks/shared/InitializingState.tsx +16 -1
  81. package/src/features/Conversation/Messages/Tasks/shared/TaskContent.tsx +68 -0
  82. package/src/features/Conversation/Messages/Tasks/shared/TaskMessages.tsx +383 -0
  83. package/src/features/Conversation/Messages/Tasks/shared/index.ts +4 -0
  84. package/src/features/Conversation/Messages/Tasks/shared/useTaskPolling.ts +48 -0
  85. package/src/features/Conversation/Messages/index.tsx +5 -0
  86. package/src/locales/default/chat.ts +4 -0
  87. package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +4 -0
  88. package/src/server/modules/AgentRuntime/__tests__/RuntimeExecutors.test.ts +106 -1
  89. package/src/server/routers/lambda/agentGroup.ts +2 -0
  90. package/src/server/routers/lambda/market/agent.ts +17 -45
  91. package/src/server/routers/lambda/market/agentGroup.ts +13 -25
  92. package/src/server/services/aiAgent/__tests__/execAgent.threadId.test.ts +2 -2
  93. package/src/server/utils/truncateToolResult.ts +1 -4
  94. package/src/store/chat/agents/GroupOrchestration/__tests__/batch-exec-async-tasks.test.ts +15 -15
  95. package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +22 -15
  96. package/src/store/chat/agents/__tests__/createAgentExecutors/exec-tasks.test.ts +21 -10
  97. package/src/store/chat/agents/createAgentExecutors.ts +2 -0
  98. package/src/store/chat/slices/aiAgent/actions/groupOrchestration.ts +10 -7
  99. package/src/features/Conversation/Messages/Task/ClientTaskDetail/CompletedState.tsx +0 -108
  100. package/src/features/Conversation/Messages/Task/ClientTaskDetail/InstructionAccordion.tsx +0 -63
  101. package/src/features/Conversation/Messages/Task/ClientTaskDetail/ProcessingState.tsx +0 -123
@@ -161,7 +161,7 @@ describe('GroupOrchestrationSupervisor', () => {
161
161
  decision: 'execute_task',
162
162
  params: {
163
163
  agentId: 'agent-1',
164
- task: 'Analyze data',
164
+ instruction: 'Analyze data',
165
165
  timeout: 30000,
166
166
  toolMessageId: 'tool-msg-1',
167
167
  },
@@ -175,7 +175,7 @@ describe('GroupOrchestrationSupervisor', () => {
175
175
  type: 'exec_async_task',
176
176
  payload: {
177
177
  agentId: 'agent-1',
178
- task: 'Analyze data',
178
+ instruction: 'Analyze data',
179
179
  timeout: 30000,
180
180
  title: undefined,
181
181
  toolMessageId: 'tool-msg-1',
@@ -193,7 +193,7 @@ describe('GroupOrchestrationSupervisor', () => {
193
193
  decision: 'execute_task',
194
194
  params: {
195
195
  agentId: 'agent-1',
196
- task: 'Analyze data',
196
+ instruction: 'Analyze data',
197
197
  timeout: 30000,
198
198
  title: 'Data Analysis Task',
199
199
  toolMessageId: 'tool-msg-1',
@@ -208,7 +208,7 @@ describe('GroupOrchestrationSupervisor', () => {
208
208
  type: 'exec_async_task',
209
209
  payload: {
210
210
  agentId: 'agent-1',
211
- task: 'Analyze data',
211
+ instruction: 'Analyze data',
212
212
  timeout: 30000,
213
213
  title: 'Data Analysis Task',
214
214
  toolMessageId: 'tool-msg-1',
@@ -409,7 +409,7 @@ describe('GroupOrchestrationSupervisor', () => {
409
409
  type: 'supervisor_decided',
410
410
  payload: {
411
411
  decision: 'execute_task',
412
- params: { agentId: 'agent-1', task: 'Do something', toolMessageId: 'tool-1' },
412
+ params: { agentId: 'agent-1', instruction: 'Do something', toolMessageId: 'tool-1' },
413
413
  skipCallSupervisor: false,
414
414
  },
415
415
  },
@@ -427,6 +427,77 @@ describe('GroupOrchestrationSupervisor', () => {
427
427
  });
428
428
  });
429
429
 
430
+ describe('decide - execute_tasks decision', () => {
431
+ it('should return batch_exec_async_tasks instruction for execute_tasks decision', async () => {
432
+ // Regression test: execute_tasks decision should return batch_exec_async_tasks instruction
433
+ // Previously, execute_tasks was not implemented and would fall through to default case,
434
+ // returning { type: 'finish', reason: 'unknown_decision: execute_tasks' }
435
+ const supervisor = new GroupOrchestrationSupervisor(defaultConfig);
436
+ const state = createMockState();
437
+
438
+ const result: ExecutorResult = {
439
+ type: 'supervisor_decided',
440
+ payload: {
441
+ decision: 'execute_tasks',
442
+ params: {
443
+ tasks: [
444
+ { agentId: 'agent-1', title: 'Task 1', instruction: 'Do task 1' },
445
+ { agentId: 'agent-2', title: 'Task 2', instruction: 'Do task 2' },
446
+ ],
447
+ toolMessageId: 'tool-msg-1',
448
+ },
449
+ skipCallSupervisor: false,
450
+ },
451
+ };
452
+
453
+ const instruction = await supervisor.decide(result, state);
454
+
455
+ // Should return batch_exec_async_tasks, NOT finish with unknown_decision
456
+ expect(instruction.type).toBe('batch_exec_async_tasks');
457
+ expect((instruction as any).payload).toEqual({
458
+ tasks: [
459
+ { agentId: 'agent-1', title: 'Task 1', instruction: 'Do task 1' },
460
+ { agentId: 'agent-2', title: 'Task 2', instruction: 'Do task 2' },
461
+ ],
462
+ toolMessageId: 'tool-msg-1',
463
+ });
464
+ });
465
+
466
+ it('should handle execute_tasks with skipCallSupervisor flag', async () => {
467
+ const supervisor = new GroupOrchestrationSupervisor(defaultConfig);
468
+ const state = createMockState();
469
+
470
+ // First, trigger execute_tasks with skipCallSupervisor: true
471
+ await supervisor.decide(
472
+ {
473
+ type: 'supervisor_decided',
474
+ payload: {
475
+ decision: 'execute_tasks',
476
+ params: {
477
+ tasks: [{ agentId: 'agent-1', title: 'Task 1', instruction: 'Do task 1' }],
478
+ toolMessageId: 'tool-msg-1',
479
+ },
480
+ skipCallSupervisor: true,
481
+ },
482
+ },
483
+ state,
484
+ );
485
+
486
+ // When tasks_completed, should finish (not call supervisor again)
487
+ const result: ExecutorResult = {
488
+ type: 'tasks_completed',
489
+ payload: { results: [{ agentId: 'agent-1', success: true }] },
490
+ };
491
+
492
+ const instruction = await supervisor.decide(result, state);
493
+
494
+ expect(instruction).toEqual({
495
+ type: 'finish',
496
+ reason: 'skip_call_supervisor',
497
+ });
498
+ });
499
+ });
500
+
430
501
  describe('decide - delegated result', () => {
431
502
  it('should always return finish instruction', async () => {
432
503
  const supervisor = new GroupOrchestrationSupervisor(defaultConfig);
@@ -53,7 +53,7 @@ export interface SupervisorInstructionParallelCallAgents {
53
53
  export interface SupervisorInstructionExecAsyncTask {
54
54
  payload: {
55
55
  agentId: string;
56
- task: string;
56
+ instruction: string;
57
57
  timeout?: number;
58
58
  /** Task title (shown in UI, used as thread title) */
59
59
  title?: string;
@@ -69,7 +69,7 @@ export interface SupervisorInstructionExecAsyncTask {
69
69
  export interface SupervisorInstructionExecClientAsyncTask {
70
70
  payload: {
71
71
  agentId: string;
72
- task: string;
72
+ instruction: string;
73
73
  timeout?: number;
74
74
  /** Task title (shown in UI, used as thread title) */
75
75
  title?: string;
@@ -85,7 +85,7 @@ export interface SupervisorInstructionBatchExecAsyncTasks {
85
85
  payload: {
86
86
  tasks: Array<{
87
87
  agentId: string;
88
- task: string;
88
+ instruction: string;
89
89
  timeout?: number;
90
90
  /** Task title (shown in UI, used as thread title) */
91
91
  title?: string;
@@ -81,21 +81,21 @@ const ExecuteTaskIntervention = memo<BuiltinInterventionProps<ExecuteTaskParams>
81
81
  );
82
82
 
83
83
  // Local state
84
- const [task, setTask] = useState(args?.task || '');
84
+ const [instruction, setInstruction] = useState(args?.instruction || '');
85
85
  const [timeout, setTimeout] = useState(args?.timeout ?? DEFAULT_TIMEOUT);
86
86
  const [hasChanges, setHasChanges] = useState(false);
87
87
 
88
88
  // Sync local state when args change externally
89
89
  useEffect(() => {
90
90
  if (!hasChanges) {
91
- setTask(args?.task || '');
91
+ setInstruction(args?.instruction || '');
92
92
  setTimeout(args?.timeout ?? DEFAULT_TIMEOUT);
93
93
  }
94
- }, [args?.task, args?.timeout, hasChanges]);
94
+ }, [args?.instruction, args?.timeout, hasChanges]);
95
95
 
96
- // Handle task change
97
- const handleTaskChange = useCallback((e: ChangeEvent<HTMLTextAreaElement>) => {
98
- setTask(e.target.value);
96
+ // Handle instruction change
97
+ const handleInstructionChange = useCallback((e: ChangeEvent<HTMLTextAreaElement>) => {
98
+ setInstruction(e.target.value);
99
99
  setHasChanges(true);
100
100
  }, []);
101
101
 
@@ -113,12 +113,12 @@ const ExecuteTaskIntervention = memo<BuiltinInterventionProps<ExecuteTaskParams>
113
113
 
114
114
  const cleanup = registerBeforeApprove('executeTask', async () => {
115
115
  if (hasChanges && onArgsChange) {
116
- await onArgsChange({ ...args, task, timeout });
116
+ await onArgsChange({ ...args, instruction, timeout });
117
117
  }
118
118
  });
119
119
 
120
120
  return cleanup;
121
- }, [registerBeforeApprove, hasChanges, task, timeout, args, onArgsChange]);
121
+ }, [registerBeforeApprove, hasChanges, instruction, timeout, args, onArgsChange]);
122
122
 
123
123
  return (
124
124
  <Flexbox className={styles.container} gap={12}>
@@ -154,12 +154,12 @@ const ExecuteTaskIntervention = memo<BuiltinInterventionProps<ExecuteTaskParams>
154
154
  </Flexbox>
155
155
  </Flexbox>
156
156
 
157
- {/* Task input */}
157
+ {/* Instruction input */}
158
158
  <Input.TextArea
159
159
  autoSize={{ maxRows: 10, minRows: 6 }}
160
- onChange={handleTaskChange}
160
+ onChange={handleInstructionChange}
161
161
  placeholder={t('agentGroupManagement.executeTask.intervention.taskPlaceholder')}
162
- value={task}
162
+ value={instruction}
163
163
  />
164
164
  </Flexbox>
165
165
  );
@@ -2,8 +2,8 @@
2
2
 
3
3
  import { DEFAULT_AVATAR } from '@lobechat/const';
4
4
  import { BuiltinInterventionProps } from '@lobechat/types';
5
- import { Avatar, Flexbox, Icon, Tooltip } from '@lobehub/ui';
6
- import { Collapse, Input, InputNumber } from 'antd';
5
+ import { Accordion, AccordionItem, Avatar, Flexbox, Icon, Tooltip } from '@lobehub/ui';
6
+ import { Input, InputNumber } from 'antd';
7
7
  import { createStaticStyles, useTheme } from 'antd-style';
8
8
  import isEqual from 'fast-deep-equal';
9
9
  import { Clock, Trash2 } from 'lucide-react';
@@ -16,10 +16,14 @@ import { agentGroupSelectors } from '@/store/agentGroup/selectors';
16
16
  import type { ExecuteTasksParams, TaskItem } from '../../types';
17
17
 
18
18
  const styles = createStaticStyles(({ css, cssVar }) => ({
19
- agentTitle: css`
20
- font-size: 14px;
21
- font-weight: 500;
22
- color: ${cssVar.colorText};
19
+ assignee: css`
20
+ display: flex;
21
+ flex-shrink: 0;
22
+ gap: 6px;
23
+ align-items: center;
24
+
25
+ font-size: 12px;
26
+ color: ${cssVar.colorTextSecondary};
23
27
  `,
24
28
  container: css`
25
29
  padding-block: 12px;
@@ -34,20 +38,18 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
34
38
  color: ${cssVar.colorError};
35
39
  }
36
40
  `,
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
- }
41
+ index: css`
42
+ flex-shrink: 0;
43
+ font-size: 12px;
44
+ color: ${cssVar.colorTextQuaternary};
46
45
  `,
47
46
  taskTitle: css`
48
- font-size: 13px;
47
+ overflow: hidden;
48
+
49
+ font-size: 14px;
49
50
  font-weight: 500;
50
- color: ${cssVar.colorText};
51
+ text-overflow: ellipsis;
52
+ white-space: nowrap;
51
53
  `,
52
54
  timeoutInput: css`
53
55
  width: 100px;
@@ -102,69 +104,66 @@ const TaskEditor = memo<TaskEditorProps>(({ task, index, onChange, onDelete }) =
102
104
  onDelete(index);
103
105
  }, [index, onDelete]);
104
106
 
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)}
107
+ return (
108
+ <AccordionItem
109
+ defaultExpand
110
+ itemKey={String(index)}
111
+ paddingBlock={4}
112
+ paddingInline={2}
113
+ title={
114
+ <Flexbox align={'center'} gap={8} horizontal>
115
+ <div className={styles.assignee}>
116
+ <Avatar
117
+ avatar={agent?.avatar || DEFAULT_AVATAR}
118
+ background={agent?.backgroundColor || theme.colorBgContainer}
119
+ shape={'circle'}
120
+ size={20}
121
+ />
122
+ <span>{agent?.title}</span>
123
+ </div>
124
+ </Flexbox>
125
+ }
126
+ >
127
+ <Flexbox gap={12} style={{ marginTop: 8 }}>
128
+ <Flexbox gap={12} horizontal>
129
+ <Input
130
+ onChange={handleTitleChange}
131
+ placeholder={t('agentGroupManagement.executeTasks.intervention.titlePlaceholder')}
132
+ size={'small'}
133
+ value={task.title}
134
+ variant={'filled'}
135
+ />
136
+ <Flexbox align={'center'} gap={8} horizontal onClick={(e) => e.stopPropagation()}>
137
+ <Tooltip title={t('agentGroupManagement.executeTask.intervention.timeout')}>
138
+ <Clock size={14} />
139
+ </Tooltip>
140
+ <InputNumber
141
+ className={styles.timeoutInput}
142
+ max={120}
143
+ min={1}
144
+ onChange={handleTimeoutChange}
145
+ size={'small'}
146
+ suffix={t('agentGroupManagement.executeTask.intervention.timeoutUnit')}
147
+ value={Math.round((task.timeout || DEFAULT_TIMEOUT) / 60_000)}
148
+ variant={'filled'}
149
+ />
150
+ <Icon
151
+ className={styles.deleteButton}
152
+ icon={Trash2}
153
+ onClick={handleDelete}
154
+ size={{ size: 16 }}
155
+ />
156
+ </Flexbox>
157
+ </Flexbox>
158
+ <Input.TextArea
159
+ autoSize={{ maxRows: 20, minRows: 8 }}
160
+ onChange={handleInstructionChange}
161
+ placeholder={t('agentGroupManagement.executeTasks.intervention.instructionPlaceholder')}
162
+ value={task.instruction}
128
163
  variant={'filled'}
129
164
  />
130
- <Icon
131
- className={styles.deleteButton}
132
- icon={Trash2}
133
- onClick={handleDelete}
134
- size={{ size: 16 }}
135
- />
136
165
  </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
- />
166
+ </AccordionItem>
168
167
  );
169
168
  });
170
169
 
@@ -216,7 +215,7 @@ const ExecuteTasksIntervention = memo<BuiltinInterventionProps<ExecuteTasksParam
216
215
  }, [registerBeforeApprove, hasChanges, tasks, args, onArgsChange]);
217
216
 
218
217
  return (
219
- <Flexbox className={styles.container} gap={12}>
218
+ <Accordion className={styles.container} gap={0} variant={'borderless'}>
220
219
  {tasks.map((task, index) => (
221
220
  <TaskEditor
222
221
  index={index}
@@ -226,7 +225,7 @@ const ExecuteTasksIntervention = memo<BuiltinInterventionProps<ExecuteTasksParam
226
225
  task={task}
227
226
  />
228
227
  ))}
229
- </Flexbox>
228
+ </Accordion>
230
229
  );
231
230
  },
232
231
  isEqual,
@@ -54,10 +54,10 @@ const ExecuteTaskRender = memo<BuiltinRenderProps<ExecuteTaskParams, ExecuteTask
54
54
  </Flexbox>
55
55
  </Flexbox>
56
56
 
57
- {/* Task content (read-only) */}
58
- {args?.task && (
57
+ {/* Instruction content (read-only) */}
58
+ {args?.instruction && (
59
59
  <Text className={styles.taskContent} style={{ margin: 0 }}>
60
- {args.task}
60
+ {args.instruction}
61
61
  </Text>
62
62
  )}
63
63
  </Flexbox>
@@ -2,11 +2,9 @@
2
2
 
3
3
  import { DEFAULT_AVATAR } from '@lobechat/const';
4
4
  import type { AgentGroupMember, BuiltinRenderProps } from '@lobechat/types';
5
- import { Avatar, Flexbox, Text } from '@lobehub/ui';
5
+ import { Accordion, AccordionItem, Avatar, Block, Flexbox, Text } from '@lobehub/ui';
6
6
  import { createStaticStyles, useTheme } from 'antd-style';
7
- import { Clock } from 'lucide-react';
8
7
  import { memo, useMemo } from 'react';
9
- import { useTranslation } from 'react-i18next';
10
8
 
11
9
  import { useAgentGroupStore } from '@/store/agentGroup';
12
10
  import { agentGroupSelectors } from '@/store/agentGroup/selectors';
@@ -14,40 +12,45 @@ import { agentGroupSelectors } from '@/store/agentGroup/selectors';
14
12
  import type { ExecuteTasksParams } from '../../../types';
15
13
 
16
14
  const styles = createStaticStyles(({ css, cssVar }) => ({
17
- container: css`
15
+ assignee: css`
18
16
  display: flex;
19
- flex-direction: column;
20
- gap: 12px;
21
- padding-block: 12px;
17
+ flex-shrink: 0;
18
+ gap: 6px;
19
+ align-items: center;
20
+
21
+ font-size: 12px;
22
+ color: ${cssVar.colorTextSecondary};
22
23
  `,
23
- taskCard: css`
24
- padding: 12px;
25
- border-radius: 8px;
26
- background: ${cssVar.colorFillQuaternary};
24
+ container: css`
25
+ .accordion-action {
26
+ margin-inline-end: 8px;
27
+ opacity: 1 !important;
28
+ }
27
29
  `,
28
- taskContent: css`
29
- padding-block: 8px;
30
- padding-inline: 12px;
31
- border-radius: ${cssVar.borderRadius};
32
- background: ${cssVar.colorFillTertiary};
30
+ index: css`
31
+ flex-shrink: 0;
32
+ font-size: 12px;
33
+ color: ${cssVar.colorTextQuaternary};
33
34
  `,
34
- taskHeader: css`
35
+ instruction: css`
35
36
  font-size: 13px;
36
- font-weight: 500;
37
- color: ${cssVar.colorText};
37
+ line-height: 1.6;
38
+ color: ${cssVar.colorTextSecondary};
38
39
  `,
39
- timeout: css`
40
- font-size: 12px;
41
- color: ${cssVar.colorTextTertiary};
40
+
41
+ taskTitle: css`
42
+ overflow: hidden;
43
+ font-size: 14px;
44
+ text-overflow: ellipsis;
45
+ white-space: nowrap;
42
46
  `,
43
47
  }));
44
48
 
45
49
  /**
46
50
  * ExecuteTasks Render component for Group Management tool
47
- * Read-only display of multiple task execution requests
51
+ * Accordion-style task list with expandable instruction and assignee on the right
48
52
  */
49
53
  const ExecuteTasksRender = memo<BuiltinRenderProps<ExecuteTasksParams>>(({ args }) => {
50
- const { t } = useTranslation('tool');
51
54
  const theme = useTheme();
52
55
  const { tasks } = args || {};
53
56
 
@@ -69,46 +72,41 @@ const ExecuteTasksRender = memo<BuiltinRenderProps<ExecuteTasksParams>>(({ args
69
72
  if (!tasksWithAgents.length) return null;
70
73
 
71
74
  return (
72
- <div className={styles.container}>
73
- {tasksWithAgents.map((task, index) => {
74
- const timeoutMinutes = task.timeout ? Math.round(task.timeout / 60_000) : 30;
75
-
76
- return (
77
- <div className={styles.taskCard} key={task.agentId || index}>
78
- <Flexbox gap={12}>
79
- {/* Header: Agent info + Timeout */}
80
- <Flexbox align={'center'} gap={12} horizontal justify={'space-between'}>
81
- <Flexbox align={'center'} flex={1} gap={8} horizontal style={{ minWidth: 0 }}>
82
- <Avatar
83
- avatar={task.agent?.avatar || DEFAULT_AVATAR}
84
- background={task.agent?.backgroundColor || theme.colorBgContainer}
85
- shape={'square'}
86
- size={20}
87
- />
88
- <span className={styles.taskHeader}>
89
- {task.title || task.agent?.title || 'Task'}
90
- </span>
91
- </Flexbox>
92
- <Flexbox align="center" className={styles.timeout} gap={4} horizontal>
93
- <Clock size={14} />
94
- <span>
95
- {timeoutMinutes}{' '}
96
- {t('agentGroupManagement.executeTask.intervention.timeoutUnit')}
97
- </span>
98
- </Flexbox>
99
- </Flexbox>
100
-
101
- {/* Task content (read-only) */}
102
- {task.instruction && (
103
- <Text className={styles.taskContent} style={{ margin: 0 }}>
104
- {task.instruction}
105
- </Text>
106
- )}
75
+ <Accordion className={styles.container} defaultExpandedKeys={[]} gap={0} variant={'borderless'}>
76
+ {tasksWithAgents.map((task, index) => (
77
+ <AccordionItem
78
+ action={
79
+ <div className={styles.assignee}>
80
+ <Avatar
81
+ avatar={task.agent?.avatar || DEFAULT_AVATAR}
82
+ background={task.agent?.backgroundColor || theme.colorBgContainer}
83
+ shape={'circle'}
84
+ size={20}
85
+ />
86
+ <span>{task.agent?.title}</span>
87
+ </div>
88
+ }
89
+ itemKey={task.agentId || String(index)}
90
+ key={task.agentId || index}
91
+ paddingBlock={8}
92
+ paddingInline={4}
93
+ title={
94
+ <Flexbox align={'center'} gap={8} horizontal style={{ minWidth: 0 }}>
95
+ <span className={styles.index}>{index + 1}.</span>
96
+ <Text className={styles.taskTitle} weight={500}>
97
+ {task.title || 'Task'}
98
+ </Text>
107
99
  </Flexbox>
108
- </div>
109
- );
110
- })}
111
- </div>
100
+ }
101
+ >
102
+ {task.instruction && (
103
+ <Block padding={12} style={{ marginTop: 8 }} variant={'filled'}>
104
+ <Text className={styles.instruction}>{task.instruction}</Text>
105
+ </Block>
106
+ )}
107
+ </AccordionItem>
108
+ ))}
109
+ </Accordion>
112
110
  );
113
111
  });
114
112
 
@@ -29,7 +29,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
29
29
  }));
30
30
 
31
31
  export const ExecuteTaskStreaming = memo<BuiltinStreamingProps<ExecuteTaskParams>>(({ args }) => {
32
- const { agentId, task } = args || {};
32
+ const { agentId, instruction } = args || {};
33
33
  const theme = useTheme();
34
34
 
35
35
  // Get active group ID and agent from store
@@ -40,7 +40,7 @@ export const ExecuteTaskStreaming = memo<BuiltinStreamingProps<ExecuteTaskParams
40
40
  : undefined,
41
41
  );
42
42
 
43
- if (!task) return null;
43
+ if (!instruction) return null;
44
44
 
45
45
  return (
46
46
  <div className={styles.container}>
@@ -56,7 +56,7 @@ export const ExecuteTaskStreaming = memo<BuiltinStreamingProps<ExecuteTaskParams
56
56
  </Flexbox>
57
57
  <div className={styles.task}>
58
58
  <Markdown animated variant={'chat'}>
59
- {task}
59
+ {instruction}
60
60
  </Markdown>
61
61
  </div>
62
62
  </Flexbox>