@lobehub/lobehub 2.0.10 → 2.0.11

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 (94) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/Dockerfile +44 -52
  3. package/changelog/v2.json +9 -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/types/src/message/ui/chat.ts +2 -0
  61. package/packages/types/src/tool/builtin.ts +5 -5
  62. package/src/features/Conversation/ChatItem/components/Title.tsx +1 -1
  63. package/src/features/Conversation/ChatList/index.tsx +0 -1
  64. package/src/features/Conversation/Messages/GroupTasks/TaskItem/ClientTaskItem.tsx +183 -0
  65. package/src/features/Conversation/Messages/GroupTasks/TaskItem/ServerTaskItem.tsx +94 -0
  66. package/src/features/Conversation/Messages/GroupTasks/TaskItem/TaskTitle.tsx +177 -0
  67. package/src/features/Conversation/Messages/GroupTasks/TaskItem/index.tsx +26 -0
  68. package/src/features/Conversation/Messages/GroupTasks/TaskItem/useClientTaskStats.ts +93 -0
  69. package/src/features/Conversation/Messages/GroupTasks/index.tsx +151 -0
  70. package/src/features/Conversation/Messages/Supervisor/index.tsx +7 -1
  71. package/src/features/Conversation/Messages/Task/ClientTaskDetail/index.tsx +72 -91
  72. package/src/features/Conversation/Messages/Task/TaskDetailPanel/StatusContent.tsx +46 -17
  73. package/src/features/Conversation/Messages/Tasks/TaskItem/ClientTaskItem.tsx +9 -24
  74. package/src/features/Conversation/Messages/Tasks/TaskItem/ServerTaskItem.tsx +18 -38
  75. package/src/features/Conversation/Messages/Tasks/shared/ErrorState.tsx +45 -2
  76. package/src/features/Conversation/Messages/Tasks/shared/InitializingState.tsx +16 -1
  77. package/src/features/Conversation/Messages/Tasks/shared/TaskContent.tsx +68 -0
  78. package/src/features/Conversation/Messages/Tasks/shared/TaskMessages.tsx +383 -0
  79. package/src/features/Conversation/Messages/Tasks/shared/index.ts +4 -0
  80. package/src/features/Conversation/Messages/Tasks/shared/useTaskPolling.ts +48 -0
  81. package/src/features/Conversation/Messages/index.tsx +5 -0
  82. package/src/locales/default/chat.ts +4 -0
  83. package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +4 -0
  84. package/src/server/modules/AgentRuntime/__tests__/RuntimeExecutors.test.ts +106 -1
  85. package/src/server/services/aiAgent/__tests__/execAgent.threadId.test.ts +2 -2
  86. package/src/server/utils/truncateToolResult.ts +1 -4
  87. package/src/store/chat/agents/GroupOrchestration/__tests__/batch-exec-async-tasks.test.ts +15 -15
  88. package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +22 -15
  89. package/src/store/chat/agents/__tests__/createAgentExecutors/exec-tasks.test.ts +21 -10
  90. package/src/store/chat/agents/createAgentExecutors.ts +2 -0
  91. package/src/store/chat/slices/aiAgent/actions/groupOrchestration.ts +10 -7
  92. package/src/features/Conversation/Messages/Task/ClientTaskDetail/CompletedState.tsx +0 -108
  93. package/src/features/Conversation/Messages/Task/ClientTaskDetail/InstructionAccordion.tsx +0 -63
  94. package/src/features/Conversation/Messages/Task/ClientTaskDetail/ProcessingState.tsx +0 -123
@@ -1,6 +1,10 @@
1
1
  import type { Message } from '../../../../types';
2
2
  import speakDifferentAgent from './speak-different-agent.json';
3
+ import supervisorAfterMultiTasks from './supervisor-after-multi-tasks.json';
4
+ import supervisorContentOnly from './supervisor-content-only.json';
3
5
 
4
6
  export const agentGroup = {
5
7
  speakDifferentAgent: speakDifferentAgent as Message[],
8
+ supervisorAfterMultiTasks: supervisorAfterMultiTasks as Message[],
9
+ supervisorContentOnly: supervisorContentOnly as Message[],
6
10
  };
