Files
buzz/desktop/src/features/agents/ui/agentSessionTranscriptPresentation.test.mjs
Taylor Ho 617a4ab4ff feat(sidebar): show per-agent activity in channel popover
Integrate joelbrilliant’s channel activity popover work on top of the composer live-activity branch, preserving per-agent elapsed ages, channel-scoped observer headlines, and activity-panel click-through.

Co-authored-by: joelbrilliant <joelbrilliant1@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-05 17:43:43 -07:00

467 lines
12 KiB
JavaScript

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 → <pre>, 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);
});