Files
pikasTech-agentrun/src/selftest/cases/15-cli-events-summary.ts
T
2026-06-10 09:34:22 +08:00

147 lines
9.2 KiB
TypeScript

import assert from "node:assert/strict";
import type { JsonRecord } from "../../common/types.js";
import { assertNoSecretLeak, type SelfTestContext, type SelfTestResult } from "../harness.js";
import { renderRunEventSummaryTsv, summarizeQueueCommanderSnapshot, summarizeQueueDispatchResult, summarizeQueueTaskListResult, summarizeQueueTaskShowResult, summarizeRunEventPage, summarizeSessionEventPage } from "../../../scripts/src/cli.js";
export default function selfTest(_context: SelfTestContext): SelfTestResult {
const summary = summarizeRunEventPage({ items: [
{ seq: 11, type: "backend_status", payload: { phase: "run-claimed", summary: { text: "runner claimed" } } },
{ seq: 12, type: "tool_call", payload: { method: "shell", status: "completed", command: "curl -H 'Authorization: Bearer test-token-material' https://example.invalid", exitCode: 0, durationMs: 321, outputSummary: "downloaded archive\nnext line", outputBytes: 4096, outputTruncated: true } },
{ seq: 13, type: "assistant_message", payload: { text: "final assistant text that is intentionally longer than the selected summary limit" } },
] }, { runId: "run_selftest", afterSeq: 10, limit: 3, tail: 2, summaryChars: 40 });
assert.equal(summary.action, "runs-events-summary");
assert.equal(summary.sourceCount, 3);
assert.equal(summary.count, 2);
const items = summary.items as JsonRecord[];
assert.deepEqual(items.map((item) => item.seq), [12, 13]);
assert.equal(items[0]?.method, "shell");
assert.equal(items[0]?.status, "completed");
assert.equal(items[0]?.exitCode, 0);
assert.equal(items[0]?.durationMs, 321);
assert.equal(items[0]?.outputTruncated, true);
assert.equal(String(items[0]?.command).includes("test-token-material"), false);
assert.equal(String(items[0]?.outputSummary).includes("\n"), false);
assert.equal(String(items[1]?.summary).endsWith("..."), true);
assertNoSecretLeak(summary);
const tsv = renderRunEventSummaryTsv(summary);
assert.match(tsv, /^seq\ttype\tmethod\tstatus\texitCode\tdurationMs\toutputTruncated\toutputBytes\tsummary\n/u);
assert.equal(tsv.includes("\n12\ttool_call\tshell\tcompleted\t0\t321\ttrue\t4096"), true);
assert.equal(tsv.includes("test-token-material"), false);
const hugeRunnerTrace = "runner trace line with test-token-material\n".repeat(2_000);
const sessionSummary = summarizeSessionEventPage({
sessionId: "sess_noise",
runId: "run_noise",
items: [
{ id: "evt_tool", seq: 265, type: "tool_call", payload: { itemId: "tool_noise", method: "commandExecution", status: "completed", command: "printf hidden", outputSummary: "tool completed" } },
{ id: "evt_output", seq: 266, type: "command_output", payload: { itemId: "tool_noise", text: hugeRunnerTrace, outputSummary: "large stdout", outputBytes: 100_000, outputTruncated: true } },
{
id: "evt_status",
seq: 267,
type: "backend_status",
payload: {
phase: "turn/cancelled",
status: "cancelled",
commandId: "cmd_noise",
runnerTrace: { raw: hugeRunnerTrace },
rawEvent: { nested: hugeRunnerTrace },
},
},
],
count: 3,
cursor: "266",
}, { kind: "trace", sessionId: "sess_noise", afterSeq: 250, limit: 100, runId: null, tail: null, summaryChars: 80, includeOutput: false });
const sessionItems = sessionSummary.items as JsonRecord[];
assert.equal(sessionSummary.action, "session-trace-summary");
assert.equal(sessionSummary.sourceCount, 3);
assert.equal(sessionSummary.displayedCount, 1);
assert.equal(sessionSummary.nextAfterSeq, 267);
assert.equal((sessionSummary.suppressedEvents as JsonRecord).count, 2);
assert.equal(((sessionSummary.suppressedEvents as JsonRecord).byType as JsonRecord).command_output, 1);
assert.equal(((sessionSummary.suppressedEvents as JsonRecord).byType as JsonRecord).backend_status, 1);
assert.deepEqual(sessionItems.map((item) => item.type), ["tool_call"]);
assert.equal(((sessionItems[0]?.detailCommands as JsonRecord).item as string).includes("--item-id tool_noise"), true);
assert.equal(((sessionItems[0]?.detailCommands as JsonRecord).seq as string).includes("--seq 265"), true);
assert.ok(Number((sessionSummary.suppressedEvents as JsonRecord).outputBytes) > 0);
assert.equal(JSON.stringify(sessionSummary).includes("runner trace line"), false);
assert.equal(String((sessionSummary.drillDownCommands as JsonRecord).full).includes("--full"), true);
assert.equal(String((sessionSummary.drillDownCommands as JsonRecord).raw).includes("--raw"), true);
assertNoSecretLeak(sessionSummary);
const sessionOutputIncluded = summarizeSessionEventPage({
sessionId: "sess_noise",
runId: "run_noise",
items: [{ id: "evt_output", seq: 266, type: "command_output", payload: { itemId: "tool_noise", text: hugeRunnerTrace, outputSummary: "large stdout", outputBytes: 100_000, outputTruncated: true } }],
count: 1,
cursor: "266",
}, { kind: "output", sessionId: "sess_noise", afterSeq: 250, limit: 100, runId: "run_noise", tail: null, summaryChars: 80, includeOutput: true });
assert.equal(((sessionOutputIncluded.items as JsonRecord[])[0]?.detailCommands as JsonRecord).seq, "./scripts/agentrun sessions output sess_noise --seq 266 --run-id run_noise --full");
assert.equal(JSON.stringify(sessionOutputIncluded).includes("runner trace line"), false);
const queueSummary = summarizeQueueDispatchResult({
action: "queue-dispatch",
mutation: true,
task: { id: "qt_noise", state: "running", queue: "dev", lane: "case", title: "large trace queue dispatch", version: 7, payload: { prompt: hugeRunnerTrace } },
run: { id: "run_noise", status: "running", terminalStatus: null, backendProfile: "codex", providerId: "G14" },
command: { id: "cmd_noise", runId: "run_noise", seq: 1, type: "turn", state: "acknowledged", payload: { prompt: hugeRunnerTrace } },
runnerJob: { action: "create-kubernetes-job", runId: "run_noise", commandId: "cmd_noise", attemptId: "attempt_noise", runnerId: "runner_noise", namespace: "agentrun-v01", jobName: "job-noise", runner: { logPath: "kubectl logs job/job-noise", runnerTrace: hugeRunnerTrace } },
latestAttempt: { attemptId: "attempt_noise", state: "running", runId: "run_noise", commandId: "cmd_noise", runnerJobId: "rj_noise", sessionId: "sess_noise", sessionPath: "/api/v1/sessions/sess_noise" },
}, "qt_noise");
assert.equal(queueSummary.action, "queue-dispatch-summary");
assert.equal(((queueSummary.runnerJob as JsonRecord).attemptId), "attempt_noise");
assert.equal(JSON.stringify(queueSummary).includes("runner trace line"), false);
assert.equal(String(((queueSummary.pollCommands as JsonRecord).events)).includes("--tail-summary"), true);
assert.equal(((queueSummary.expandedOutput as JsonRecord).fullFlag), "--full");
assertNoSecretLeak(queueSummary);
const noisyTask = {
id: "qt_noisy",
state: "completed",
queue: "dev",
lane: "case",
title: "noisy queue task",
priority: 50,
backendProfile: "codex",
providerId: "G14",
version: 9,
payload: { prompt: hugeRunnerTrace },
latestAttempt: { attemptId: "attempt_noisy", state: "completed", runId: "run_noisy", commandId: "cmd_noisy", runnerJobId: "rj_noisy", sessionId: "sess_noisy", sessionPath: "/api/v1/sessions/sess_noisy" },
sessionRef: { sessionId: "sess_noisy" },
unread: true,
active: false,
attentionState: "unread",
};
const commanderSummary = summarizeQueueCommanderSnapshot({
queue: null,
readerId: "cli",
stats: { queue: null, total: 2, maxVersion: 9, byState: { completed: 1 }, byLane: { case: 1 }, byBackendProfile: { codex: 1 }, generatedAt: "2026-06-10T00:00:00.000Z" },
items: [noisyTask, { ...noisyTask, id: "qt_hidden" }],
generatedAt: "2026-06-10T00:00:00.000Z",
}, { limit: 1 });
assert.equal(commanderSummary.action, "queue-commander-summary");
assert.equal(commanderSummary.sourceCount, 2);
assert.equal(commanderSummary.displayedCount, 1);
assert.equal(JSON.stringify(commanderSummary).includes("runner trace line"), false);
assert.equal((((commanderSummary.items as JsonRecord[])[0]?.latestAttempt as JsonRecord).sessionId), "sess_noisy");
assert.equal(String(((commanderSummary.drillDownCommands as JsonRecord).full)).includes("--full"), true);
assertNoSecretLeak(commanderSummary);
const listSummary = summarizeQueueTaskListResult({ items: [noisyTask], nextCursor: "9" }, { limit: 20 });
assert.equal(listSummary.action, "queue-list-summary");
assert.equal(JSON.stringify(listSummary).includes("runner trace line"), false);
assert.equal(String(((listSummary.drillDownCommands as JsonRecord).next)).includes("--cursor 9"), true);
assertNoSecretLeak(listSummary);
const showSummary = summarizeQueueTaskShowResult(noisyTask, "qt_noisy");
assert.equal(showSummary.action, "queue-show-summary");
assert.equal(JSON.stringify(showSummary).includes("runner trace line"), false);
assert.ok(Number(showSummary.payloadBytes) > 10_000);
assert.equal(String(((showSummary.pollCommands as JsonRecord).trace)).includes("sess_noisy"), true);
assertNoSecretLeak(showSummary);
return { name: "15-cli-events-summary", tests: ["runs-events-summary-tail", "runs-events-summary-tsv-redaction", "sessions-events-low-noise-summary", "queue-dispatch-low-noise-summary", "queue-list-show-commander-low-noise-summary"] };
}