mirror of
https://github.com/block/buzz.git
synced 2026-11-02 15:31:27 +00:00
Two-layer prod-safe gate for the acpToolSummaries experiment, default OFF:
UI gate: buildCompactToolSummary now takes summaryTitleEnabled (default
off) and only consults the agent-provided friendly phrase when the
experiment is on. ToolItem and BotActivityBar/getActivityHeadline read
useFeatureEnabled('acpToolSummaries') and thread the flag through.
Failure-precedence behavior is unchanged: failed rows always paint the
failure label regardless of the gate.
Runtime/cost gate: the frontend mirrors preview-experiment overrides to
experiments.json via the new set_desktop_experiments command (AppShell
mirrors on boot and on every toggle); spawn_agent_child sets
BUZZ_AGENT_NO_TOOL_SUMMARY=1 when the experiment is off so disabled
agents never spend the async LLM summary call. All spawn paths (start,
create, app-startup restore) funnel through spawn_agent_child, and
missing/unknown mirror state resolves to off — restore-time respawns
before the webview loads stay on the safe side. Experiment-on leaves
the env untouched, so a user-provided kill switch still wins.
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
331 lines
8.7 KiB
JavaScript
331 lines
8.7 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
getActivityHeadline,
|
|
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 titles and assistant text", () => {
|
|
assert.equal(getActivityHeadline(makeTool()), "Send Message · abc");
|
|
assert.equal(
|
|
getActivityHeadline(makeMessage({ text: "First line\nSecond line" })),
|
|
"First line",
|
|
);
|
|
assert.equal(getActivityHeadline(makeMessage({ text: " " })), "Responding");
|
|
});
|
|
|
|
test("getActivityHeadline gates the friendly summaryTitle on the experiment", () => {
|
|
const tool = makeTool({ summaryTitle: "sending a status update" });
|
|
|
|
// Off (default): raw tool label, friendly phrase never consulted.
|
|
assert.equal(getActivityHeadline(tool), "Send Message · abc");
|
|
assert.equal(
|
|
getActivityHeadline(tool, { summaryTitleEnabled: false }),
|
|
"Send Message · abc",
|
|
);
|
|
// On: friendly phrase wins the headline.
|
|
assert.equal(
|
|
getActivityHeadline(tool, { summaryTitleEnabled: true }),
|
|
"sending a status update · abc",
|
|
);
|
|
});
|
|
|
|
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 uses semantic tool descriptors", () => {
|
|
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("Send Message")),
|
|
"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,
|
|
);
|
|
});
|