@@ -0,0 +1,91 @@
1
+ [
2
+ {
3
+ "id": "msg-user-1",
4
+ "role": "user",
5
+ "content": "帮我调研下 clawdbot",
6
+ "parentId": null,
7
+ "createdAt": 1704067200000,
8
+ "updatedAt": 1704067200000
9
+ },
10
+ {
11
+ "id": "msg-supervisor-1",
12
+ "role": "assistant",
13
+ "agentId": "supervisor",
14
+ "content": "我会安排团队成员进行调研。",
15
+ "parentId": "msg-user-1",
16
+ "tools": [
17
+ {
18
+ "id": "call_tasks_1",
19
+ "type": "builtin",
20
+ "apiName": "executeAgentTasks",
21
+ "arguments": "{\"tasks\":[{\"agentId\":\"agent-1\",\"title\":\"任务1\"},{\"agentId\":\"agent-2\",\"title\":\"任务2\"}]}",
22
+ "identifier": "lobe-group-management"
23
+ }
24
+ ],
25
+ "createdAt": 1704067201000,
26
+ "updatedAt": 1704067201000,
27
+ "metadata": {
28
+ "isSupervisor": true
29
+ }
30
+ },
31
+ {
32
+ "id": "msg-tool-1",
33
+ "role": "tool",
34
+ "content": "Triggered 2 tasks.",
35
+ "parentId": "msg-supervisor-1",
36
+ "tool_call_id": "call_tasks_1",
37
+ "createdAt": 1704067202000,
38
+ "updatedAt": 1704067202000
39
+ },
40
+ {
41
+ "id": "msg-task-1",
42
+ "role": "task",
43
+ "content": "调研结果1...",
44
+ "parentId": "msg-tool-1",
45
+ "agentId": "agent-1",
46
+ "createdAt": 1704067203000,
47
+ "updatedAt": 1704067203000,
48
+ "metadata": {
49
+ "taskTitle": "任务1"
50
+ },
51
+ "taskDetail": {
52
+ "status": "completed",
53
+ "threadId": "thd_xxx1",
54
+ "title": "任务1"
55
+ }
56
+ },
57
+ {
58
+ "id": "msg-task-2",
59
+ "role": "task",
60
+ "content": "调研结果2...",
61
+ "parentId": "msg-tool-1",
62
+ "agentId": "agent-2",
63
+ "createdAt": 1704067204000,
64
+ "updatedAt": 1704067204000,
65
+ "metadata": {
66
+ "taskTitle": "任务2"
67
+ },
68
+ "taskDetail": {
69
+ "status": "completed",
70
+ "threadId": "thd_xxx2",
71
+ "title": "任务2"
72
+ }
73
+ },
74
+ {
75
+ "id": "msg-supervisor-summary",
76
+ "role": "assistant",
77
+ "agentId": "supervisor",
78
+ "content": "调研完成!这是综合汇总报告...",
79
+ "parentId": "msg-task-2",
80
+ "tools": null,
81
+ "createdAt": 1704067210000,
82
+ "updatedAt": 1704067210000,
83
+ "metadata": {
84
+ "isSupervisor": true,
85
+ "tps": 78.99,
86
+ "cost": 0.208
87
+ },
88
+ "model": "claude-sonnet-4",
89
+ "provider": "anthropic"
90
+ }
91
+ ]
@@ -0,0 +1,74 @@
1
+ [
2
+ {
3
+ "id": "msg-user-1",
4
+ "role": "user",
5
+ "content": "帮我调研下 clawdbot",
6
+ "parentId": null,
7
+ "createdAt": 1704067200000,
8
+ "updatedAt": 1704067200000
9
+ },
10
+ {
11
+ "id": "msg-supervisor-1",
12
+ "role": "assistant",
13
+ "agentId": "supervisor",
14
+ "content": "我会安排团队成员进行调研。",
15
+ "parentId": "msg-user-1",
16
+ "tools": [
17
+ {
18
+ "id": "call_tasks_1",
19
+ "type": "builtin",
20
+ "apiName": "executeAgentTasks",
21
+ "arguments": "{\"tasks\":[{\"agentId\":\"agent-1\",\"title\":\"调研任务\"}]}",
22
+ "identifier": "lobe-group-management"
23
+ }
24
+ ],
25
+ "createdAt": 1704067201000,
26
+ "updatedAt": 1704067201000,
27
+ "metadata": {
28
+ "isSupervisor": true
29
+ }
30
+ },
31
+ {
32
+ "id": "msg-tool-1",
33
+ "role": "tool",
34
+ "content": "Triggered 1 task.",
35
+ "parentId": "msg-supervisor-1",
36
+ "tool_call_id": "call_tasks_1",
37
+ "createdAt": 1704067202000,
38
+ "updatedAt": 1704067202000
39
+ },
40
+ {
41
+ "id": "msg-task-1",
42
+ "role": "task",
43
+ "content": "调研结果内容...",
44
+ "parentId": "msg-tool-1",
45
+ "agentId": "agent-1",
46
+ "createdAt": 1704067203000,
47
+ "updatedAt": 1704067203000,
48
+ "metadata": {
49
+ "taskTitle": "调研任务"
50
+ },
51
+ "taskDetail": {
52
+ "status": "completed",
53
+ "threadId": "thd_xxx",
54
+ "title": "调研任务"
55
+ }
56
+ },
57
+ {
58
+ "id": "msg-supervisor-summary",
59
+ "role": "assistant",
60
+ "agentId": "supervisor",
61
+ "content": "调研完成!这是综合汇总报告...",
62
+ "parentId": "msg-task-1",
63
+ "tools": null,
64
+ "createdAt": 1704067210000,
65
+ "updatedAt": 1704067210000,
66
+ "metadata": {
67
+ "isSupervisor": true,
68
+ "tps": 78.99,
69
+ "cost": 0.208
70
+ },
71
+ "model": "claude-sonnet-4",
72
+ "provider": "anthropic"
73
+ }
74
+ ]
@@ -153,6 +153,43 @@ describe('parse', () => {
153
153
 
154
154
  expect(serializeParseResult(result)).toEqual(outputs.agentGroup.speakDifferentAgent);
155
155
  });
