@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.
- package/CHANGELOG.md +50 -0
- package/Dockerfile +44 -52
- package/changelog/v2.json +18 -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/model-bank/src/aiModels/cerebras.ts +2 -22
- package/packages/model-bank/src/aiModels/google.ts +1 -44
- package/packages/model-bank/src/aiModels/nvidia.ts +12 -16
- package/packages/model-bank/src/aiModels/siliconcloud.ts +20 -0
- package/packages/model-bank/src/aiModels/volcengine.ts +69 -0
- package/packages/model-bank/src/aiModels/wenxin.ts +41 -38
- package/packages/model-bank/src/aiModels/zhipu.ts +58 -28
- package/packages/model-bank/src/types/aiModel.ts +29 -0
- package/packages/model-runtime/src/core/usageConverters/utils/computeChatCost.test.ts +2 -2
- package/packages/model-runtime/src/providers/google/createImage.test.ts +12 -12
- package/packages/model-runtime/src/providers/openrouter/index.test.ts +102 -0
- package/packages/model-runtime/src/providers/openrouter/index.ts +19 -7
- package/packages/model-runtime/src/providers/vercelaigateway/index.test.ts +47 -0
- package/packages/model-runtime/src/providers/vercelaigateway/index.ts +7 -1
- 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
|
@@ -139,8 +139,8 @@ describe('createGroupOrchestrationExecutors', () => {
|
|
|
139
139
|
{
|
|
140
140
|
payload: {
|
|
141
141
|
tasks: [
|
|
142
|
-
{ agentId: TEST_IDS.AGENT_1_ID,
|
|
143
|
-
{ agentId: TEST_IDS.AGENT_2_ID,
|
|
142
|
+
{ agentId: TEST_IDS.AGENT_1_ID, instruction: 'Task 1', title: 'Task 1 Title' },
|
|
143
|
+
{ agentId: TEST_IDS.AGENT_2_ID, instruction: 'Task 2', title: 'Task 2 Title' },
|
|
144
144
|
],
|
|
145
145
|
toolMessageId: TEST_IDS.TOOL_MESSAGE_ID,
|
|
146
146
|
},
|
|
@@ -187,8 +187,8 @@ describe('createGroupOrchestrationExecutors', () => {
|
|
|
187
187
|
{
|
|
188
188
|
payload: {
|
|
189
189
|
tasks: [
|
|
190
|
-
{ agentId: TEST_IDS.AGENT_1_ID,
|
|
191
|
-
{ agentId: TEST_IDS.AGENT_2_ID,
|
|
190
|
+
{ agentId: TEST_IDS.AGENT_1_ID, instruction: 'Task 1', title: 'Task 1 Title' },
|
|
191
|
+
{ agentId: TEST_IDS.AGENT_2_ID, instruction: 'Task 2', title: 'Task 2 Title' },
|
|
192
192
|
],
|
|
193
193
|
toolMessageId: TEST_IDS.TOOL_MESSAGE_ID,
|
|
194
194
|
},
|
|
@@ -263,8 +263,8 @@ describe('createGroupOrchestrationExecutors', () => {
|
|
|
263
263
|
{
|
|
264
264
|
payload: {
|
|
265
265
|
tasks: [
|
|
266
|
-
{ agentId: TEST_IDS.AGENT_1_ID,
|
|
267
|
-
{ agentId: TEST_IDS.AGENT_2_ID,
|
|
266
|
+
{ agentId: TEST_IDS.AGENT_1_ID, instruction: 'Task 1', title: 'Task 1 Title' },
|
|
267
|
+
{ agentId: TEST_IDS.AGENT_2_ID, instruction: 'Task 2', title: 'Task 2 Title' },
|
|
268
268
|
],
|
|
269
269
|
toolMessageId: TEST_IDS.TOOL_MESSAGE_ID,
|
|
270
270
|
},
|
|
@@ -327,8 +327,8 @@ describe('createGroupOrchestrationExecutors', () => {
|
|
|
327
327
|
{
|
|
328
328
|
payload: {
|
|
329
329
|
tasks: [
|
|
330
|
-
{ agentId: TEST_IDS.AGENT_1_ID,
|
|
331
|
-
{ agentId: TEST_IDS.AGENT_2_ID,
|
|
330
|
+
{ agentId: TEST_IDS.AGENT_1_ID, instruction: 'Task 1', title: 'Task 1 Title' },
|
|
331
|
+
{ agentId: TEST_IDS.AGENT_2_ID, instruction: 'Task 2', title: 'Task 2 Title' },
|
|
332
332
|
],
|
|
333
333
|
toolMessageId: TEST_IDS.TOOL_MESSAGE_ID,
|
|
334
334
|
},
|
|
@@ -386,8 +386,8 @@ describe('createGroupOrchestrationExecutors', () => {
|
|
|
386
386
|
{
|
|
387
387
|
payload: {
|
|
388
388
|
tasks: [
|
|
389
|
-
{ agentId: TEST_IDS.AGENT_1_ID,
|
|
390
|
-
{ agentId: TEST_IDS.AGENT_2_ID,
|
|
389
|
+
{ agentId: TEST_IDS.AGENT_1_ID, instruction: 'Task 1', title: 'Task 1 Title' },
|
|
390
|
+
{ agentId: TEST_IDS.AGENT_2_ID, instruction: 'Task 2', title: 'Task 2 Title' },
|
|
391
391
|
],
|
|
392
392
|
toolMessageId: TEST_IDS.TOOL_MESSAGE_ID,
|
|
393
393
|
},
|
|
@@ -445,8 +445,8 @@ describe('createGroupOrchestrationExecutors', () => {
|
|
|
445
445
|
{
|
|
446
446
|
payload: {
|
|
447
447
|
tasks: [
|
|
448
|
-
{ agentId: TEST_IDS.AGENT_1_ID,
|
|
449
|
-
{ agentId: TEST_IDS.AGENT_2_ID,
|
|
448
|
+
{ agentId: TEST_IDS.AGENT_1_ID, instruction: 'Task 1', title: 'Task 1 Title' },
|
|
449
|
+
{ agentId: TEST_IDS.AGENT_2_ID, instruction: 'Task 2', title: 'Task 2 Title' },
|
|
450
450
|
],
|
|
451
451
|
toolMessageId: TEST_IDS.TOOL_MESSAGE_ID,
|
|
452
452
|
},
|
|
@@ -498,7 +498,7 @@ describe('createGroupOrchestrationExecutors', () => {
|
|
|
498
498
|
const result = await batchExecTasksExecutor(
|
|
499
499
|
{
|
|
500
500
|
payload: {
|
|
501
|
-
tasks: [{ agentId: TEST_IDS.AGENT_1_ID,
|
|
501
|
+
tasks: [{ agentId: TEST_IDS.AGENT_1_ID, instruction: 'Task 1', title: 'Task 1 Title' }],
|
|
502
502
|
toolMessageId: TEST_IDS.TOOL_MESSAGE_ID,
|
|
503
503
|
},
|
|
504
504
|
type: 'batch_exec_async_tasks',
|
|
@@ -546,7 +546,7 @@ describe('createGroupOrchestrationExecutors', () => {
|
|
|
546
546
|
const result = await batchExecTasksExecutor(
|
|
547
547
|
{
|
|
548
548
|
payload: {
|
|
549
|
-
tasks: [{ agentId: TEST_IDS.AGENT_1_ID,
|
|
549
|
+
tasks: [{ agentId: TEST_IDS.AGENT_1_ID, instruction: 'Task 1', title: 'Task 1 Title' }],
|
|
550
550
|
toolMessageId: TEST_IDS.TOOL_MESSAGE_ID,
|
|
551
551
|
},
|
|
552
552
|
type: 'batch_exec_async_tasks',
|
|
@@ -604,7 +604,7 @@ describe('createGroupOrchestrationExecutors', () => {
|
|
|
604
604
|
await batchExecTasksExecutor(
|
|
605
605
|
{
|
|
606
606
|
payload: {
|
|
607
|
-
tasks: [{ agentId: TEST_IDS.AGENT_1_ID,
|
|
607
|
+
tasks: [{ agentId: TEST_IDS.AGENT_1_ID, instruction: 'Task 1', title: 'Task 1 Title' }],
|
|
608
608
|
toolMessageId: TEST_IDS.TOOL_MESSAGE_ID,
|
|
609
609
|
},
|
|
610
610
|
type: 'batch_exec_async_tasks',
|
|
@@ -369,14 +369,17 @@ export const createGroupOrchestrationExecutors = (
|
|
|
369
369
|
*
|
|
370
370
|
* Returns: task_completed result
|
|
371
371
|
*/
|
|
372
|
-
exec_async_task: async (
|
|
373
|
-
|
|
374
|
-
|
|
372
|
+
exec_async_task: async (
|
|
373
|
+
supervisorInstruction,
|
|
374
|
+
state,
|
|
375
|
+
): Promise<GroupOrchestrationExecutorOutput> => {
|
|
376
|
+
const { agentId, instruction, timeout, title, toolMessageId } = (
|
|
377
|
+
supervisorInstruction as SupervisorInstructionExecAsyncTask
|
|
375
378
|
).payload;
|
|
376
379
|
|
|
377
380
|
const sessionLogId = `${state.operationId}:exec_async_task`;
|
|
378
381
|
log(
|
|
379
|
-
`[${sessionLogId}] Executing async task for agent: ${agentId},
|
|
382
|
+
`[${sessionLogId}] Executing async task for agent: ${agentId}, instruction: ${instruction}, timeout: ${timeout}`,
|
|
380
383
|
);
|
|
381
384
|
|
|
382
385
|
const { groupId, topicId } = messageContext;
|
|
@@ -400,7 +403,7 @@ export const createGroupOrchestrationExecutors = (
|
|
|
400
403
|
agentId,
|
|
401
404
|
content: '',
|
|
402
405
|
groupId,
|
|
403
|
-
metadata: { instruction
|
|
406
|
+
metadata: { instruction, taskTitle: title },
|
|
404
407
|
parentId: toolMessageId,
|
|
405
408
|
role: 'task',
|
|
406
409
|
topicId,
|
|
@@ -427,7 +430,7 @@ export const createGroupOrchestrationExecutors = (
|
|
|
427
430
|
const createResult = await aiAgentService.execSubAgentTask({
|
|
428
431
|
agentId,
|
|
429
432
|
groupId,
|
|
430
|
-
instruction
|
|
433
|
+
instruction,
|
|
431
434
|
parentMessageId: taskMessageId,
|
|
432
435
|
title,
|
|
433
436
|
topicId,
|
|
@@ -600,9 +603,12 @@ export const createGroupOrchestrationExecutors = (
|
|
|
600
603
|
*
|
|
601
604
|
* Returns: task_completed result
|
|
602
605
|
*/
|
|
603
|
-
exec_client_async_task: async (
|
|
604
|
-
|
|
605
|
-
|
|
606
|
+
exec_client_async_task: async (
|
|
607
|
+
supervisorInstruction,
|
|
608
|
+
state,
|
|
609
|
+
): Promise<GroupOrchestrationExecutorOutput> => {
|
|
610
|
+
const { agentId, instruction, title, toolMessageId } = (
|
|
611
|
+
supervisorInstruction as SupervisorInstructionExecClientAsyncTask
|
|
606
612
|
).payload;
|
|
607
613
|
|
|
608
614
|
const sessionLogId = `${state.operationId}:exec_client_async_task`;
|
|
@@ -629,7 +635,7 @@ export const createGroupOrchestrationExecutors = (
|
|
|
629
635
|
agentId,
|
|
630
636
|
content: '',
|
|
631
637
|
groupId,
|
|
632
|
-
metadata: { instruction
|
|
638
|
+
metadata: { instruction, taskTitle: title },
|
|
633
639
|
parentId: toolMessageId,
|
|
634
640
|
role: 'task',
|
|
635
641
|
topicId,
|
|
@@ -656,7 +662,7 @@ export const createGroupOrchestrationExecutors = (
|
|
|
656
662
|
// Use Group-specific API that handles different agentIds in thread context
|
|
657
663
|
const threadResult = await aiAgentService.createClientGroupAgentTaskThread({
|
|
658
664
|
groupId: groupId!,
|
|
659
|
-
instruction
|
|
665
|
+
instruction,
|
|
660
666
|
parentMessageId: taskMessageId,
|
|
661
667
|
subAgentId: agentId,
|
|
662
668
|
title,
|
|
@@ -861,9 +867,9 @@ export const createGroupOrchestrationExecutors = (
|
|
|
861
867
|
interface TaskTracker {
|
|
862
868
|
agentId: string;
|
|
863
869
|
error?: string;
|
|
870
|
+
instruction: string;
|
|
864
871
|
result?: string;
|
|
865
872
|
status: 'pending' | 'running' | 'completed' | 'failed';
|
|
866
|
-
task: string;
|
|
867
873
|
taskMessageId?: string;
|
|
868
874
|
threadId?: string;
|
|
869
875
|
timeout: number;
|
|
@@ -873,7 +879,7 @@ export const createGroupOrchestrationExecutors = (
|
|
|
873
879
|
const taskTrackers: TaskTracker[] = tasks.map((t) => ({
|
|
874
880
|
agentId: t.agentId,
|
|
875
881
|
status: 'pending',
|
|
876
|
-
|
|
882
|
+
instruction: t.instruction,
|
|
877
883
|
timeout: t.timeout || 1_800_000, // Default 30 minutes
|
|
878
884
|
title: t.title,
|
|
879
885
|
}));
|
|
@@ -887,8 +893,9 @@ export const createGroupOrchestrationExecutors = (
|
|
|
887
893
|
{
|
|
888
894
|
agentId: tracker.agentId,
|
|
889
895
|
content: '',
|
|
896
|
+
createdAt: Date.now() + index,
|
|
890
897
|
groupId,
|
|
891
|
-
metadata: { instruction: tracker.
|
|
898
|
+
metadata: { instruction: tracker.instruction, taskTitle: tracker.title },
|
|
892
899
|
parentId: toolMessageId,
|
|
893
900
|
role: 'task',
|
|
894
901
|
topicId,
|
|
@@ -922,7 +929,7 @@ export const createGroupOrchestrationExecutors = (
|
|
|
922
929
|
const createResult = await aiAgentService.execSubAgentTask({
|
|
923
930
|
agentId: tracker.agentId,
|
|
924
931
|
groupId,
|
|
925
|
-
instruction: tracker.
|
|
932
|
+
instruction: tracker.instruction,
|
|
926
933
|
parentMessageId: tracker.taskMessageId,
|
|
927
934
|
title: tracker.title,
|
|
928
935
|
topicId,
|
|
@@ -66,7 +66,8 @@ describe('exec_tasks executor', () => {
|
|
|
66
66
|
expect(result.nextContext).toBeDefined();
|
|
67
67
|
expect((result.nextContext as AgentRuntimeContext).phase).toBe('tasks_batch_result');
|
|
68
68
|
|
|
69
|
-
const payload = (result.nextContext as AgentRuntimeContext)
|
|
69
|
+
const payload = (result.nextContext as AgentRuntimeContext)
|
|
70
|
+
.payload as TasksBatchResultPayload;
|
|
70
71
|
expect(payload.results).toHaveLength(1);
|
|
71
72
|
expect(payload.results[0].success).toBe(true);
|
|
72
73
|
expect(payload.results[0].threadId).toBe('thread_1');
|
|
@@ -131,7 +132,8 @@ describe('exec_tasks executor', () => {
|
|
|
131
132
|
|
|
132
133
|
// Then
|
|
133
134
|
expect(result.nextContext).toBeDefined();
|
|
134
|
-
const payload = (result.nextContext as AgentRuntimeContext)
|
|
135
|
+
const payload = (result.nextContext as AgentRuntimeContext)
|
|
136
|
+
.payload as TasksBatchResultPayload;
|
|
135
137
|
expect(payload.results).toHaveLength(3);
|
|
136
138
|
expect(payload.results.every((r) => r.success)).toBe(true);
|
|
137
139
|
});
|
|
@@ -170,7 +172,8 @@ describe('exec_tasks executor', () => {
|
|
|
170
172
|
|
|
171
173
|
// Then
|
|
172
174
|
expect(result.nextContext).toBeDefined();
|
|
173
|
-
const payload = (result.nextContext as AgentRuntimeContext)
|
|
175
|
+
const payload = (result.nextContext as AgentRuntimeContext)
|
|
176
|
+
.payload as TasksBatchResultPayload;
|
|
174
177
|
expect(payload.results).toHaveLength(1);
|
|
175
178
|
expect(payload.results[0].success).toBe(false);
|
|
176
179
|
expect(payload.results[0].error).toBe('No valid context available');
|
|
@@ -196,7 +199,8 @@ describe('exec_tasks executor', () => {
|
|
|
196
199
|
});
|
|
197
200
|
|
|
198
201
|
// Then
|
|
199
|
-
const payload = (result.nextContext as AgentRuntimeContext)
|
|
202
|
+
const payload = (result.nextContext as AgentRuntimeContext)
|
|
203
|
+
.payload as TasksBatchResultPayload;
|
|
200
204
|
expect(payload.results[0].success).toBe(false);
|
|
201
205
|
expect(payload.results[0].error).toBe('Failed to create task message');
|
|
202
206
|
});
|
|
@@ -228,7 +232,8 @@ describe('exec_tasks executor', () => {
|
|
|
228
232
|
});
|
|
229
233
|
|
|
230
234
|
// Then
|
|
231
|
-
const payload = (result.nextContext as AgentRuntimeContext)
|
|
235
|
+
const payload = (result.nextContext as AgentRuntimeContext)
|
|
236
|
+
.payload as TasksBatchResultPayload;
|
|
232
237
|
expect(payload.results[0].success).toBe(false);
|
|
233
238
|
expect(payload.results[0].error).toBe('API error');
|
|
234
239
|
expect(mockStore.optimisticUpdateMessageContent).toHaveBeenCalledWith(
|
|
@@ -270,7 +275,8 @@ describe('exec_tasks executor', () => {
|
|
|
270
275
|
});
|
|
271
276
|
|
|
272
277
|
// Then
|
|
273
|
-
const payload = (result.nextContext as AgentRuntimeContext)
|
|
278
|
+
const payload = (result.nextContext as AgentRuntimeContext)
|
|
279
|
+
.payload as TasksBatchResultPayload;
|
|
274
280
|
expect(payload.results[0].success).toBe(false);
|
|
275
281
|
expect(payload.results[0].error).toBe('Execution error');
|
|
276
282
|
});
|
|
@@ -318,7 +324,8 @@ describe('exec_tasks executor', () => {
|
|
|
318
324
|
},
|
|
319
325
|
{ operationId: 'test-op' },
|
|
320
326
|
);
|
|
321
|
-
const payload = (result.nextContext as AgentRuntimeContext)
|
|
327
|
+
const payload = (result.nextContext as AgentRuntimeContext)
|
|
328
|
+
.payload as TasksBatchResultPayload;
|
|
322
329
|
expect(payload.results[0].success).toBe(true);
|
|
323
330
|
});
|
|
324
331
|
|
|
@@ -353,7 +360,8 @@ describe('exec_tasks executor', () => {
|
|
|
353
360
|
});
|
|
354
361
|
|
|
355
362
|
// Then
|
|
356
|
-
const payload = (result.nextContext as AgentRuntimeContext)
|
|
363
|
+
const payload = (result.nextContext as AgentRuntimeContext)
|
|
364
|
+
.payload as TasksBatchResultPayload;
|
|
357
365
|
expect(payload.results[0].success).toBe(false);
|
|
358
366
|
expect(payload.results[0].error).toBe('Task was cancelled');
|
|
359
367
|
expect(mockStore.optimisticUpdateMessageContent).toHaveBeenCalledWith(
|
|
@@ -402,7 +410,8 @@ describe('exec_tasks executor', () => {
|
|
|
402
410
|
});
|
|
403
411
|
|
|
404
412
|
// Then
|
|
405
|
-
const payload = (result.nextContext as AgentRuntimeContext)
|
|
413
|
+
const payload = (result.nextContext as AgentRuntimeContext)
|
|
414
|
+
.payload as TasksBatchResultPayload;
|
|
406
415
|
expect(payload.results[0].success).toBe(false);
|
|
407
416
|
expect(payload.results[0].error).toBe('Operation cancelled');
|
|
408
417
|
// getSubAgentTaskStatus should not be called since operation was cancelled before poll
|
|
@@ -532,6 +541,7 @@ describe('exec_tasks executor', () => {
|
|
|
532
541
|
{
|
|
533
542
|
agentId: 'agent_1',
|
|
534
543
|
content: '',
|
|
544
|
+
createdAt: expect.any(Number),
|
|
535
545
|
metadata: { instruction: 'Do something important' },
|
|
536
546
|
parentId: 'msg_parent',
|
|
537
547
|
role: 'task',
|
|
@@ -588,7 +598,8 @@ describe('exec_tasks executor', () => {
|
|
|
588
598
|
});
|
|
589
599
|
|
|
590
600
|
// Then
|
|
591
|
-
const payload = (result.nextContext as AgentRuntimeContext)
|
|
601
|
+
const payload = (result.nextContext as AgentRuntimeContext)
|
|
602
|
+
.payload as TasksBatchResultPayload;
|
|
592
603
|
expect(payload.results).toHaveLength(2);
|
|
593
604
|
expect(payload.results[0].success).toBe(true);
|
|
594
605
|
expect(payload.results[1].success).toBe(false);
|
|
@@ -1349,6 +1349,7 @@ export const createAgentExecutors = (context: {
|
|
|
1349
1349
|
{
|
|
1350
1350
|
agentId,
|
|
1351
1351
|
content: '',
|
|
1352
|
+
createdAt: Date.now() + taskIndex,
|
|
1352
1353
|
metadata: { instruction: task.instruction },
|
|
1353
1354
|
parentId: parentMessageId,
|
|
1354
1355
|
role: 'task',
|
|
@@ -2035,6 +2036,7 @@ export const createAgentExecutors = (context: {
|
|
|
2035
2036
|
{
|
|
2036
2037
|
agentId,
|
|
2037
2038
|
content: '',
|
|
2039
|
+
createdAt: Date.now() + taskIndex,
|
|
2038
2040
|
metadata: { instruction: task.instruction, taskTitle: task.description },
|
|
2039
2041
|
parentId: parentMessageId,
|
|
2040
2042
|
role: 'task',
|
|
@@ -216,17 +216,17 @@ export const groupOrchestrationSlice: StateCreator<
|
|
|
216
216
|
const {
|
|
217
217
|
supervisorAgentId,
|
|
218
218
|
agentId,
|
|
219
|
-
|
|
219
|
+
instruction,
|
|
220
220
|
timeout,
|
|
221
221
|
toolMessageId,
|
|
222
222
|
skipCallSupervisor,
|
|
223
223
|
runInClient,
|
|
224
224
|
} = params;
|
|
225
225
|
log(
|
|
226
|
-
'[triggerExecuteTask] Starting orchestration with execute_task: supervisorAgentId=%s, agentId=%s,
|
|
226
|
+
'[triggerExecuteTask] Starting orchestration with execute_task: supervisorAgentId=%s, agentId=%s, instruction=%s, timeout=%s, toolMessageId=%s, skipCallSupervisor=%s, runInClient=%s',
|
|
227
227
|
supervisorAgentId,
|
|
228
228
|
agentId,
|
|
229
|
-
|
|
229
|
+
instruction,
|
|
230
230
|
timeout,
|
|
231
231
|
toolMessageId,
|
|
232
232
|
skipCallSupervisor,
|
|
@@ -248,7 +248,7 @@ export const groupOrchestrationSlice: StateCreator<
|
|
|
248
248
|
type: 'supervisor_decided',
|
|
249
249
|
payload: {
|
|
250
250
|
decision: 'execute_task',
|
|
251
|
-
params: { agentId,
|
|
251
|
+
params: { agentId, instruction, runInClient, timeout, toolMessageId },
|
|
252
252
|
skipCallSupervisor: skipCallSupervisor ?? false,
|
|
253
253
|
},
|
|
254
254
|
},
|
|
@@ -446,12 +446,15 @@ export const groupOrchestrationSlice: StateCreator<
|
|
|
446
446
|
revalidateOnReconnect: false,
|
|
447
447
|
refreshInterval: POLLING_INTERVAL,
|
|
448
448
|
onSuccess: (data) => {
|
|
449
|
-
if (data
|
|
450
|
-
// Update taskDetail
|
|
449
|
+
if (data && messageId) {
|
|
450
|
+
// Update taskDetail and tasks (intermediate messages)
|
|
451
451
|
get().internal_dispatchMessage({
|
|
452
452
|
id: messageId,
|
|
453
453
|
type: 'updateMessage',
|
|
454
|
-
value: {
|
|
454
|
+
value: {
|
|
455
|
+
taskDetail: data.taskDetail,
|
|
456
|
+
tasks: data.messages,
|
|
457
|
+
},
|
|
455
458
|
});
|
|
456
459
|
|
|
457
460
|
// Update content when task is completed or failed
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { type AssistantContentBlock } from '@lobechat/types';
|
|
4
|
-
import { Accordion, AccordionItem, Block, Flexbox, Icon, Text } from '@lobehub/ui';
|
|
5
|
-
import { cssVar } from 'antd-style';
|
|
6
|
-
import { Workflow } from 'lucide-react';
|
|
7
|
-
import { memo, useMemo } from 'react';
|
|
8
|
-
import { useTranslation } from 'react-i18next';
|
|
9
|
-
|
|
10
|
-
import ContentBlock from '../../AssistantGroup/components/ContentBlock';
|
|
11
|
-
import { formatDuration } from '../../Tasks/shared/utils';
|
|
12
|
-
import Usage from '../../components/Extras/Usage';
|
|
13
|
-
|
|
14
|
-
interface CompletedStateProps {
|
|
15
|
-
assistantId: string;
|
|
16
|
-
blocks: AssistantContentBlock[];
|
|
17
|
-
duration?: number;
|
|
18
|
-
model?: string;
|
|
19
|
-
provider?: string;
|
|
20
|
-
totalCost?: number;
|
|
21
|
-
totalTokens?: number;
|
|
22
|
-
totalToolCalls?: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const CompletedState = memo<CompletedStateProps>(
|
|
26
|
-
({ blocks, assistantId, duration, totalToolCalls, model, provider, totalTokens, totalCost }) => {
|
|
27
|
-
const { t } = useTranslation('chat');
|
|
28
|
-
|
|
29
|
-
// Split blocks: intermediate steps (all but last) and final result (last)
|
|
30
|
-
const { intermediateBlocks, finalBlock } = useMemo(() => {
|
|
31
|
-
if (blocks.length === 0) return { finalBlock: null, intermediateBlocks: [] };
|
|
32
|
-
if (blocks.length === 1) return { finalBlock: blocks[0], intermediateBlocks: [] };
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
finalBlock: blocks.at(-1)!,
|
|
36
|
-
intermediateBlocks: blocks.slice(0, -1),
|
|
37
|
-
};
|
|
38
|
-
}, [blocks]);
|
|
39
|
-
|
|
40
|
-
if (!finalBlock) return null;
|
|
41
|
-
|
|
42
|
-
const title = (
|
|
43
|
-
<Flexbox align="center" gap={8} horizontal>
|
|
44
|
-
<Block
|
|
45
|
-
align="center"
|
|
46
|
-
flex="none"
|
|
47
|
-
gap={4}
|
|
48
|
-
height={24}
|
|
49
|
-
horizontal
|
|
50
|
-
justify="center"
|
|
51
|
-
style={{ fontSize: 12 }}
|
|
52
|
-
variant="outlined"
|
|
53
|
-
width={24}
|
|
54
|
-
>
|
|
55
|
-
<Icon color={cssVar.colorTextSecondary} icon={Workflow} />
|
|
56
|
-
</Block>
|
|
57
|
-
<Flexbox align="center" gap={4} horizontal>
|
|
58
|
-
<Text as="span" type="secondary" weight={500}>
|
|
59
|
-
{totalToolCalls}
|
|
60
|
-
</Text>
|
|
61
|
-
<Text as="span" type="secondary">
|
|
62
|
-
{t('task.metrics.toolCallsShort')}
|
|
63
|
-
</Text>
|
|
64
|
-
{/* Duration display */}
|
|
65
|
-
{duration && (
|
|
66
|
-
<Text as="span" type="secondary">
|
|
67
|
-
{t('task.metrics.duration', { duration: formatDuration(duration) })}
|
|
68
|
-
</Text>
|
|
69
|
-
)}
|
|
70
|
-
</Flexbox>
|
|
71
|
-
</Flexbox>
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
return (
|
|
75
|
-
<Flexbox gap={8}>
|
|
76
|
-
{/* Intermediate steps - collapsed by default */}
|
|
77
|
-
{intermediateBlocks.length > 0 && (
|
|
78
|
-
<Accordion defaultExpandedKeys={[]} gap={8}>
|
|
79
|
-
<AccordionItem itemKey="intermediate" paddingBlock={4} paddingInline={4} title={title}>
|
|
80
|
-
<Flexbox gap={8} paddingInline={4} style={{ marginTop: 8 }}>
|
|
81
|
-
{intermediateBlocks.map((block) => (
|
|
82
|
-
<ContentBlock
|
|
83
|
-
{...block}
|
|
84
|
-
assistantId={assistantId}
|
|
85
|
-
disableEditing
|
|
86
|
-
key={block.id}
|
|
87
|
-
/>
|
|
88
|
-
))}
|
|
89
|
-
</Flexbox>
|
|
90
|
-
</AccordionItem>
|
|
91
|
-
</Accordion>
|
|
92
|
-
)}
|
|
93
|
-
|
|
94
|
-
{/* Final result - always visible */}
|
|
95
|
-
<ContentBlock {...finalBlock} assistantId={assistantId} disableEditing />
|
|
96
|
-
|
|
97
|
-
{/* Usage display */}
|
|
98
|
-
{model && provider && (
|
|
99
|
-
<Usage model={model} provider={provider} usage={{ cost: totalCost, totalTokens }} />
|
|
100
|
-
)}
|
|
101
|
-
</Flexbox>
|
|
102
|
-
);
|
|
103
|
-
},
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
CompletedState.displayName = 'ClientCompletedState';
|
|
107
|
-
|
|
108
|
-
export default CompletedState;
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { Accordion, AccordionItem, Block, Flexbox, Icon, Markdown, Text } from '@lobehub/ui';
|
|
2
|
-
import { cssVar } from 'antd-style';
|
|
3
|
-
import { ScrollText } from 'lucide-react';
|
|
4
|
-
import { memo, useEffect, useState } from 'react';
|
|
5
|
-
import { useTranslation } from 'react-i18next';
|
|
6
|
-
|
|
7
|
-
interface InstructionAccordionProps {
|
|
8
|
-
childrenCount: number;
|
|
9
|
-
instruction: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const InstructionAccordion = memo<InstructionAccordionProps>(({ instruction, childrenCount }) => {
|
|
13
|
-
const { t } = useTranslation('chat');
|
|
14
|
-
|
|
15
|
-
// Auto-collapse instruction when children count exceeds threshold
|
|
16
|
-
const [expandedKeys, setExpandedKeys] = useState<string[]>(['instruction']);
|
|
17
|
-
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
if (childrenCount > 1) {
|
|
20
|
-
setExpandedKeys([]);
|
|
21
|
-
}
|
|
22
|
-
}, [childrenCount > 1]);
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<Accordion
|
|
26
|
-
expandedKeys={expandedKeys}
|
|
27
|
-
gap={8}
|
|
28
|
-
onExpandedChange={(keys) => setExpandedKeys(keys as string[])}
|
|
29
|
-
>
|
|
30
|
-
<AccordionItem
|
|
31
|
-
itemKey="instruction"
|
|
32
|
-
paddingBlock={4}
|
|
33
|
-
paddingInline={4}
|
|
34
|
-
title={
|
|
35
|
-
<Flexbox align="center" gap={8} horizontal>
|
|
36
|
-
<Block
|
|
37
|
-
align="center"
|
|
38
|
-
flex="none"
|
|
39
|
-
gap={4}
|
|
40
|
-
height={24}
|
|
41
|
-
horizontal
|
|
42
|
-
justify="center"
|
|
43
|
-
style={{ fontSize: 12 }}
|
|
44
|
-
variant="outlined"
|
|
45
|
-
width={24}
|
|
46
|
-
>
|
|
47
|
-
<Icon color={cssVar.colorTextSecondary} icon={ScrollText} />
|
|
48
|
-
</Block>
|
|
49
|
-
<Text as="span" type="secondary">
|
|
50
|
-
{t('task.instruction')}
|
|
51
|
-
</Text>
|
|
52
|
-
</Flexbox>
|
|
53
|
-
}
|
|
54
|
-
>
|
|
55
|
-
<Block padding={12} style={{ marginBlock: 8, maxHeight: 300, overflow: 'auto' }} variant={'outlined'}>
|
|
56
|
-
<Markdown variant={'chat'}>{instruction}</Markdown>
|
|
57
|
-
</Block>
|
|
58
|
-
</AccordionItem>
|
|
59
|
-
</Accordion>
|
|
60
|
-
);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
export default InstructionAccordion;
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { type AssistantContentBlock } from '@lobechat/types';
|
|
4
|
-
import { Block, Flexbox, ScrollShadow, Text } from '@lobehub/ui';
|
|
5
|
-
import { createStaticStyles } from 'antd-style';
|
|
6
|
-
import { type RefObject, memo, useEffect, useMemo, useState } from 'react';
|
|
7
|
-
import { useTranslation } from 'react-i18next';
|
|
8
|
-
|
|
9
|
-
import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
|
|
10
|
-
import AnimatedNumber from '@/features/Conversation/Messages/components/Extras/Usage/UsageDetail/AnimatedNumber';
|
|
11
|
-
import { useAutoScroll } from '@/hooks/useAutoScroll';
|
|
12
|
-
|
|
13
|
-
import ContentBlock from '../../AssistantGroup/components/ContentBlock';
|
|
14
|
-
import { accumulateUsage, formatElapsedTime } from '../../Tasks/shared/utils';
|
|
15
|
-
import Usage from '../../components/Extras/Usage';
|
|
16
|
-
|
|
17
|
-
const styles = createStaticStyles(({ css }) => ({
|
|
18
|
-
contentScroll: css`
|
|
19
|
-
max-height: min(50vh, 300px);
|
|
20
|
-
`,
|
|
21
|
-
}));
|
|
22
|
-
|
|
23
|
-
interface ProcessingStateProps {
|
|
24
|
-
assistantId: string;
|
|
25
|
-
blocks: AssistantContentBlock[];
|
|
26
|
-
model?: string;
|
|
27
|
-
provider?: string;
|
|
28
|
-
startTime?: number;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const ProcessingState = memo<ProcessingStateProps>(
|
|
32
|
-
({ blocks, assistantId, startTime, model, provider }) => {
|
|
33
|
-
const { t } = useTranslation('chat');
|
|
34
|
-
const [elapsedTime, setElapsedTime] = useState(0);
|
|
35
|
-
const { ref, handleScroll } = useAutoScroll<HTMLDivElement>({
|
|
36
|
-
deps: [blocks],
|
|
37
|
-
enabled: true,
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const totalToolCalls = useMemo(
|
|
41
|
-
() => blocks.reduce((sum, block) => sum + (block.tools?.length || 0), 0),
|
|
42
|
-
[blocks],
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
// Accumulate usage from all blocks
|
|
46
|
-
const accumulatedUsage = useMemo(() => accumulateUsage(blocks), [blocks]);
|
|
47
|
-
|
|
48
|
-
// Calculate initial elapsed time
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
if (startTime) {
|
|
51
|
-
setElapsedTime(Math.max(0, Date.now() - startTime));
|
|
52
|
-
}
|
|
53
|
-
}, [startTime]);
|
|
54
|
-
|
|
55
|
-
// Timer for updating elapsed time every second
|
|
56
|
-
useEffect(() => {
|
|
57
|
-
if (!startTime) return;
|
|
58
|
-
|
|
59
|
-
const timer = setInterval(() => {
|
|
60
|
-
setElapsedTime(Math.max(0, Date.now() - startTime));
|
|
61
|
-
}, 1000);
|
|
62
|
-
|
|
63
|
-
return () => clearInterval(timer);
|
|
64
|
-
}, [startTime]);
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
<Flexbox gap={8}>
|
|
68
|
-
<Flexbox align="center" gap={8} horizontal paddingInline={4}>
|
|
69
|
-
<Block
|
|
70
|
-
align="center"
|
|
71
|
-
flex="none"
|
|
72
|
-
gap={4}
|
|
73
|
-
height={24}
|
|
74
|
-
horizontal
|
|
75
|
-
justify="center"
|
|
76
|
-
style={{ fontSize: 12 }}
|
|
77
|
-
variant="outlined"
|
|
78
|
-
width={24}
|
|
79
|
-
>
|
|
80
|
-
<NeuralNetworkLoading size={16} />
|
|
81
|
-
</Block>
|
|
82
|
-
<Flexbox align="center" gap={4} horizontal>
|
|
83
|
-
<Text as="span" type="secondary" weight={500}>
|
|
84
|
-
<AnimatedNumber
|
|
85
|
-
duration={500}
|
|
86
|
-
formatter={(v) => Math.round(v).toString()}
|
|
87
|
-
value={totalToolCalls}
|
|
88
|
-
/>
|
|
89
|
-
</Text>
|
|
90
|
-
<Text as="span" type="secondary">
|
|
91
|
-
{t('task.metrics.toolCallsShort')}
|
|
92
|
-
</Text>
|
|
93
|
-
{startTime && (
|
|
94
|
-
<Text as="span" type="secondary">
|
|
95
|
-
({formatElapsedTime(elapsedTime)})
|
|
96
|
-
</Text>
|
|
97
|
-
)}
|
|
98
|
-
</Flexbox>
|
|
99
|
-
</Flexbox>
|
|
100
|
-
<ScrollShadow
|
|
101
|
-
className={styles.contentScroll}
|
|
102
|
-
offset={12}
|
|
103
|
-
onScroll={handleScroll}
|
|
104
|
-
ref={ref as RefObject<HTMLDivElement>}
|
|
105
|
-
size={8}
|
|
106
|
-
>
|
|
107
|
-
<Flexbox gap={8}>
|
|
108
|
-
{blocks.map((block) => (
|
|
109
|
-
<ContentBlock {...block} assistantId={assistantId} disableEditing key={block.id} />
|
|
110
|
-
))}
|
|
111
|
-
</Flexbox>
|
|
112
|
-
</ScrollShadow>
|
|
113
|
-
|
|
114
|
-
{/* Usage display */}
|
|
115
|
-
{model && provider && <Usage model={model} provider={provider} usage={accumulatedUsage} />}
|
|
116
|
-
</Flexbox>
|
|
117
|
-
);
|
|
118
|
-
},
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
ProcessingState.displayName = 'ClientProcessingState';
|
|
122
|
-
|
|
123
|
-
export default ProcessingState;
|