@lobehub/lobehub 2.0.10 → 2.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/database/src/repositories/agentGroup/index.ts +4 -0
- package/packages/types/src/message/ui/chat.ts +2 -0
- package/packages/types/src/tool/builtin.ts +5 -5
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/ForkGroupAndChat.tsx +2 -1
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/index.tsx +2 -2
- package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/useMarketGroupPublish.ts +11 -12
- 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/routers/lambda/agentGroup.ts +2 -0
- package/src/server/routers/lambda/market/agent.ts +17 -45
- package/src/server/routers/lambda/market/agentGroup.ts +13 -25
- 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
|
@@ -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;
|