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:
Taylor Ho
2026-06-15 15:59:28 -07:00
parent faefae6af5
commit 2d7fae0ab8
4 changed files with 1 additions and 220 deletions
@@ -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>
+1 -4
View File
@@ -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(