156
+
157
+ it('should handle supervisor content-only message (no tools)', () => {
158
+ const result = parse(inputs.agentGroup.supervisorContentOnly);
159
+
160
+ // The critical assertions:
161
+ // 1. The final supervisor message (content-only, no tools) should be transformed to role='supervisor'
162
+ // 2. Its content should be moved to children array
163
+ const supervisorSummary = result.flatList.find((m) => m.id === 'msg-supervisor-summary');
164
+ expect(supervisorSummary).toBeDefined();
165
+ expect(supervisorSummary?.role).toBe('supervisor');
166
+ expect((supervisorSummary as any)?.children).toHaveLength(1);
167
+ expect((supervisorSummary as any)?.children[0].content).toBe('调研完成!这是综合汇总报告...');
168
+ // The top-level content should be empty
169
+ expect(supervisorSummary?.content).toBe('');
170
+ });
171
+
172
+ it('should handle supervisor summary after multiple tasks (content folded into children)', () => {
173
+ const result = parse(inputs.agentGroup.supervisorAfterMultiTasks);
174
+
175
+ // The critical assertions:
176
+ // 1. flatList should have: user, supervisor(+tool), groupTasks(2 tasks), supervisor-summary
177
+ expect(result.flatList).toHaveLength(4);
178
+ expect(result.flatList[0].role).toBe('user');
179
+ expect(result.flatList[1].role).toBe('supervisor');
180
+ expect(result.flatList[2].role).toBe('groupTasks');
181
+ expect(result.flatList[3].role).toBe('supervisor');
182
+
183
+ // 2. groupTasks should have 2 tasks
184
+ expect((result.flatList[2] as any).tasks).toHaveLength(2);
185
+
186
+ // 3. The supervisor summary (no tools) should have content folded into children
187
+ const supervisorSummary = result.flatList[3];
188
+ expect(supervisorSummary.id).toBe('msg-supervisor-summary');
189
+ expect(supervisorSummary.content).toBe(''); // content should be empty
190
+ expect((supervisorSummary as any).children).toHaveLength(1);
191
+ expect((supervisorSummary as any).children[0].content).toBe('调研完成!这是综合汇总报告...');
192
+ });
156
193
  });
