@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.
- package/CHANGELOG.md +25 -0
- package/Dockerfile +44 -52
- package/changelog/v2.json +9 -0
- package/locales/ar/chat.json +4 -0
- package/locales/ar/models.json +65 -0
- package/locales/bg-BG/chat.json +4 -0
- package/locales/bg-BG/models.json +10 -0
- package/locales/de-DE/chat.json +4 -0
- package/locales/de-DE/models.json +41 -0
- package/locales/en-US/chat.json +4 -0
- package/locales/es-ES/chat.json +4 -0
- package/locales/es-ES/models.json +50 -0
- package/locales/fa-IR/chat.json +4 -0
- package/locales/fa-IR/models.json +39 -0
- package/locales/fr-FR/chat.json +4 -0
- package/locales/fr-FR/models.json +9 -0
- package/locales/it-IT/chat.json +4 -0
- package/locales/it-IT/models.json +62 -0
- package/locales/ja-JP/chat.json +4 -0
- package/locales/ja-JP/models.json +40 -0
- package/locales/ko-KR/chat.json +4 -0
- package/locales/ko-KR/models.json +31 -0
- package/locales/nl-NL/chat.json +4 -0
- package/locales/nl-NL/models.json +52 -0
- package/locales/pl-PL/chat.json +4 -0
- package/locales/pl-PL/models.json +43 -0
- package/locales/pt-BR/chat.json +4 -0
- package/locales/pt-BR/models.json +92 -0
- package/locales/ru-RU/chat.json +4 -0
- package/locales/ru-RU/models.json +34 -0
- package/locales/tr-TR/chat.json +4 -0
- package/locales/tr-TR/models.json +55 -0
- package/locales/vi-VN/chat.json +4 -0
- package/locales/vi-VN/models.json +31 -0
- package/locales/zh-CN/chat.json +4 -0
- package/locales/zh-TW/chat.json +4 -0
- package/package.json +1 -1
- package/packages/agent-runtime/src/groupOrchestration/GroupOrchestrationSupervisor.ts +18 -1
- package/packages/agent-runtime/src/groupOrchestration/__tests__/GroupOrchestrationSupervisor.test.ts +76 -5
- package/packages/agent-runtime/src/groupOrchestration/types.ts +3 -3
- package/packages/builtin-tool-group-management/src/client/Intervention/ExecuteTask.tsx +11 -11
- package/packages/builtin-tool-group-management/src/client/Intervention/ExecuteTasks.tsx +78 -79
- package/packages/builtin-tool-group-management/src/client/Render/ExecuteTask/index.tsx +3 -3
- package/packages/builtin-tool-group-management/src/client/Render/ExecuteTasks/index.tsx +61 -63
- package/packages/builtin-tool-group-management/src/client/Streaming/ExecuteTask/index.tsx +3 -3
- package/packages/builtin-tool-group-management/src/executor.test.ts +7 -9
- package/packages/builtin-tool-group-management/src/executor.ts +3 -3
- package/packages/builtin-tool-group-management/src/manifest.ts +49 -50
- package/packages/builtin-tool-group-management/src/systemRole.ts +153 -5
- package/packages/builtin-tool-group-management/src/types.ts +3 -2
- package/packages/builtin-tool-gtd/src/systemRole.ts +4 -4
- package/packages/context-engine/src/processors/TasksFlatten.ts +7 -5
- package/packages/context-engine/src/processors/__tests__/TasksFlatten.test.ts +164 -0
- package/packages/conversation-flow/src/__tests__/fixtures/inputs/agentGroup/index.ts +4 -0
- package/packages/conversation-flow/src/__tests__/fixtures/inputs/agentGroup/supervisor-after-multi-tasks.json +91 -0
- package/packages/conversation-flow/src/__tests__/fixtures/inputs/agentGroup/supervisor-content-only.json +74 -0
- package/packages/conversation-flow/src/__tests__/parse.test.ts +37 -0
- package/packages/conversation-flow/src/transformation/FlatListBuilder.ts +70 -4
- package/packages/conversation-flow/src/transformation/__tests__/FlatListBuilder.test.ts +147 -0
- package/packages/types/src/message/ui/chat.ts +2 -0
- package/packages/types/src/tool/builtin.ts +5 -5
- package/src/features/Conversation/ChatItem/components/Title.tsx +1 -1
- package/src/features/Conversation/ChatList/index.tsx +0 -1
- package/src/features/Conversation/Messages/GroupTasks/TaskItem/ClientTaskItem.tsx +183 -0
- package/src/features/Conversation/Messages/GroupTasks/TaskItem/ServerTaskItem.tsx +94 -0
- package/src/features/Conversation/Messages/GroupTasks/TaskItem/TaskTitle.tsx +177 -0
- package/src/features/Conversation/Messages/GroupTasks/TaskItem/index.tsx +26 -0
- package/src/features/Conversation/Messages/GroupTasks/TaskItem/useClientTaskStats.ts +93 -0
- package/src/features/Conversation/Messages/GroupTasks/index.tsx +151 -0
- package/src/features/Conversation/Messages/Supervisor/index.tsx +7 -1
- package/src/features/Conversation/Messages/Task/ClientTaskDetail/index.tsx +72 -91
- package/src/features/Conversation/Messages/Task/TaskDetailPanel/StatusContent.tsx +46 -17
- package/src/features/Conversation/Messages/Tasks/TaskItem/ClientTaskItem.tsx +9 -24
- package/src/features/Conversation/Messages/Tasks/TaskItem/ServerTaskItem.tsx +18 -38
- package/src/features/Conversation/Messages/Tasks/shared/ErrorState.tsx +45 -2
- package/src/features/Conversation/Messages/Tasks/shared/InitializingState.tsx +16 -1
- package/src/features/Conversation/Messages/Tasks/shared/TaskContent.tsx +68 -0
- package/src/features/Conversation/Messages/Tasks/shared/TaskMessages.tsx +383 -0
- package/src/features/Conversation/Messages/Tasks/shared/index.ts +4 -0
- package/src/features/Conversation/Messages/Tasks/shared/useTaskPolling.ts +48 -0
- package/src/features/Conversation/Messages/index.tsx +5 -0
- package/src/locales/default/chat.ts +4 -0
- package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +4 -0
- package/src/server/modules/AgentRuntime/__tests__/RuntimeExecutors.test.ts +106 -1
- package/src/server/services/aiAgent/__tests__/execAgent.threadId.test.ts +2 -2
- package/src/server/utils/truncateToolResult.ts +1 -4
- package/src/store/chat/agents/GroupOrchestration/__tests__/batch-exec-async-tasks.test.ts +15 -15
- package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +22 -15
- package/src/store/chat/agents/__tests__/createAgentExecutors/exec-tasks.test.ts +21 -10
- package/src/store/chat/agents/createAgentExecutors.ts +2 -0
- package/src/store/chat/slices/aiAgent/actions/groupOrchestration.ts +10 -7
- package/src/features/Conversation/Messages/Task/ClientTaskDetail/CompletedState.tsx +0 -108
- package/src/features/Conversation/Messages/Task/ClientTaskDetail/InstructionAccordion.tsx +0 -63
- 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
|
-
//
|
|
102
|
-
const
|
|
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
|
-
|
|
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
|
|
469
|
+
* Detailed instruction for the agent to execute
|
|
470
470
|
*/
|
|
471
471
|
instruction: string;
|
|
472
472
|
/**
|
|
@@ -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>
|