fix: preserve AgentRun command tool calls in trace

This commit is contained in:
Codex
2026-06-02 12:15:21 +08:00
parent 5beff46ee9
commit fcfc7e84e5
4 changed files with 27 additions and 14 deletions
@@ -1041,20 +1041,21 @@ function mapAgentRunEvent(event, mapping = {}) {
function agentRunCommandExecutionEvent(base, payload = {}) {
const item = payload.item && typeof payload.item === "object" ? payload.item : null;
if (item?.type !== "commandExecution") return null;
const payloadToolType = firstNonEmpty(payload.toolName, payload.type, payload.name);
if (item?.type !== "commandExecution" && payloadToolType !== "commandExecution") return null;
const method = String(payload.method ?? "");
const completed = method === "item/completed" || item.status === "completed";
const output = firstNonEmpty(item.aggregatedOutput, item.stdout, item.output, payload.summary?.text, payload.itemPreview);
const completed = method === "item/completed" || payload.status === "completed" || item?.status === "completed";
const output = firstNonEmpty(item?.aggregatedOutput, item?.stdout, item?.output, payload.outputSummary, payload.stdoutSummary, payload.summary?.text, payload.itemPreview);
return {
...base,
type: "tool_call",
status: completed ? "completed" : "started",
label: completed ? "item/commandExecution:completed" : "item/commandExecution:started",
toolName: "commandExecution",
itemId: item.id ?? null,
command: item.command ?? item.commandLine ?? null,
exitCode: Number.isInteger(item.exitCode) ? item.exitCode : undefined,
durationMs: typeof item.durationMs === "number" ? item.durationMs : undefined,
itemId: item?.id ?? payload.itemId ?? null,
command: firstNonEmpty(item?.command, item?.commandLine, payload.command, payload.commandLine),
exitCode: Number.isInteger(item?.exitCode) ? item.exitCode : Number.isInteger(payload.exitCode) ? payload.exitCode : undefined,
durationMs: typeof item?.durationMs === "number" ? item.durationMs : typeof payload.durationMs === "number" ? payload.durationMs : undefined,
outputBytes: typeof payload.outputBytes === "number" ? payload.outputBytes : payload.summary?.outputBytes,
stdoutSummary: output,
outputSummary: output,
+1 -1
View File
@@ -249,7 +249,7 @@ test("cloud api /v1/agent/chat delegates v0.2 turns to AgentRun v0.1 over adapte
] });
return send({ items: [
{ id: "evt_1", runId: "run_hwlab_adapter", seq: 1, type: "backend_status", payload: { phase: "runner-job-created", commandId: "cmd_hwlab_adapter", attemptId: "attempt_hwlab_adapter", jobName: "agentrun-v01-runner-hwlab-adapter", namespace: "agentrun-v01" }, createdAt: "2026-06-01T00:00:00.000Z" },
{ id: "evt_tool", runId: "run_hwlab_adapter", seq: 2, type: "tool_call", payload: { method: "item/completed", item: { type: "commandExecution", id: "call_agentrun_tool", command: "/bin/sh -lc 'hwpod profile list'", status: "completed", exitCode: 0, durationMs: 708, aggregatedOutput: '{"ok":true,"action":"profile.list"}' }, summary: { outputBytes: 42, outputTruncated: false }, commandId: "cmd_hwlab_adapter", runnerId: "runner_hwlab_adapter", attemptId: "attempt_hwlab_adapter" }, createdAt: "2026-06-01T00:00:00.500Z" },
{ id: "evt_tool", runId: "run_hwlab_adapter", seq: 2, type: "tool_call", payload: { method: "item/completed", type: "commandExecution", toolName: "commandExecution", itemId: "call_agentrun_tool", command: "/bin/sh -lc 'hwpod profile list'", status: "completed", exitCode: 0, durationMs: 708, outputSummary: '{"ok":true,"action":"profile.list"}', summary: { outputBytes: 42, outputTruncated: false }, commandId: "cmd_hwlab_adapter", runnerId: "runner_hwlab_adapter", attemptId: "attempt_hwlab_adapter" }, createdAt: "2026-06-01T00:00:00.500Z" },
{ id: "evt_noise", runId: "run_hwlab_adapter", seq: 3, type: "backend_status", payload: { phase: "thread/status/changed", commandId: "cmd_hwlab_adapter" }, createdAt: "2026-06-01T00:00:00.750Z" },
{ id: "evt_2", runId: "run_hwlab_adapter", seq: 4, type: "assistant_message", payload: { commandId: "cmd_hwlab_adapter", text: "AgentRun adapter 已接管 HWLAB Code Agent。" }, createdAt: "2026-06-01T00:00:01.000Z" },
{ id: "evt_3", runId: "run_hwlab_adapter", seq: 5, type: "terminal_status", payload: { commandId: "cmd_hwlab_adapter", terminalStatus: "completed" }, createdAt: "2026-06-01T00:00:02.000Z" }
+7 -2
View File
@@ -606,19 +606,24 @@ test("hwlab-cli Web trace render reports suppressed noise and command tool detai
{ traceId: "trc_render_agentrun", seq: 1, label: "agentrun:backend:command-created", status: "running", type: "backend", createdAt: "2026-06-01T13:00:00.000Z" },
{ traceId: "trc_render_agentrun", seq: 2, label: "agentrun:backend:thread/status/changed", status: "running", type: "backend", createdAt: "2026-06-01T13:00:01.000Z" },
{ traceId: "trc_render_agentrun", seq: 3, label: "item/commandExecution:completed", type: "tool_call", toolName: "commandExecution", status: "completed", itemId: "call_1", command: "/bin/sh -lc 'hwpod profile list'", exitCode: 0, stdoutSummary: '{"ok":true,"action":"profile.list"}', createdAt: "2026-06-01T13:00:02.000Z" },
{ traceId: "trc_render_agentrun", seq: 4, label: "agentrun:assistant:message", type: "assistant", status: "running", message: "当前可见 device-pod。", createdAt: "2026-06-01T13:00:03.000Z" }
{ traceId: "trc_render_agentrun", seq: 4, label: "agentrun:tool:item/started", type: "tool_call", toolName: "commandExecution", status: "started", itemId: "call_2", command: "/bin/sh -lc 'printf TOOL_RENDER_OK'", createdAt: "2026-06-01T13:00:02.100Z" },
{ traceId: "trc_render_agentrun", seq: 5, label: "agentrun:tool:item/completed", type: "tool_call", toolName: "commandExecution", status: "completed", itemId: "call_2", command: "/bin/sh -lc 'printf TOOL_RENDER_OK'", exitCode: 0, stdoutSummary: "TOOL_RENDER_OK", outputBytes: 14, createdAt: "2026-06-01T13:00:02.200Z" },
{ traceId: "trc_render_agentrun", seq: 6, label: "agentrun:assistant:message", type: "assistant", status: "running", message: "当前可见 device-pod。", createdAt: "2026-06-01T13:00:03.000Z" }
]
}), { status: 200 })
});
assert.equal(result.exitCode, 0);
assert.equal(result.payload.body.render, "web");
assert.equal(result.payload.body.sourceEventCount, 4);
assert.equal(result.payload.body.sourceEventCount, 6);
assert.equal(result.payload.body.noiseEventCount, 2);
const text = JSON.stringify(result.payload.body.rows);
assert.equal(text.includes("thread/status/changed"), false);
assert.match(text, /hwpod profile list/u);
assert.match(text, /profile\.list/u);
assert.match(text, /TOOL_RENDER_OK/u);
assert.equal(text.includes("toolName=item/started"), false);
assert.equal(text.includes("toolName=item/completed"), false);
assert.match(text, / device-pod/u);
});
+11 -4
View File
@@ -303,7 +303,7 @@ export function traceDisplayRows(trace, events) {
if (isCommandExecutionTraceEvent(event)) {
const groupKey = traceCommandGroupKey(event);
const group = commandGroups.get(groupKey) ?? { key: groupKey, started: event, completed: event, outputs: [] };
const renderHere = event.label === "item/commandExecution:started" || group.started === event;
const renderHere = isCommandExecutionStartedTraceEvent(event) || group.started === event;
if (renderHere && !renderedCommands.has(groupKey)) {
const row = traceCommandSummaryRow(trace, group);
if (row) rows.push(row);
@@ -383,7 +383,7 @@ function traceCommandExecutionGroups(events) {
if (isCommandExecutionTraceEvent(event)) {
const key = traceCommandGroupKey(event, activeKey);
const group = ensureGroup(key, event);
if (event.label === "item/commandExecution:started") {
if (isCommandExecutionStartedTraceEvent(event)) {
group.started = group.started ?? event;
activeKey = key;
} else {
@@ -966,8 +966,15 @@ function traceCommandExecutionBody(event) {
}
function isCommandExecutionTraceEvent(event) {
return event?.type === "tool_call" && event?.toolName === "commandExecution" &&
(event?.label === "item/commandExecution:started" || event?.label === "item/commandExecution:completed");
if (event?.type !== "tool_call" || event?.toolName !== "commandExecution") return false;
const label = String(event?.label ?? "");
return label === "item/commandExecution:started" || label === "item/commandExecution:completed" ||
label === "agentrun:tool:item/started" || label === "agentrun:tool:item/completed";
}
function isCommandExecutionStartedTraceEvent(event) {
const label = String(event?.label ?? "");
return label === "item/commandExecution:started" || label === "agentrun:tool:item/started";
}
function isGenericToolCallTraceEvent(event) {