157
194
 
158
195
  describe('Tasks Aggregation', () => {
@@ -98,8 +98,16 @@ export class FlatListBuilder {
98
98
  return child?.role !== 'task';
99
99
  });
100
100
 
101
- // Create tasks virtual message
102
- const tasksMessage = this.createTasksMessage(parentMessage, taskChildren, processedIds);
101
+ // Check if tasks have different agentIds (groupTasks) or same agentId (tasks)
102
+ const taskAgentIds = new Set(
103
+ taskChildren.map((childId) => this.messageMap.get(childId)?.agentId).filter(Boolean),
104
+ );
105
+ const isGroupTasks = taskAgentIds.size > 1;
106
+
107
+ // Create appropriate virtual message based on agent diversity
108
+ const tasksMessage = isGroupTasks
109
+ ? this.createGroupTasksMessage(parentMessage, taskChildren, processedIds)
110
+ : this.createTasksMessage(parentMessage, taskChildren, processedIds);
103
111
  flatList.push(tasksMessage);
104
112
 
105
113
  // Continue with non-task children (e.g., final summary from assistant)
@@ -136,8 +144,18 @@ export class FlatListBuilder {
136
144
  taskGrandchild.tools &&
137
145
  taskGrandchild.tools.length > 0
138
146
  ) {
139
- this.processAssistantGroup(
140
- taskGrandchild,
147
+ this.processAssistantGroup(taskGrandchild, flatList, processedIds, allMessages);
148
+ } else if (
149
+ // Check if it's a supervisor message without tools (content-only)
150
+ taskGrandchild.role === 'assistant' &&
151
+ taskGrandchild.metadata?.isSupervisor &&
152
+ (!taskGrandchild.tools || taskGrandchild.tools.length === 0)
153
+ ) {
154
+ const supervisorMessage = this.createSupervisorContentMessage(taskGrandchild);
155
+ flatList.push(supervisorMessage);
156
+ processedIds.add(taskGrandchildId);
157
+ this.buildFlatListRecursive(
158
+ taskGrandchildId,
141
159
  flatList,
142
160
  processedIds,
143
161
  allMessages,
@@ -1037,4 +1055,52 @@ export class FlatListBuilder {
1037
1055
  updatedAt,
1038
1056
  } as Message;
1039
1057
  }
1058
+
1059
+ /**
1060
+ * Create a virtual groupTasks message for multiple tasks with different agentIds
1061
+ */
1062
+ private createGroupTasksMessage(
1063
+ parentMessage: Message,
1064
+ taskChildIds: string[],
1065
+ processedIds: Set<string>,
1066
+ ): Message {
1067
+ const taskMessages: Message[] = [];
1068
+
1069
+ for (const taskId of taskChildIds) {
1070
+ const taskMessage = this.messageMap.get(taskId);
1071
+ if (taskMessage) {
1072
+ taskMessages.push(taskMessage);
1073
+ processedIds.add(taskId);
1074
+ }
1075
+ }
1076
+
1077
+ // Sort by createdAt to maintain order
1078
+ taskMessages.sort((a, b) => a.createdAt - b.createdAt);
1079
+
1080
+ // Generate ID with parent message id and all task message ids
1081
+ const taskIdsStr = taskMessages.map((t) => t.id).join('-');
1082
+ const groupTasksId = `groupTasks-${parentMessage.id}-${taskIdsStr}`;
1083
+
1084
+ // Calculate timestamps from task messages
1085
+ const createdAt =
1086
+ taskMessages.length > 0
1087
+ ? Math.min(...taskMessages.map((m) => m.createdAt))
1088
+ : parentMessage.createdAt;
1089
+ const updatedAt =
1090
+ taskMessages.length > 0
1091
+ ? Math.max(...taskMessages.map((m) => m.updatedAt))
1092
+ : parentMessage.updatedAt;
1093
+
1094
+ return {
1095
+ content: '',
1096
+ createdAt,
1097
+ extra: {
1098
+ parentMessageId: parentMessage.id,
1099
+ },
1100
+ id: groupTasksId,
1101
+ role: 'groupTasks' as any,
1102
+ tasks: taskMessages as any,
1103
+ updatedAt,
1104
+ } as Message;
1105
+ }
1040
1106
  }
@@ -557,5 +557,152 @@ describe('FlatListBuilder', () => {
557
557
  expect(result[1].id).toBe('msg-2');
558
558
  expect(result[2].id).toBe('msg-3');
559
559
  });
560
+
561
+ it('should create tasks message when multiple tasks have same agentId', () => {
562
+ const messages: Message[] = [
563
+ {
564
+ content: 'User request',
565
+ createdAt: 0,
566
+ id: 'msg-1',
567
+ role: 'user',
568
+ updatedAt: 0,
569
+ },
570
+ {
571
+ content: 'Tool message',
572
+ createdAt: 0,
573
+ id: 'tool-1',
574
+ parentId: 'msg-1',
575
+ role: 'tool',
576
+ updatedAt: 0,
577
+ },
578
+ {
579
+ agentId: 'agent-1',
580
+ content: 'Task 1 result',
581
+ createdAt: 1,
582
+ id: 'task-1',
583
+ parentId: 'tool-1',
584
+ role: 'task',
585
+ updatedAt: 1,
586
+ },
587
+ {
588
+ agentId: 'agent-1',
589
+ content: 'Task 2 result',
590
+ createdAt: 2,
591
+ id: 'task-2',
592
+ parentId: 'tool-1',
593
+ role: 'task',
594
+ updatedAt: 2,
595
+ },
596
+ ];
597
+
598
+ const builder = createBuilder(messages);
599
+ const result = builder.flatten(messages);
600
+
601
+ // Should create tasks (not groupTasks) since all tasks have same agentId
602
+ expect(result).toHaveLength(3);
603
+ expect(result[0].id).toBe('msg-1');
604
+ expect(result[1].id).toBe('tool-1');
605
+ expect(result[2].role).toBe('tasks');
606
+ expect((result[2] as any).tasks).toHaveLength(2);
607
+ });
608
+
609
+ it('should create groupTasks message when multiple tasks have different agentIds', () => {
610
+ const messages: Message[] = [
611
+ {
612
+ content: 'User request',
613
+ createdAt: 0,
614
+ id: 'msg-1',
615
+ role: 'user',
616
+ updatedAt: 0,
617
+ },
618
+ {
619
+ content: 'Tool message',
620
+ createdAt: 0,
621
+ id: 'tool-1',
622
+ parentId: 'msg-1',
623
+ role: 'tool',
624
+ updatedAt: 0,
625
+ },
626
+ {
627
+ agentId: 'agent-1',
628
+ content: 'Task 1 result',
629
+ createdAt: 1,
630
+ id: 'task-1',
631
+ parentId: 'tool-1',
632
+ role: 'task',
633
+ updatedAt: 1,
634
+ },
635
+ {
636
+ agentId: 'agent-2',
637
+ content: 'Task 2 result',
638
+ createdAt: 2,
639
+ id: 'task-2',
640
+ parentId: 'tool-1',
641
+ role: 'task',
642
+ updatedAt: 2,
643
+ },
644
+ {
645
+ agentId: 'agent-3',
646
+ content: 'Task 3 result',
647
+ createdAt: 3,
648
+ id: 'task-3',
649
+ parentId: 'tool-1',
650
+ role: 'task',
651
+ updatedAt: 3,
652
+ },
653
+ ];
654
+
655
+ const builder = createBuilder(messages);
656
+ const result = builder.flatten(messages);
657
+
658
+ // Should create groupTasks since tasks have different agentIds
659
+ expect(result).toHaveLength(3);
660
+ expect(result[0].id).toBe('msg-1');
661
+ expect(result[1].id).toBe('tool-1');
662
+ expect(result[2].role).toBe('groupTasks');
663
+ expect((result[2] as any).tasks).toHaveLength(3);
664
+ // Verify ID format
665
+ expect(result[2].id).toContain('groupTasks-');
666
+ });
667
+
668
+ it('should create groupTasks with correct timestamps from task messages', () => {
669
+ const messages: Message[] = [
670
+ {
671
+ content: 'Tool message',
672
+ createdAt: 0,
673
+ id: 'tool-1',
674
+ role: 'tool',
675
+ updatedAt: 0,
676
+ },
677
+ {
678
+ agentId: 'agent-1',
679
+ content: 'Task 1',
680
+ createdAt: 100,
681
+ id: 'task-1',
682
+ parentId: 'tool-1',
683
+ role: 'task',
684
+ updatedAt: 150,
685
+ },
686
+ {
687
+ agentId: 'agent-2',
688
+ content: 'Task 2',
689
+ createdAt: 200,
690
+ id: 'task-2',
691
+ parentId: 'tool-1',
692
+ role: 'task',
693
+ updatedAt: 300,
694
+ },
695
+ ];
696
+
697
+ const builder = createBuilder(messages);
698
+ const result = builder.flatten(messages);
699
+
700
+ const groupTasksMsg = result.find((m) => m.role === 'groupTasks');
701
+ expect(groupTasksMsg).toBeDefined();
702
+ // createdAt should be min of task createdAt
703
+ expect(groupTasksMsg!.createdAt).toBe(100);
704
+ // updatedAt should be max of task updatedAt
705
+ expect(groupTasksMsg!.updatedAt).toBe(300);
706
+ });
560
707
  });
