fix: 归并异步工具状态卡片

- 统一异步阶段事件的稳定任务标识

- 保留原始工具调用 ID 供事件关联

- 将提交、轮询和结果状态更新到同一审批卡片
This commit is contained in:
2026-07-23 19:48:44 +08:00
parent 4a8e633083
commit 8b4ba65e1c
4 changed files with 147 additions and 3 deletions

View File

@@ -336,6 +336,74 @@ describe('agentTimelineAdapter', () => {
expect(error?.message).toBe('失败');
});
it('keeps async workflow polling events in the original approval card', () => {
const items: any[] = [];
applyAgentSseEnvelope(items, {
domain: 'TOOL',
type: 'FORM_REQUEST',
payload: {
input: { user_input: '写一篇小作文' },
requestId: 'req-async',
resumeToken: 'token-async',
toolCallId: 'submit-call-1',
toolName: '文档生成',
},
});
applyAgentSseEnvelope(items, {
domain: 'TOOL',
type: 'TOOL_RESULT',
payload: {
asyncTool: true,
phase: 'submit',
sourceToolCallId: 'submit-call-1',
status: 'RUNNING',
taskId: 'task-1',
toolCallId: 'task-1',
toolName: '文档生成',
},
});
for (const sourceToolCallId of ['observe-call-1', 'observe-call-2']) {
applyAgentSseEnvelope(items, {
domain: 'TOOL',
type: 'TOOL_CALL',
payload: {
asyncTool: true,
input: { taskId: 'task-1' },
phase: 'observe',
sourceToolCallId,
status: 'RUNNING',
taskId: 'task-1',
toolCallId: 'task-1',
toolName: '文档生成',
},
});
}
applyAgentSseEnvelope(items, {
domain: 'TOOL',
type: 'TOOL_RESULT',
payload: {
asyncTool: true,
phase: 'result',
sourceToolCallId: 'result-call-1',
status: 'SUCCEEDED',
taskId: 'task-1',
toolCallId: 'task-1',
toolName: '文档生成',
},
});
const tools = items.filter((item) => item.type === 'tool');
expect(tools).toHaveLength(1);
expect(tools[0]).toMatchObject({
mode: 'approval',
status: 'success',
taskId: 'task-1',
toolCallId: 'task-1',
toolName: '文档生成',
});
});
it('keeps assistant text and approval card when a tool request is rejected', () => {
const items: any[] = [];

View File

@@ -463,6 +463,7 @@ export function applyAgentSseEnvelope(
}
if (domain === 'TOOL' && (type === 'TOOL_CALL' || type === 'TOOL_RESULT')) {
const asyncTool = payload.asyncTool === true;
const taskInput = asRecord(payload.input ?? payload.toolInput);
const toolName = normalizeToolName(
payload.toolDisplayName ?? payload.toolName ?? payload.name,
);
@@ -485,6 +486,12 @@ export function applyAgentSseEnvelope(
metadata,
'knowledge-retrieval',
),
sourceToolCallId: asyncTool
? asText(payload.sourceToolCallId ?? payload.source_tool_call_id)
: undefined,
taskId: asyncTool
? asText(payload.taskId ?? taskInput.taskId ?? taskInput.task_id)
: undefined,
toolCallId: asyncTool
? asText(payload.toolCallId ?? payload.taskId ?? payload.id)
: normalizeToolCallId(payload),