Files
pikasTech-HWLAB/web/hwlab-cloud-web/app-trace.test.ts
T

121 lines
3.9 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import { traceDisplayRows } from "./app-trace.ts";
test("trace display rows render request, setup, command, assistant markdown, and completion path", () => {
const trace = {
traceId: "trc_trace_contract",
events: traceEvents(),
assistantStreams: [{ itemId: "assistant-final", text: "# 处理完成\n\n- trace markdown ok" }]
};
const rows = traceDisplayRows(trace, trace.events);
const text = rows.map((row) => `${row.header}\n${row.body ?? ""}`).join("\n---\n");
assert.match(text, /请求接受.*请检查 trace/u);
assert.match(text, /会话复用/u);
assert.match(text, /工具调用/u);
assert.match(text, /hostJobId=job-trace-1/u);
assert.match(text, /助手最后一条消息,轮次完成/u);
assert.match(text, /# 处理完成/u);
assert.equal(rows.some((row) => row.bodyFormat === "markdown"), true);
});
test("trace display rows render completion when no terminal assistant event exists", () => {
const events = [
event(1, "request:accepted", { promptSummary: "只跑完成事件" }),
event(2, "turn:completed", { status: "completed" })
];
const rows = traceDisplayRows({ traceId: "trc_completion", events }, events);
assert.equal(rows.some((row) => /轮次完成/u.test(row.header)), true);
});
test("trace display rows render assistant item text when stream snapshot is absent", () => {
const events = [
event(1, "request:accepted", { promptSummary: "请列出 device-pod" }),
event(2, "assistant:item_completed", {
type: "assistant_message",
status: "completed",
itemId: "msg_item_0",
message: "当前有以下 **5 个 device-pod** 可用。"
}),
commandEvent(3, "item/commandExecution:completed", {
itemId: "cmd-trace-2",
command: "grep -rn device-pod /workspace/hwlab",
status: "completed",
exitCode: 0,
stdoutSummary: "success=true"
}),
event(4, "assistant:completed", {
type: "assistant_message",
terminal: true,
status: "completed",
itemId: "assistant-final",
message: "可以继续指定要操作的 device-pod。"
})
];
const rows = traceDisplayRows({ traceId: "trc_assistant_item_text", events }, events);
const text = rows.map((row) => `${row.header}\n${row.body ?? ""}`).join("\n---\n");
assert.match(text, /🤖 助手消息(第一条)/u);
assert.match(text, /当前有以下 \*\*5 个 device-pod\*\* 可用/u);
assert.match(text, /工具调用/u);
assert.match(text, /助手最后一条消息/u);
assert.match(text, /可以继续指定要操作的 device-pod/u);
});
function traceEvents() {
return [
event(1, "request:accepted", { promptSummary: "请检查 trace" }),
event(2, "session:reused"),
commandEvent(3, "item/commandExecution:started", {
itemId: "cmd-trace-1",
command: "bash -lc 'build start'"
}),
{
...event(4, "item/commandExecution/outputDelta", {
type: "tool_call",
status: "output_chunk",
itemId: "cmd-trace-1",
outputSummary: '{"hostJobId":"job-trace-1","success":true}'
})
},
commandEvent(5, "item/commandExecution:completed", {
itemId: "cmd-trace-1",
command: "bash -lc 'build status'",
status: "completed",
exitCode: 0,
durationMs: 1200
}),
event(6, "assistant:completed", {
type: "assistant_message",
terminal: true,
status: "completed",
itemId: "assistant-final"
})
];
}
function commandEvent(seq, label, fields) {
return event(seq, label, {
type: "tool_call",
toolName: "commandExecution",
...fields
});
}
function event(seq, label, fields = {}) {
return {
traceId: "trc_trace_contract",
seq,
label,
type: fields.type ?? "event",
status: fields.status ?? "observed",
createdAt: new Date(1779690000000 + seq * 1000).toISOString(),
...fields
};
}