561
708
  });
@@ -25,6 +25,7 @@ export type UIMessageRoleType =
25
25
  | 'tool'
26
26
  | 'task'
27
27
  | 'tasks'
28
+ | 'groupTasks'
28
29
  | 'supervisor'
29
30
  | 'assistantGroup'
30
31
  | 'agentCouncil'
@@ -185,6 +186,7 @@ export interface UIChatMessage {
185
186
  /**
186
187
  * Task messages for role='tasks' virtual message
187
188
  * Contains aggregated task messages with same parentId
189
+ * Also used to store task execution messages (intermediate steps) from polling
188
190
  */
189
191
  tasks?: UIChatMessage[];
190
192
  threadId?: string | null;
@@ -433,6 +433,10 @@ export interface TriggerExecuteTaskParams extends GroupOrchestrationBaseParams {
433
433
  * The agent ID to execute the task
434
434
  */
435
435
  agentId: string;
436
+ /**
437
+ * The instruction/task description for the agent
438
+ */
439
+ instruction: string;
436
440
  /**
437
441
  * Whether to run on the desktop client (for local file/shell access).
438
442
  * MUST be true when task requires local-system tools. Default is false (server execution).
@@ -443,10 +447,6 @@ export interface TriggerExecuteTaskParams extends GroupOrchestrationBaseParams {
443
447
  * without calling the supervisor again.
444
448
  */
445
449
  skipCallSupervisor?: boolean;
446
- /**
447
- * The task description for the agent
448
- */
449
- task: string;
450
450
  /**
451
451
  * Optional timeout in milliseconds
452
452
  */
@@ -466,7 +466,7 @@ export interface TriggerExecuteTaskItem {
466
466
  */
467
467
  agentId: string;
468
468
  /**
469
- * Detailed instruction/prompt for the task execution
469
+ * Detailed instruction for the agent to execute
470
470
  */
471
471
  instruction: string;
472
472
  /**
@@ -24,7 +24,7 @@ const Title = memo<TitleProps>(({ showTitle, time, avatar, titleAddon }) => {
24
24
  </Text>
25
25
  )}
26
26
  {showTitle ? titleAddon : undefined}
27
- {time && (
27
+ {!time ? null : (
28
28
  <Text
29
29
  aria-label="published-date"
30
30
  as={'time'}
@@ -91,7 +91,6 @@ const ChatList = memo<ChatListProps>(({ disableActionsBar, welcome, itemContent
91
91
  <MessageActionProvider withSingletonActionsBar={!disableActionsBar}>
92
92
  <VirtualizedList
93
93
  dataSource={displayMessageIds}
94
- // isGenerating={isGenerating}
95
94
  itemContent={itemContent ?? defaultItemContent}
96
95
  />
97
96
  </MessageActionProvider>