mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(agents): remove activity transcript now summary
- Remove the sticky Now summary card from AgentSessionTranscriptList so transcript rows no longer scroll under a pinned status element - Drop summary-only helpers, Shimmer usage, and icon imports that only supported the removed card - Remove the showInterventionHint prop plumbing from ManagedAgentSessionPanel and AgentSessionThreadPanel after the summary hint was deleted - Update the channel activity E2E expectation to assert the removed summary no longer renders
This commit is contained in:
@@ -1,15 +1,12 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
AlertCircle,
|
||||
Bot,
|
||||
Brain,
|
||||
CheckCheck,
|
||||
ChevronDown,
|
||||
CircleDot,
|
||||
Loader2,
|
||||
Radio,
|
||||
TerminalSquare,
|
||||
Wrench,
|
||||
} from "lucide-react";
|
||||
|
||||
import {
|
||||
@@ -20,7 +17,6 @@ import { cn } from "@/shared/lib/cn";
|
||||
import { normalizePubkey } from "@/shared/lib/pubkey";
|
||||
import { Badge } from "@/shared/ui/badge";
|
||||
import { Markdown } from "@/shared/ui/markdown";
|
||||
import { Shimmer } from "@/shared/ui/Shimmer";
|
||||
import { Toggle } from "@/shared/ui/toggle";
|
||||
import { UserAvatar } from "@/shared/ui/UserAvatar";
|
||||
import type { PromptSection, TranscriptItem } from "./agentSessionTypes";
|
||||
@@ -55,14 +51,12 @@ export function AgentSessionTranscriptList({
|
||||
isWorking = false,
|
||||
items,
|
||||
profiles,
|
||||
showInterventionHint = false,
|
||||
}: AgentTranscriptIdentityProps & {
|
||||
compact?: boolean;
|
||||
emptyDescription: string;
|
||||
isWorking?: boolean;
|
||||
items: TranscriptItem[];
|
||||
profiles?: UserProfileLookup;
|
||||
showInterventionHint?: boolean;
|
||||
}) {
|
||||
const presentation = React.useMemo(
|
||||
() => buildTranscriptPresentation(items, isWorking),
|
||||
@@ -90,13 +84,6 @@ export function AgentSessionTranscriptList({
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<TranscriptNowSummary
|
||||
agentName={agentName}
|
||||
compact={compact}
|
||||
isWorking={isWorking}
|
||||
presentation={presentation}
|
||||
showInterventionHint={showInterventionHint}
|
||||
/>
|
||||
<div
|
||||
aria-label="Live ACP transcript"
|
||||
aria-live="polite"
|
||||
@@ -132,202 +119,6 @@ function TranscriptAcpSourceBadge({ source }: { source: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
function TranscriptNowSummary({
|
||||
agentName,
|
||||
compact,
|
||||
isWorking,
|
||||
presentation,
|
||||
showInterventionHint,
|
||||
}: {
|
||||
agentName: string;
|
||||
compact: boolean;
|
||||
isWorking: boolean;
|
||||
presentation: ReturnType<typeof buildTranscriptPresentation>;
|
||||
showInterventionHint: boolean;
|
||||
}) {
|
||||
const { counts, hasError, headline, lastUpdatedAt, state } = presentation;
|
||||
const showSummary = isWorking || hasError || itemsHaveActivity(counts);
|
||||
|
||||
if (!showSummary) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const StateIcon = getStateIcon(state, isWorking);
|
||||
const statusLabel = getStateLabel(state, isWorking);
|
||||
const lastUpdated = lastUpdatedAt
|
||||
? formatTranscriptTime(lastUpdatedAt)
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"sticky top-0 z-10 mb-3 rounded-lg border bg-background/95 backdrop-blur-sm",
|
||||
hasError
|
||||
? "border-destructive/30 bg-destructive/[0.04]"
|
||||
: "border-border/70",
|
||||
compact ? "px-2.5 py-2" : "px-3 py-2.5",
|
||||
)}
|
||||
data-testid="agent-transcript-now-summary"
|
||||
>
|
||||
<div className="flex items-start gap-2">
|
||||
<span
|
||||
className={cn(
|
||||
"mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full",
|
||||
hasError
|
||||
? "bg-destructive/10 text-destructive"
|
||||
: isWorking
|
||||
? "bg-primary/10 text-primary"
|
||||
: "bg-muted text-muted-foreground",
|
||||
)}
|
||||
>
|
||||
<StateIcon
|
||||
className={cn(
|
||||
"h-3 w-3",
|
||||
isWorking &&
|
||||
state !== "error" &&
|
||||
state !== "idle" &&
|
||||
"animate-pulse",
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex flex-wrap items-center gap-x-2 gap-y-0.5">
|
||||
<p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
|
||||
Now
|
||||
</p>
|
||||
<span className="text-xs text-muted-foreground/70">·</span>
|
||||
<p className="text-xs text-muted-foreground">{agentName}</p>
|
||||
{lastUpdated ? (
|
||||
<>
|
||||
<span className="text-xs text-muted-foreground/70">·</span>
|
||||
<p className="text-xs text-muted-foreground/70">
|
||||
{lastUpdated}
|
||||
</p>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
<p
|
||||
className={cn(
|
||||
"mt-0.5 text-sm font-medium leading-snug",
|
||||
hasError ? "text-destructive" : "text-foreground",
|
||||
)}
|
||||
>
|
||||
{isWorking && state !== "idle" && state !== "error" ? (
|
||||
<Shimmer>{headline}</Shimmer>
|
||||
) : (
|
||||
headline
|
||||
)}
|
||||
</p>
|
||||
<div className="mt-1.5 flex flex-wrap items-center gap-1.5">
|
||||
<Badge
|
||||
className="h-5 px-1.5 text-xs font-normal"
|
||||
variant={
|
||||
hasError ? "destructive" : isWorking ? "default" : "secondary"
|
||||
}
|
||||
>
|
||||
{statusLabel}
|
||||
</Badge>
|
||||
{counts.tools > 0 ? (
|
||||
<ActivityCountBadge
|
||||
count={counts.tools}
|
||||
label="tool"
|
||||
tone={counts.toolErrors > 0 ? "error" : "default"}
|
||||
/>
|
||||
) : null}
|
||||
{counts.thoughts > 0 ? (
|
||||
<ActivityCountBadge count={counts.thoughts} label="thought" />
|
||||
) : null}
|
||||
{counts.messages > 0 ? (
|
||||
<ActivityCountBadge count={counts.messages} label="message" />
|
||||
) : null}
|
||||
</div>
|
||||
{showInterventionHint && isWorking ? (
|
||||
<p className="mt-2 text-xs leading-relaxed text-muted-foreground">
|
||||
Use <span className="font-medium text-foreground">Stop</span>{" "}
|
||||
above to interrupt this turn without stopping the agent process.
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ActivityCountBadge({
|
||||
count,
|
||||
label,
|
||||
tone = "default",
|
||||
}: {
|
||||
count: number;
|
||||
label: string;
|
||||
tone?: "default" | "error";
|
||||
}) {
|
||||
return (
|
||||
<Badge
|
||||
className="h-5 px-1.5 text-xs font-normal"
|
||||
variant={tone === "error" ? "destructive" : "outline"}
|
||||
>
|
||||
{count} {label}
|
||||
{count === 1 ? "" : "s"}
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
|
||||
function itemsHaveActivity(
|
||||
counts: ReturnType<typeof buildTranscriptPresentation>["counts"],
|
||||
) {
|
||||
return (
|
||||
counts.tools > 0 ||
|
||||
counts.thoughts > 0 ||
|
||||
counts.messages > 0 ||
|
||||
counts.lifecycle > 0
|
||||
);
|
||||
}
|
||||
|
||||
function getStateIcon(
|
||||
state: ReturnType<typeof buildTranscriptPresentation>["state"],
|
||||
isWorking: boolean,
|
||||
) {
|
||||
if (state === "error") {
|
||||
return AlertCircle;
|
||||
}
|
||||
if (!isWorking) {
|
||||
return CircleDot;
|
||||
}
|
||||
switch (state) {
|
||||
case "tool_running":
|
||||
return Wrench;
|
||||
case "thinking":
|
||||
return Brain;
|
||||
case "responding":
|
||||
return Bot;
|
||||
default:
|
||||
return Loader2;
|
||||
}
|
||||
}
|
||||
|
||||
function getStateLabel(
|
||||
state: ReturnType<typeof buildTranscriptPresentation>["state"],
|
||||
isWorking: boolean,
|
||||
) {
|
||||
if (state === "error") {
|
||||
return "Error";
|
||||
}
|
||||
if (!isWorking) {
|
||||
return "Idle";
|
||||
}
|
||||
switch (state) {
|
||||
case "tool_running":
|
||||
return "Running tool";
|
||||
case "thinking":
|
||||
return "Thinking";
|
||||
case "responding":
|
||||
return "Responding";
|
||||
default:
|
||||
return "Working";
|
||||
}
|
||||
}
|
||||
|
||||
function getDisplayBlockKey(block: TranscriptDisplayBlock) {
|
||||
if (block.kind === "single") {
|
||||
return block.item.id;
|
||||
|
||||
@@ -35,7 +35,6 @@ type ManagedAgentSessionPanelProps = {
|
||||
isWorking?: boolean;
|
||||
rawLayout?: "responsive" | "exclusive";
|
||||
showHeader?: boolean;
|
||||
showInterventionHint?: boolean;
|
||||
showRaw?: boolean;
|
||||
profiles?: UserProfileLookup;
|
||||
};
|
||||
@@ -49,7 +48,6 @@ export function ManagedAgentSessionPanel({
|
||||
isWorking = false,
|
||||
rawLayout = "responsive",
|
||||
showHeader = true,
|
||||
showInterventionHint = false,
|
||||
showRaw = true,
|
||||
profiles,
|
||||
}: ManagedAgentSessionPanelProps) {
|
||||
@@ -115,7 +113,6 @@ export function ManagedAgentSessionPanel({
|
||||
isWorking={isWorking}
|
||||
profiles={profiles}
|
||||
rawLayout={rawLayout}
|
||||
showInterventionHint={showInterventionHint}
|
||||
showRaw={showRaw}
|
||||
transcript={scopedTranscript}
|
||||
/>
|
||||
@@ -171,7 +168,6 @@ function SessionBody({
|
||||
isWorking,
|
||||
profiles,
|
||||
rawLayout,
|
||||
showInterventionHint,
|
||||
showRaw,
|
||||
transcript,
|
||||
}: {
|
||||
@@ -187,7 +183,6 @@ function SessionBody({
|
||||
isWorking: boolean;
|
||||
profiles?: UserProfileLookup;
|
||||
rawLayout: "responsive" | "exclusive";
|
||||
showInterventionHint: boolean;
|
||||
showRaw: boolean;
|
||||
transcript: TranscriptItem[];
|
||||
}) {
|
||||
@@ -229,7 +224,6 @@ function SessionBody({
|
||||
isWorking={isWorking}
|
||||
items={transcript}
|
||||
profiles={profiles}
|
||||
showInterventionHint={showInterventionHint}
|
||||
/>
|
||||
{showRaw && rawLayout === "responsive" ? (
|
||||
<RawEventRail events={events} />
|
||||
|
||||
@@ -206,7 +206,6 @@ export function AgentSessionThreadPanel({
|
||||
profiles={profiles}
|
||||
rawLayout="exclusive"
|
||||
showHeader={false}
|
||||
showInterventionHint={canInterruptTurn}
|
||||
showRaw={showRawFeed}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -773,10 +773,7 @@ test("shows and clears activity indicators for active channel agents", async ({
|
||||
await expect(page.getByTestId("agent-session-thread-panel")).toContainText(
|
||||
"alice",
|
||||
);
|
||||
await expect(page.getByTestId("agent-transcript-now-summary")).toBeVisible();
|
||||
await expect(page.getByTestId("agent-transcript-now-summary")).toContainText(
|
||||
"Working",
|
||||
);
|
||||
await expect(page.getByTestId("agent-transcript-now-summary")).toHaveCount(0);
|
||||
await expect(page.getByTestId("agent-session-stop-turn")).toBeVisible();
|
||||
await expect(page.getByTestId("agent-session-stop-turn")).toBeDisabled();
|
||||
await expect(page.getByTestId("agent-session-thread-panel")).toContainText(
|
||||
|
||||
Reference in New Issue
Block a user