diff --git a/internal/cloud/code-agent-agentrun-adapter.ts b/internal/cloud/code-agent-agentrun-adapter.ts index c8d9bb97..cef5f06f 100644 --- a/internal/cloud/code-agent-agentrun-adapter.ts +++ b/internal/cloud/code-agent-agentrun-adapter.ts @@ -805,7 +805,21 @@ function mapAgentRunEvent(event, mapping = {}) { return { ...base, type: "backend", status: "running", label: `agentrun:backend:${phase}`, message: textPayload(payload, phase), waitingFor: waitingForForPhase(phase) }; } if (event.type === "assistant_message") { - return { ...base, type: "assistant", status: "running", label: "agentrun:assistant:message", message: textPayload(payload, "assistant message"), text: textPayload(payload, "") }; + const terminal = payload.replyAuthority === true || payload.final === true; + return { + ...base, + type: "assistant", + status: terminal ? "completed" : "running", + label: "agentrun:assistant:message", + message: textPayload(payload, "assistant message"), + text: textPayload(payload, ""), + itemId: payload.itemId ?? null, + messageIndex: payload.messageIndex ?? null, + messageCount: payload.messageCount ?? null, + replyAuthority: payload.replyAuthority === true, + final: payload.final === true, + terminal + }; } if (event.type === "tool_call") { const commandExecution = agentRunCommandExecutionEvent(base, payload); diff --git a/tools/hwlab-cli/client.test.ts b/tools/hwlab-cli/client.test.ts index b11bfe59..f44a03b0 100644 --- a/tools/hwlab-cli/client.test.ts +++ b/tools/hwlab-cli/client.test.ts @@ -506,6 +506,28 @@ test("hwlab-cli Web trace render reports suppressed noise and command tool detai assert.match(text, /当前可见 device-pod/u); }); +test("hwlab-cli Web trace render keeps AgentRun middle assistant message", async () => { + const result = await runHwlabCli(["client", "agent", "trace", "trc_render_agentrun_middle", "--base-url", "http://web.test", "--cookie", "hwlab_session=session-a", "--render", "web"], { + fetchImpl: async () => new Response(JSON.stringify({ + status: "completed", + traceId: "trc_render_agentrun_middle", + events: [ + { traceId: "trc_render_agentrun_middle", seq: 1, label: "agentrun:request:accepted", status: "running", type: "request", createdAt: "2026-06-01T13:00:00.000Z" }, + { traceId: "trc_render_agentrun_middle", seq: 2, label: "agentrun:assistant:message", type: "assistant", status: "running", itemId: "msg_progress", messageIndex: 1, messageCount: 2, replyAuthority: false, final: false, message: "我先检查当前 device-pod 列表。", createdAt: "2026-06-01T13:00:01.000Z" }, + { traceId: "trc_render_agentrun_middle", seq: 3, label: "agentrun:assistant:message", type: "assistant", status: "completed", itemId: "msg_final", messageIndex: 2, messageCount: 2, replyAuthority: true, final: true, terminal: true, message: "当前有 2 个 device-pod 可用。", createdAt: "2026-06-01T13:00:02.000Z" }, + { traceId: "trc_render_agentrun_middle", seq: 4, label: "agentrun:terminal:completed", type: "result", terminal: true, status: "completed", createdAt: "2026-06-01T13:00:03.000Z" } + ] + }), { status: 200 }) + }); + + assert.equal(result.exitCode, 0); + assert.equal(result.payload.body.render, "web"); + const text = JSON.stringify(result.payload.body.rows); + assert.match(text, /我先检查当前 device-pod 列表/u); + assert.match(text, /当前有 2 个 device-pod 可用/u); + assert.match(text, /助手最后一条消息/u); +}); + test("hwlab-cli client agent trace auto logs in when protected trace has no local session", async () => { const cwd = await mkdtemp(path.join(os.tmpdir(), "hwlab-cli-client-auth-")); const calls: any[] = []; diff --git a/web/hwlab-cloud-web/app-trace.test.ts b/web/hwlab-cloud-web/app-trace.test.ts index d6bf570b..f168af77 100644 --- a/web/hwlab-cloud-web/app-trace.test.ts +++ b/web/hwlab-cloud-web/app-trace.test.ts @@ -96,7 +96,10 @@ test("trace display rows suppress low-value AgentRun backend noise", () => { }), event(15, "agentrun:assistant:message", { type: "assistant", - status: "running", + status: "completed", + replyAuthority: true, + final: true, + terminal: true, message: "当前可见 1 个 device-pod。" }), event(16, "agentrun:terminal:completed", { type: "result", terminal: true, status: "completed" }) @@ -145,6 +148,43 @@ test("trace display rows collapse successful assistant-only AgentRun turns", () assert.match(rows[0].body ?? "", /HWLAB663_FINAL_T2_OK/u); }); +test("trace display rows keep AgentRun middle assistant message before final authority", () => { + const events = [ + event(1, "agentrun:request:accepted", { message: "accepted" }), + event(2, "agentrun:assistant:message", { + type: "assistant", + status: "running", + itemId: "msg_progress", + messageIndex: 1, + messageCount: 2, + replyAuthority: false, + final: false, + message: "我先检查当前 device-pod 列表。" + }), + event(3, "agentrun:assistant:message", { + type: "assistant", + status: "completed", + itemId: "msg_final", + messageIndex: 2, + messageCount: 2, + replyAuthority: true, + final: true, + terminal: true, + message: "当前有 2 个 device-pod 可用。" + }), + event(4, "agentrun:terminal:completed", { type: "result", terminal: true, status: "completed" }) + ]; + + const rows = traceDisplayRows({ traceId: "trc_agentrun_middle_message", events }, events); + const text = rows.map((row) => `${row.header}\n${row.body ?? ""}`).join("\n---\n"); + + assert.equal(rows.length, 2); + assert.match(text, /助手消息(第一条)/u); + assert.match(text, /我先检查当前 device-pod 列表/u); + assert.match(text, /助手最后一条消息/u); + assert.match(text, /当前有 2 个 device-pod 可用/u); +}); + test("trace display rows collapse AgentRun reused backend lifecycle noise", () => { const events = [ event(1, "agentrun:request:accepted", { message: "accepted" }), @@ -174,7 +214,10 @@ test("trace display rows collapse AgentRun reused backend lifecycle noise", () = }), event(12, "agentrun:assistant:message", { type: "assistant", - status: "running", + status: "completed", + replyAuthority: true, + final: true, + terminal: true, message: "HWLAB663_REUSE_T2_OK" }), event(13, "agentrun:backend:backend-turn-finished", { message: "backend-turn-finished", waitingFor: "agentrun-backend" }), diff --git a/web/hwlab-cloud-web/app-trace.ts b/web/hwlab-cloud-web/app-trace.ts index 9b8c9b94..3ddf56ec 100644 --- a/web/hwlab-cloud-web/app-trace.ts +++ b/web/hwlab-cloud-web/app-trace.ts @@ -993,7 +993,9 @@ function isAssistantMessageTraceEvent(event) { function isTerminalAssistantTraceEvent(event) { const label = String(event?.label ?? ""); - return event?.terminal === true || label === "assistant:completed" || label === "agentrun:assistant:message"; + if (event?.terminal === true || label === "assistant:completed") return true; + if (label === "agentrun:assistant:message") return event?.replyAuthority === true || event?.final === true; + return false; } function isRequestTraceEvent(event) {