fix: Trace Viewer 内容渲染修复
1. useAgentStream: 每轮迭代只创建一个 TraceStep, 状态转换时更新而非新建; tool_result 反向搜索包含 toolCallId 的步骤, 修复工具结果丢失 2. TraceStep: 渲染工具状态图标/结果/错误/耗时; Thought 添加 maxHeight 200+滚动; 展开状态用户操作后不被自动覆盖 3. ToolResultBlock: 移除 500 字符截断, 改为 maxHeight 300+滚动 4. ToolCallCard: 参数区域添加 overflowY auto+wordBreak
This commit is contained in:
+41
-31
@@ -4,10 +4,10 @@
|
||||
* 监听 window.metona.agent.onStreamEvent / onStateChange,将事件分发到 Zustand Store。
|
||||
*
|
||||
* 架构设计:
|
||||
* - onStateChange:迭代号追踪 + 消息卡片创建 + Trace 步骤创建 + Agent 状态映射
|
||||
* (状态变化事件总是先于同迭代的流式内容事件到达,因此在此统一管理迭代边界)
|
||||
* - onStateChange:迭代号追踪 + 消息卡片创建 + Trace 步骤管理 + Agent 状态映射
|
||||
* 每轮迭代只创建一个 TraceStep,状态转换时更新当前步骤的 state 字段(避免碎片化)
|
||||
* - onStreamEvent:纯内容更新(reasoning、text、tool_call、tool_result、usage、done、error)
|
||||
* (不再处理迭代号比较,消除竞态条件)
|
||||
* tool_result 反向搜索包含对应 toolCallId 的 TraceStep(修复工具结果丢失)
|
||||
*/
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
@@ -147,22 +147,27 @@ export function useAgentStream(): void {
|
||||
getStore().updateMessage(lastMsg.id, { toolCalls: updatedToolCalls });
|
||||
}
|
||||
|
||||
// 同步更新 Trace 步骤中的工具调用状态
|
||||
// 反向搜索包含该 toolCallId 的 TraceStep(修复工具结果丢失)
|
||||
// tool_call_complete 在 THINKING 阶段写入,tool_result 在 EXECUTING 阶段到达
|
||||
// 两者可能在同一轮迭代但不同状态转换,需反向查找
|
||||
const steps = getStore().traceSteps;
|
||||
const lastTrace = steps[steps.length - 1];
|
||||
if (lastTrace?.toolCalls) {
|
||||
const updatedTraceToolCalls = lastTrace.toolCalls.map((tc) =>
|
||||
tc.id === data.toolResult!.toolCallId
|
||||
? {
|
||||
...tc,
|
||||
status: data.toolResult!.success ? 'success' as const : 'error' as const,
|
||||
result: data.toolResult!.result,
|
||||
error: data.toolResult!.error,
|
||||
durationMs: data.toolResult!.durationMs,
|
||||
}
|
||||
: tc,
|
||||
);
|
||||
getStore().updateLastTraceStep({ toolCalls: updatedTraceToolCalls });
|
||||
for (let i = steps.length - 1; i >= 0; i--) {
|
||||
const trace = steps[i];
|
||||
if (trace.toolCalls?.some((tc) => tc.id === data.toolResult!.toolCallId)) {
|
||||
const updatedTraceToolCalls = trace.toolCalls.map((tc) =>
|
||||
tc.id === data.toolResult!.toolCallId
|
||||
? {
|
||||
...tc,
|
||||
status: data.toolResult!.success ? 'success' as const : 'error' as const,
|
||||
result: data.toolResult!.result,
|
||||
error: data.toolResult!.error,
|
||||
durationMs: data.toolResult!.durationMs,
|
||||
}
|
||||
: tc,
|
||||
);
|
||||
getStore().updateTraceStep(trace.iteration, { toolCalls: updatedTraceToolCalls });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -260,26 +265,31 @@ export function useAgentStream(): void {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Trace 步骤管理 ---
|
||||
// --- Trace 步骤管理(每轮迭代一个步骤,状态转换时更新而非新建)---
|
||||
if (data.state && data.iteration != null) {
|
||||
const traceSteps = store.traceSteps;
|
||||
const lastStep = traceSteps[traceSteps.length - 1];
|
||||
|
||||
// 标记上一个 Trace 步骤为已完成
|
||||
if (traceSteps.length > 0) {
|
||||
const lastStep = traceSteps[traceSteps.length - 1];
|
||||
if (!lastStep.completedAt) {
|
||||
// 判断是否需要创建新步骤:同一迭代的首次状态(INIT/THINKING)创建新步骤
|
||||
// 后续状态转换(EXECUTING/OBSERVING等)只更新当前步骤的 state 字段
|
||||
const isSameIteration = lastStep && lastStep.iteration === data.iteration;
|
||||
|
||||
if (isSameIteration) {
|
||||
// 同一迭代内的状态转换 → 更新当前步骤状态
|
||||
store.updateLastTraceStep({ state: data.state });
|
||||
} else {
|
||||
// 新迭代 → 标记上一步完成,创建新步骤
|
||||
if (lastStep && !lastStep.completedAt) {
|
||||
store.updateLastTraceStep({ completedAt: Date.now() });
|
||||
}
|
||||
store.addTraceStep({
|
||||
id: `trace_${data.iteration}_${data.state}_${Date.now()}`,
|
||||
iteration: data.iteration,
|
||||
state: data.state,
|
||||
startedAt: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
// 创建新的 Trace 步骤
|
||||
store.addTraceStep({
|
||||
id: `trace_${data.iteration}_${data.state}_${Date.now()}`,
|
||||
iteration: data.iteration,
|
||||
state: data.state,
|
||||
startedAt: Date.now(),
|
||||
});
|
||||
|
||||
// --- Agent 状态映射 ---
|
||||
const stateToStatus: Record<string, AgentStatus> = {
|
||||
THINKING: 'thinking',
|
||||
|
||||
Reference in New Issue
Block a user