@lobehub/lobehub 2.0.9 → 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 (108) 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/model-bank/src/aiModels/cerebras.ts +2 -22
  61. package/packages/model-bank/src/aiModels/google.ts +1 -44
  62. package/packages/model-bank/src/aiModels/nvidia.ts +12 -16
  63. package/packages/model-bank/src/aiModels/siliconcloud.ts +20 -0
  64. package/packages/model-bank/src/aiModels/volcengine.ts +69 -0
  65. package/packages/model-bank/src/aiModels/wenxin.ts +41 -38
  66. package/packages/model-bank/src/aiModels/zhipu.ts +58 -28
  67. package/packages/model-bank/src/types/aiModel.ts +29 -0
  68. package/packages/model-runtime/src/core/usageConverters/utils/computeChatCost.test.ts +2 -2
  69. package/packages/model-runtime/src/providers/google/createImage.test.ts +12 -12
  70. package/packages/model-runtime/src/providers/openrouter/index.test.ts +102 -0
  71. package/packages/model-runtime/src/providers/openrouter/index.ts +19 -7
  72. package/packages/model-runtime/src/providers/vercelaigateway/index.test.ts +47 -0
  73. package/packages/model-runtime/src/providers/vercelaigateway/index.ts +7 -1
  74. package/packages/types/src/message/ui/chat.ts +2 -0
  75. package/packages/types/src/tool/builtin.ts +5 -5
  76. package/src/features/Conversation/ChatItem/components/Title.tsx +1 -1
  77. package/src/features/Conversation/ChatList/index.tsx +0 -1
  78. package/src/features/Conversation/Messages/GroupTasks/TaskItem/ClientTaskItem.tsx +183 -0
  79. package/src/features/Conversation/Messages/GroupTasks/TaskItem/ServerTaskItem.tsx +94 -0
  80. package/src/features/Conversation/Messages/GroupTasks/TaskItem/TaskTitle.tsx +177 -0
  81. package/src/features/Conversation/Messages/GroupTasks/TaskItem/index.tsx +26 -0
  82. package/src/features/Conversation/Messages/GroupTasks/TaskItem/useClientTaskStats.ts +93 -0
  83. package/src/features/Conversation/Messages/GroupTasks/index.tsx +151 -0
  84. package/src/features/Conversation/Messages/Supervisor/index.tsx +7 -1
  85. package/src/features/Conversation/Messages/Task/ClientTaskDetail/index.tsx +72 -91
  86. package/src/features/Conversation/Messages/Task/TaskDetailPanel/StatusContent.tsx +46 -17
  87. package/src/features/Conversation/Messages/Tasks/TaskItem/ClientTaskItem.tsx +9 -24
  88. package/src/features/Conversation/Messages/Tasks/TaskItem/ServerTaskItem.tsx +18 -38
  89. package/src/features/Conversation/Messages/Tasks/shared/ErrorState.tsx +45 -2
  90. package/src/features/Conversation/Messages/Tasks/shared/InitializingState.tsx +16 -1
  91. package/src/features/Conversation/Messages/Tasks/shared/TaskContent.tsx +68 -0
  92. package/src/features/Conversation/Messages/Tasks/shared/TaskMessages.tsx +383 -0
  93. package/src/features/Conversation/Messages/Tasks/shared/index.ts +4 -0
  94. package/src/features/Conversation/Messages/Tasks/shared/useTaskPolling.ts +48 -0
  95. package/src/features/Conversation/Messages/index.tsx +5 -0
  96. package/src/locales/default/chat.ts +4 -0
  97. package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +4 -0
  98. package/src/server/modules/AgentRuntime/__tests__/RuntimeExecutors.test.ts +106 -1
  99. package/src/server/services/aiAgent/__tests__/execAgent.threadId.test.ts +2 -2
  100. package/src/server/utils/truncateToolResult.ts +1 -4
  101. package/src/store/chat/agents/GroupOrchestration/__tests__/batch-exec-async-tasks.test.ts +15 -15
  102. package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +22 -15
  103. package/src/store/chat/agents/__tests__/createAgentExecutors/exec-tasks.test.ts +21 -10
  104. package/src/store/chat/agents/createAgentExecutors.ts +2 -0
  105. package/src/store/chat/slices/aiAgent/actions/groupOrchestration.ts +10 -7
  106. package/src/features/Conversation/Messages/Task/ClientTaskDetail/CompletedState.tsx +0 -108
  107. package/src/features/Conversation/Messages/Task/ClientTaskDetail/InstructionAccordion.tsx +0 -63
  108. 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
  });
@@ -1,27 +1,6 @@
1
1
  import { AIChatModelCard } from '../types/aiModel';
