mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Hide automation prompts from the chat timeline
The auto-fix-CI and address-comments nudges are sent as user messages so the agent hears them through the normal pipeline — but rendering them as the user's own bubbles broke the illusion. They now carry an ["automation", "work-panel"] tag (riding the outgoing tag path the composer already uses) and the timeline renders only their anchored activity: the agent's turn markers and reply appear with no visible prompt, so armed automation reads as ambient. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
e63099c093
commit
47b67066c1
@@ -7,6 +7,17 @@ import * as React from "react";
|
||||
const STORAGE_PREFIX = "buzz:chat-work-automation:v1";
|
||||
const STORAGE_EVENT = "buzz:chat-work-automation-changed";
|
||||
|
||||
/**
|
||||
* Tag attached to automation-generated prompts (auto-fix CI, address
|
||||
* comments). The message still reaches the agent like any user message, but
|
||||
* the chat timeline renders only its activity — not the message bubble — so
|
||||
* armed automation feels ambient instead of ventriloquized.
|
||||
*/
|
||||
export const CHAT_AUTOMATION_TAG: [string, string] = [
|
||||
"automation",
|
||||
"work-panel",
|
||||
];
|
||||
|
||||
export type ChatWorkAutomation = {
|
||||
autoFixCi: boolean;
|
||||
addressComments: boolean;
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
NO_PROJECT_SELECTION_ID,
|
||||
} from "@/features/chats/lib/chatSetup";
|
||||
import { ChatActivityTranscript } from "@/features/chats/ui/ChatActivityTranscript";
|
||||
import { CHAT_AUTOMATION_TAG } from "@/features/chats/lib/chatWorkAutomation";
|
||||
import {
|
||||
deriveBranchFromAgentMessages,
|
||||
deriveChatWorkBranch,
|
||||
@@ -562,6 +563,13 @@ export function ChatDetail({
|
||||
"chat_context",
|
||||
"source",
|
||||
);
|
||||
// Automation prompts stay invisible: the agent's
|
||||
// activity and reply anchor here, but no bubble.
|
||||
const isAutomationMessage = eventHasTag(
|
||||
message,
|
||||
CHAT_AUTOMATION_TAG[0],
|
||||
CHAT_AUTOMATION_TAG[1],
|
||||
);
|
||||
const isAgentMessage =
|
||||
defaultAgent?.pubkey != null &&
|
||||
normalizePubkey(message.pubkey) ===
|
||||
@@ -579,7 +587,7 @@ export function ChatDetail({
|
||||
)}
|
||||
messageId={message.id}
|
||||
>
|
||||
{isContextMessage ? (
|
||||
{isAutomationMessage ? null : isContextMessage ? (
|
||||
<ChatContextRow event={message} />
|
||||
) : (
|
||||
<ChatMessageRow
|
||||
@@ -676,7 +684,9 @@ export function ChatDetail({
|
||||
<ChatWorkPanel
|
||||
branch={workBranch}
|
||||
chatId={chat.id}
|
||||
onAutomationPrompt={(content) => void onSend(content, [])}
|
||||
onAutomationPrompt={(content) =>
|
||||
void onSend(content, [], [CHAT_AUTOMATION_TAG])
|
||||
}
|
||||
open={showWorkPanel}
|
||||
prHref={workPanelHref}
|
||||
projectPath={metadata?.projectPath ?? selectedProject?.path ?? null}
|
||||
|
||||
@@ -187,6 +187,37 @@ test("first message in a new chat is sent and rendered", async ({ page }) => {
|
||||
await expect(page.getByTestId("automation-auto-fix-ci")).toBeVisible();
|
||||
await expect(page.getByTestId("automation-address-comments")).toBeVisible();
|
||||
|
||||
// Arming address-comments fires the automation prompt (2 open threads in
|
||||
// the mock). The message goes out tagged — but no bubble renders: the
|
||||
// automation stays invisible in the timeline.
|
||||
await page.getByTestId("automation-address-comments").click();
|
||||
await expect
|
||||
.poll(() =>
|
||||
page.evaluate(() =>
|
||||
(
|
||||
(
|
||||
window as Window & {
|
||||
__BUZZ_E2E_COMMAND_PAYLOADS__?: Array<{
|
||||
command: string;
|
||||
payload?: { content?: string; mediaTags?: string[][] };
|
||||
}>;
|
||||
}
|
||||
).__BUZZ_E2E_COMMAND_PAYLOADS__ ?? []
|
||||
).some(
|
||||
(entry) =>
|
||||
entry.command === "send_channel_message" &&
|
||||
entry.payload?.content?.includes("unanswered review comments") &&
|
||||
entry.payload?.mediaTags?.some(
|
||||
(tag) => tag[0] === "automation" && tag[1] === "work-panel",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toBe(true);
|
||||
await expect(
|
||||
page.getByLabel("Chat messages").getByText("unanswered review comments"),
|
||||
).toHaveCount(0);
|
||||
|
||||
// The header's PR button toggles the panel.
|
||||
await page.getByTestId("toggle-work-panel").click();
|
||||
await expect(workPanel).not.toBeVisible();
|
||||
|
||||
Reference in New Issue
Block a user