import assert from "node:assert/strict"; import test from "node:test"; import { getActivityHeadline, getLatestActivityHeadline, isMeaningfulItem, isSpineItem, shouldShowTranscriptRowTimestamp, } from "./agentSessionTranscriptPresentation.ts"; const baseTimestamp = "2026-06-14T19:00:00.000Z"; function makeTool(overrides = {}) { return { id: "tool:1", type: "tool", title: "Send Message", toolName: "send_message", buzzToolName: "send_message", status: "executing", args: { channel_id: "abc" }, result: "", isError: false, timestamp: baseTimestamp, startedAt: baseTimestamp, completedAt: null, ...overrides, }; } function makeMessage(overrides = {}) { return { id: "msg:1", type: "message", role: "assistant", title: "Assistant", text: "Looking into that now.", timestamp: baseTimestamp, ...overrides, }; } test("getActivityHeadline formats tool actions tersely and assistant text", () => { // Tool items use the terse action tier (verb + object), not label · preview. assert.equal(getActivityHeadline(makeTool()), "Sent abc"); assert.equal( getActivityHeadline(makeMessage({ text: "First line\nSecond line" })), "First line", ); assert.equal(getActivityHeadline(makeMessage({ text: " " })), "Responding"); }); test("getActivityHeadline basenames path-like tool objects", () => { assert.equal( getActivityHeadline( makeTool({ title: "Read file", toolName: "dev__read_file", buzzToolName: null, args: { path: "src/agents/ui/foo.ts" }, descriptor: { renderClass: "file-read", label: "Read file", preview: "src/agents/ui/foo.ts", action: { verb: "Read", object: "src/agents/ui/foo.ts" }, source: "harness", groupKey: "read_file", }, }), ), "Read foo.ts", ); assert.equal( getActivityHeadline( makeTool({ title: "Edit file", toolName: "dev__str_replace", buzzToolName: null, args: { path: "desktop/src/features/channels/ui/ChannelPane.tsx" }, descriptor: { renderClass: "file-edit", label: "Edited file", preview: "desktop/src/features/channels/ui/ChannelPane.tsx", action: { verb: "Edited", object: "desktop/src/features/channels/ui/ChannelPane.tsx", }, source: "harness", groupKey: "file-edit:str_replace", }, }), ), "Edited ChannelPane.tsx", ); }); test("getActivityHeadline renders plan and thought items in past tense", () => { // Bare "Plan" / "Thinking" titles must not headline next to the past-tense // tool verbs ("Read foo.ts", "Ran …"). assert.equal( getActivityHeadline({ id: "plan:1", type: "plan", renderClass: "plan", title: "Plan", text: "1. Do the thing", timestamp: baseTimestamp, }), "Created plan", ); assert.equal( getActivityHeadline({ id: "plan:1:update:x", type: "plan", renderClass: "plan", title: "Plan updated", text: "Now doing step 2", timestamp: baseTimestamp, isUpdate: true, targetId: "plan:1", }), "Updated plan", ); assert.equal( getActivityHeadline({ id: "thought:1", type: "thought", renderClass: "thought", title: "Thinking", text: "hmm", timestamp: baseTimestamp, }), "Thought", ); assert.equal( getActivityHeadline({ id: "thought:2", type: "thought", renderClass: "thought", title: "Plan", text: "plan-shaped thought", timestamp: baseTimestamp, }), "Planned", ); }); test("getActivityHeadline keeps shell commands whole (no basenaming)", () => { assert.equal( getActivityHeadline( makeTool({ title: "Shell", toolName: "dev__shell", buzzToolName: null, args: { command: "cat src/agents/ui/foo.ts" }, descriptor: { renderClass: "shell", label: "Ran command", preview: "cat src/agents/ui/foo.ts", action: { verb: "Ran", object: "cat src/agents/ui/foo.ts" }, source: "harness", groupKey: "shell:command", }, }), ), "Ran cat src/agents/ui/foo.ts", ); }); test("isMeaningfulItem ignores lifecycle noise and raw JSON-RPC metadata", () => { assert.equal( isMeaningfulItem({ id: "life:1", type: "lifecycle", title: "Turn started", text: "", timestamp: baseTimestamp, }), false, "turn started is lifecycle noise → not meaningful", ); assert.equal( isMeaningfulItem({ id: "meta:raw", type: "metadata", renderClass: "raw-rail", title: "Raw ACP payload", sections: [], timestamp: baseTimestamp, acpSource: "raw_json_rpc", }), false, "raw_json_rpc metadata is infrastructure noise → not meaningful", ); assert.equal( isMeaningfulItem({ id: "meta:ctx", type: "metadata", renderClass: "raw-rail", title: "Prompt context", sections: [], timestamp: baseTimestamp, acpSource: "session/prompt:context", }), true, "prompt context metadata is semantic → meaningful", ); assert.equal( isMeaningfulItem({ id: "meta:sys", type: "metadata", renderClass: "raw-rail", title: "System prompt", sections: [], timestamp: baseTimestamp, }), true, "system prompt metadata (no acpSource) is semantic → meaningful", ); assert.equal( isMeaningfulItem({ id: "life:2", type: "lifecycle", title: "Turn error", text: "boom", timestamp: baseTimestamp, }), true, ); }); test("getActivityHeadline falls back to label · preview when a descriptor has no action", () => { assert.equal( getActivityHeadline( makeTool({ title: "Shell", toolName: "dev__shell", buzzToolName: null, args: { command: "buzz messages send --content hi" }, descriptor: { renderClass: "message", label: "Send Message", preview: "hi", source: "shell", groupKey: "buzz-cli:messages.send", }, }), ), "Send Message · hi", ); }); test("isMeaningfulItem ignores suppressed tools", () => { assert.equal( isMeaningfulItem( makeTool({ renderClass: "suppressed", descriptor: { renderClass: "suppressed", label: "Checked todos", preview: null, source: "harness", groupKey: "suppressed:stop-hook", }, }), ), false, ); }); const metadataSystemPrompt = { id: "meta:sys", type: "metadata", renderClass: "raw-rail", title: "System prompt", sections: [], timestamp: baseTimestamp, }; const metadataPromptContext = { id: "meta:ctx", type: "metadata", renderClass: "raw-rail", title: "Prompt context", sections: [], timestamp: baseTimestamp, acpSource: "session/prompt:context", }; test("isSpineItem excludes metadata items (reads recede)", () => { assert.equal( isSpineItem(metadataSystemPrompt), false, "system prompt metadata is not spine work", ); assert.equal( isSpineItem(metadataPromptContext), false, "prompt context metadata is not spine work", ); assert.equal(isSpineItem(makeTool()), true, "tool items are spine work"); assert.equal( isSpineItem(makeMessage()), true, "message items are spine work", ); assert.equal( isSpineItem({ id: "meta:raw", type: "metadata", renderClass: "raw-rail", title: "Raw ACP payload", sections: [], timestamp: baseTimestamp, acpSource: "raw_json_rpc", }), false, "raw_json_rpc is already filtered by isMeaningfulItem → not spine", ); }); test("isSpineItem: metadata still meaningful via isMeaningfulItem (feed visibility unchanged)", () => { // isMeaningfulItem must still return true for non-raw metadata — the feed // renders metadata items independently of isSpineItem. assert.equal(isMeaningfulItem(metadataSystemPrompt), true); assert.equal(isMeaningfulItem(metadataPromptContext), true); }); test("two-tier headline: metadata excluded when spine work is present", () => { // Simulate what BotActivityBar does: when any spine item exists, only spine // items are eligible for the headline rotation. const transcript = [metadataSystemPrompt, makeTool()]; const hasSpine = transcript.some(isSpineItem); const passFilter = hasSpine ? isSpineItem : isMeaningfulItem; const headlines = transcript .filter(passFilter) .map((item) => getActivityHeadline(item)) .filter(Boolean); assert.ok( !headlines.includes("System prompt"), "System prompt should not headline when spine work exists", ); assert.ok( headlines.some((h) => h?.includes("Sent")), "Tool headline should appear", ); }); test("two-tier headline: metadata headlines when it is the only activity (session start / idle)", () => { // When no spine items exist, fall back to isMeaningfulItem so the bar is not // empty at session start. const transcript = [metadataSystemPrompt, metadataPromptContext]; const hasSpine = transcript.some(isSpineItem); const passFilter = hasSpine ? isSpineItem : isMeaningfulItem; const headlines = transcript .filter(passFilter) .map((item) => getActivityHeadline(item)) .filter(Boolean); assert.ok( headlines.includes("System prompt"), "System prompt should headline when no spine work exists", ); assert.ok( headlines.includes("Prompt context"), "Prompt context should headline when no spine work exists", ); }); // Render-tier tests (raw_json_rpc →
, non-raw → polished accordion) live in
// activityRenderClasses/RawRailActivity.render.test.mjs — they use
// renderToStaticMarkup and would fail if the isRawPayload branch in
// RawRailActivity were removed.
test("shouldShowTranscriptRowTimestamp: off by default (enabled=false)", () => {
assert.equal(
shouldShowTranscriptRowTimestamp(makeTool(), {
enabled: false,
variant: "default",
}),
false,
);
});
test("shouldShowTranscriptRowTimestamp: enabled shows for tools, thoughts, assistant messages", () => {
const options = { enabled: true, variant: "default" };
assert.equal(shouldShowTranscriptRowTimestamp(makeTool(), options), true);
assert.equal(
shouldShowTranscriptRowTimestamp(
makeMessage({ role: "assistant" }),
options,
),
true,
);
assert.equal(
shouldShowTranscriptRowTimestamp(
{
id: "thought:1",
type: "thought",
title: "Thinking",
text: "hmm",
timestamp: baseTimestamp,
},
options,
),
true,
);
});
test("shouldShowTranscriptRowTimestamp: user message bubbles keep their own footer (excluded)", () => {
assert.equal(
shouldShowTranscriptRowTimestamp(
makeMessage({ role: "user", title: "tho" }),
{ enabled: true, variant: "default" },
),
false,
"user bubbles already render a timestamp footer",
);
});
test("shouldShowTranscriptRowTimestamp: compact preview stays dense", () => {
assert.equal(
shouldShowTranscriptRowTimestamp(makeTool(), {
enabled: true,
variant: "compactPreview",
}),
false,
);
});
test("getLatestActivityHeadline prefers latest spine work and scopes by channel", () => {
const items = [
makeMessage({
id: "msg:old",
text: "Old reply",
channelId: "chan-a",
timestamp: "2026-06-14T19:00:00.000Z",
}),
makeTool({
id: "tool:1",
channelId: "chan-a",
timestamp: "2026-06-14T19:00:10.000Z",
startedAt: "2026-06-14T19:00:10.000Z",
}),
makeMessage({
id: "msg:other",
text: "Other channel",
channelId: "chan-b",
timestamp: "2026-06-14T19:00:20.000Z",
}),
];
assert.equal(
getLatestActivityHeadline(items, "chan-a"),
"Send Message · abc",
);
assert.equal(getLatestActivityHeadline(items, "chan-b"), "Other channel");
assert.equal(getLatestActivityHeadline(items, "chan-missing"), null);
});
test("getLatestActivityHeadline returns null for empty transcripts", () => {
assert.equal(getLatestActivityHeadline([]), null);
});