2
2
 
3
3
  const cerebrasModels: AIChatModelCard[] = [
4
- {
5
- abilities: {
6
- functionCall: true,
7
- reasoning: true,
8
- structuredOutput: true,
9
- },
10
- contextWindowTokens: 131_072,
11
- description:
12
- 'Performs well on coding and reasoning tasks, supports streaming and tool calls, and fits agentic coding and complex reasoning.',
13
- displayName: 'GLM-4.6',
14
- enabled: true,
15
- id: 'zai-glm-4.6',
16
- maxOutput: 40_000,
17
- pricing: {
18
- units: [
19
- { name: 'textInput', rate: 2.25, strategy: 'fixed', unit: 'millionTokens' },
20
- { name: 'textOutput', rate: 2.75, strategy: 'fixed', unit: 'millionTokens' },
21
- ],
22
- },
23
- type: 'chat',
24
- },
25
4
  {
26
5
  abilities: {
27
6
  functionCall: true,
@@ -96,7 +75,8 @@ const cerebrasModels: AIChatModelCard[] = [
96
75
  functionCall: true,
97
76
  },
98
77
  contextWindowTokens: 32_768,
99
- description: 'Llama 3.1 8B: a small, low-latency Llama variant for lightweight online inference and chat.',
78
+ description:
79
+ 'Llama 3.1 8B: a small, low-latency Llama variant for lightweight online inference and chat.',
100
80
  displayName: 'Llama 3.1 8B',
101
81
  id: 'llama3.1-8b',
102
82
  pricing: {
@@ -1,4 +1,4 @@
1
- import { CHAT_MODEL_IMAGE_GENERATION_PARAMS, ModelParamsSchema } from '../standard-parameters';
1
+ import { ModelParamsSchema } from '../standard-parameters';
2
2
  import { AIChatModelCard, AIImageModelCard } from '../types';
3
3
 
4
4
  /**
@@ -485,32 +485,6 @@ const googleChatModels: AIChatModelCard[] = [
485
485
  },
486
486
  type: 'chat',
487
487
  },
488
- {
489
- abilities: {
490
- imageOutput: true,
491
- vision: true,
492
- },
493
- contextWindowTokens: 32_768 + 8192,
494
- description:
495
- 'Nano Banana is Google’s newest, fastest, and most efficient native multimodal model, enabling conversational image generation and editing.',
496
- displayName: 'Nano Banana (Preview)',
497
- id: 'gemini-2.5-flash-image-preview',
498
- maxOutput: 8192,
499
- pricing: {
500
- approximatePricePerImage: 0.039,
501
- units: [
502
- { name: 'textInput', rate: 0.3, strategy: 'fixed', unit: 'millionTokens' },
503
- { name: 'imageInput', rate: 0.3, strategy: 'fixed', unit: 'millionTokens' },
504
- { name: 'textOutput', rate: 2.5, strategy: 'fixed', unit: 'millionTokens' },
505
- { name: 'imageOutput', rate: 30, strategy: 'fixed', unit: 'millionTokens' },
506
- ],
507
- },
508
- releasedAt: '2025-08-26',
509
- settings: {
510
- extendParams: ['imageAspectRatio'],
511
- },
512
- type: 'chat',
513
- },
514
488
  {
515
489
  abilities: {
516
490
  functionCall: true,
@@ -967,23 +941,6 @@ const googleImageModels: AIImageModelCard[] = [
967
941
  ],
968
942
  },
969
943
  },
970
- {
971
- displayName: 'Nano Banana (Preview)',
972
- id: 'gemini-2.5-flash-image-preview:image',
973
- type: 'image',
974
- description:
975
- 'Nano Banana is Google’s newest, fastest, and most efficient native multimodal model, enabling conversational image generation and editing.',
976
- releasedAt: '2025-08-26',
977
- parameters: CHAT_MODEL_IMAGE_GENERATION_PARAMS,
978
- pricing: {
979
- approximatePricePerImage: 0.039,
980
- units: [
981
- { name: 'textInput', rate: 0.3, strategy: 'fixed', unit: 'millionTokens' },
982
- { name: 'textOutput', rate: 2.5, strategy: 'fixed', unit: 'millionTokens' },
983
- { name: 'imageOutput', rate: 30, strategy: 'fixed', unit: 'millionTokens' },
984
- ],
985
- },
986
- },
987
944
  {
988
945
  displayName: 'Imagen 4',
989
946
  id: 'imagen-4.0-generate-001',
@@ -79,7 +79,8 @@ const nvidiaChatModels: AIChatModelCard[] = [
79
79
  vision: true,
80
80
  },
81
81
  contextWindowTokens: 128_000,
82
- description: 'A frontier vision-language model that excels at high-quality reasoning from images.',
82
+ description:
83
+ 'A frontier vision-language model that excels at high-quality reasoning from images.',
83
84
  displayName: 'Llama 3.2 11B Vision Instruct',
84
85
  id: 'meta/llama-3.2-11b-vision-instruct',
85
86
  type: 'chat',
@@ -89,7 +90,8 @@ const nvidiaChatModels: AIChatModelCard[] = [
89
90
  vision: true,
90
91
  },
91
92
  contextWindowTokens: 128_000,
92
- description: 'A frontier vision-language model that excels at high-quality reasoning from images.',
93
+ description:
94
+ 'A frontier vision-language model that excels at high-quality reasoning from images.',
93
95
  displayName: 'Llama 3.2 90B Vision Instruct',
94
96
  id: 'meta/llama-3.2-90b-vision-instruct',
95
97
  type: 'chat',
@@ -151,41 +153,35 @@ const nvidiaChatModels: AIChatModelCard[] = [
151
153
  },
152
154
  {
153
155
  contextWindowTokens: 8192,
154
- description: 'A frontier text generation model strong in understanding, transformation, and code generation.',
156
+ description:
157
+ 'A frontier text generation model strong in understanding, transformation, and code generation.',
155
158
  displayName: 'Gemma 2 9B Instruct',
156
159
  id: 'google/gemma-2-9b-it',
157
160
  type: 'chat',
158
161
  },
159
162
  {
160
163
  contextWindowTokens: 8192,
161
- description: 'A frontier text generation model strong in understanding, transformation, and code generation.',
164
+ description:
165
+ 'A frontier text generation model strong in understanding, transformation, and code generation.',
162
166
  displayName: 'Gemma 2 27B Instruct',
163
167
  id: 'google/gemma-2-27b-it',
164
168
  type: 'chat',
165
169
  },
166
- {
167
- abilities: {
168
- reasoning: true,
169
- },
170
- contextWindowTokens: 128_000,
171
- description: 'A state-of-the-art efficient LLM strong in reasoning, math, and programming.',
172
- displayName: 'DeepSeek R1',
173
- id: 'deepseek-ai/deepseek-r1',
174
- type: 'chat',
175
- },
176
170
  {
177
171
  abilities: {
178
172
  functionCall: true,
179
173
  },
180
174
  contextWindowTokens: 32_768,
181
- description: 'A bilingual LLM for Chinese and English across language, coding, math, and reasoning.',
175
+ description:
176
+ 'A bilingual LLM for Chinese and English across language, coding, math, and reasoning.',
182
177
  displayName: 'Qwen2.5 7B Instruct',
183
178
  id: 'qwen/qwen2.5-7b-instruct',
184
179
  type: 'chat',
185
180
  },
186
181
  {
187
182
  contextWindowTokens: 32_768,
188
- description: 'A strong mid-sized code model with 32K context, excelling at multilingual programming.',
183
+ description:
184
+ 'A strong mid-sized code model with 32K context, excelling at multilingual programming.',
189
185
  displayName: 'Qwen2.5 Coder 7B Instruct',
190
186
  id: 'qwen/qwen2.5-coder-7b-instruct',
191
187
  type: 'chat',
@@ -2,6 +2,26 @@ import { AIChatModelCard, AIImageModelCard } from '../types/aiModel';
2
2
 
3
3
  // https://siliconflow.cn/zh-cn/models
4
4
  const siliconcloudChatModels: AIChatModelCard[] = [
5
+ {
6
+ abilities: {
7
+ functionCall: true,
8
+ reasoning: true,
9
+ },
10
+ contextWindowTokens: 192_000,
11
+ description:
12
+ 'MiniMax-M2.1 is an open-source large language model optimized for agent capabilities, excelling in programming, tool usage, instruction following, and long-term planning. The model supports multilingual software development and complex multi-step workflow execution, achieving a score of 74.0 on SWE-bench Verified and surpassing Claude Sonnet 4.5 in multilingual scenarios.',
13
+ displayName: 'MiniMax-M2.1 (Pro)',
14
+ id: 'Pro/MiniMaxAI/MiniMax-M2.1',
15
+ pricing: {
16
+ currency: 'CNY',
17
+ units: [
18
+ { name: 'textInput', rate: 2.1, strategy: 'fixed', unit: 'millionTokens' },
19
+ { name: 'textOutput', rate: 8.4, strategy: 'fixed', unit: 'millionTokens' },
20
+ ],
21
+ },
22
+ releasedAt: '2025-12-23',
23
+ type: 'chat',
24
+ },
5
25
  {
6
26
  abilities: {
7
27
  functionCall: true,