From a05b76cd9bd580c3c7b97a7f5318eb16f607af61 Mon Sep 17 00:00:00 2001 From: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz> Date: Mon, 27 Jul 2026 23:23:49 -0700 Subject: [PATCH 1/2] feat(desktop): identify agent in activity header Co-authored-by: Taylor Ho Signed-off-by: Taylor Ho --- .../channels/ui/AgentSessionThreadPanel.tsx | 46 +++++++++++++------ .../activity-scope-label-screenshots.spec.ts | 39 ++++++++++++++-- 2 files changed, 67 insertions(+), 18 deletions(-) diff --git a/desktop/src/features/channels/ui/AgentSessionThreadPanel.tsx b/desktop/src/features/channels/ui/AgentSessionThreadPanel.tsx index a907f87245..2c3a60927f 100644 --- a/desktop/src/features/channels/ui/AgentSessionThreadPanel.tsx +++ b/desktop/src/features/channels/ui/AgentSessionThreadPanel.tsx @@ -35,10 +35,12 @@ import { AuxiliaryPanelHeader, AuxiliaryPanelHeaderActions, AuxiliaryPanelHeaderGroup, - AuxiliaryPanelHeaderTitleBlock, } from "@/shared/layout/AuxiliaryPanel"; import { Button } from "@/shared/ui/button"; import type { UserProfileLookup } from "@/features/profile/lib/identity"; +import { resolveUserLabel } from "@/features/profile/lib/identity"; +import { ProfileAvatar } from "@/features/profile/ui/ProfileAvatar"; +import { normalizePubkey } from "@/shared/lib/pubkey"; import { DropdownMenu, DropdownMenuContent, @@ -237,6 +239,15 @@ export function AgentSessionThreadPanel({ ? `#${scopeChannelName}` : "1 channel" : "All channels"; + const agentProfile = profiles?.[normalizePubkey(agent.pubkey)] ?? null; + const agentLabel = resolveUserLabel({ + pubkey: agent.pubkey, + fallbackName: agent.name, + profiles, + preferResolvedSelfLabel: true, + }); + const viewLabel = showRawFeed ? "Raw ACP activity" : "Activity"; + const headerMetadata = `${viewLabel} · ${scopeLabel} · ${lastUpdatedLabel}`; const animateActivity = useTranscriptAnimationEnabled(); const showTimestamps = useTranscriptTimestampsEnabled(); async function handleInterruptTurn() { @@ -417,19 +428,28 @@ export function AgentSessionThreadPanel({ backButtonTestId="agent-session-back" onBack={onBack} > - - {/* Scope label: makes channel-targeted vs all-channels state obvious - (an all-channels pane can look "wrong" without it). */} - - {scopeLabel} - +
+

+ {agentLabel} +

+

+ {headerMetadata} +

+
{agentHeaderActions} diff --git a/desktop/tests/e2e/activity-scope-label-screenshots.spec.ts b/desktop/tests/e2e/activity-scope-label-screenshots.spec.ts index 0fee5ebf9d..7cd0900ae2 100644 --- a/desktop/tests/e2e/activity-scope-label-screenshots.spec.ts +++ b/desktop/tests/e2e/activity-scope-label-screenshots.spec.ts @@ -6,6 +6,8 @@ import { installMockBridge, TEST_IDENTITIES } from "../helpers/bridge"; const SHOTS = "test-results/activity-scope-label"; const AGENT_PUBKEY = TEST_IDENTITIES.tyler.pubkey; +const LONG_AGENT_NAME = + "Observer Agent With An Exceptionally Long Display Name"; const AGENTS_CHANNEL_ID = "94a444a4-c0a3-5966-ab05-530c6ddc2301"; // #agents // Open the activity pane via profile → "View activity" (same ingress the @@ -57,9 +59,20 @@ test.describe("activity panel scope label", () => { "channel-agents", "agents", ); - await expect(page.getByTestId("agent-session-scope-label")).toHaveText( - "#agents", + await expect(page.getByTestId("agent-session-agent-name")).toHaveText( + "Observer Agent", ); + await expect(page.getByTestId("agent-session-agent-avatar")).toBeVisible(); + await expect(page.getByTestId("agent-session-scope-label")).toContainText( + "Activity · #agents · No updates yet", + ); + + await page.getByTestId("agent-session-settings-menu-trigger").click(); + await page.getByTestId("agent-session-toggle-raw-feed").click(); + await expect(page.getByTestId("agent-session-scope-label")).toContainText( + "Raw ACP activity · #agents · No updates yet", + ); + await page.keyboard.press("Escape"); await waitForAnimations(page); await panel.screenshot({ path: `${SHOTS}/01-channel-scoped.png` }); @@ -75,11 +88,18 @@ test.describe("activity panel scope label", () => { managedAgents: [ { pubkey: AGENT_PUBKEY, - name: "Observer Agent", + name: LONG_AGENT_NAME, status: "running" as const, channelNames: ["random"], }, ], + searchProfiles: [ + { + pubkey: AGENT_PUBKEY, + displayName: LONG_AGENT_NAME, + isAgent: true, + }, + ], }); await page.goto( @@ -90,8 +110,17 @@ test.describe("activity panel scope label", () => { const panel = page.getByTestId("agent-session-thread-panel"); await expect(panel).toBeVisible({ timeout: 10_000 }); - await expect(page.getByTestId("agent-session-scope-label")).toHaveText( - "All channels", + await expect(page.getByTestId("agent-session-agent-name")).toHaveText( + LONG_AGENT_NAME, + ); + const agentName = page.getByTestId("agent-session-agent-name"); + expect( + await agentName.evaluate((element) => element.scrollWidth), + ).toBeGreaterThan( + await agentName.evaluate((element) => element.clientWidth), + ); + await expect(page.getByTestId("agent-session-scope-label")).toContainText( + "Activity · All channels · No updates yet", ); await waitForAnimations(page); From bb1c706eb7fa903ab801a5be128f99e1dd7c22e6 Mon Sep 17 00:00:00 2001 From: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz> Date: Tue, 28 Jul 2026 07:15:21 -0700 Subject: [PATCH 2/2] fix(desktop): keep activity recency visible Co-authored-by: Taylor Ho Signed-off-by: Taylor Ho --- .../channels/ui/AgentSessionThreadPanel.tsx | 27 +++++++--- .../activity-scope-label-screenshots.spec.ts | 50 ++++++++++++++++--- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/desktop/src/features/channels/ui/AgentSessionThreadPanel.tsx b/desktop/src/features/channels/ui/AgentSessionThreadPanel.tsx index 2c3a60927f..641b81490b 100644 --- a/desktop/src/features/channels/ui/AgentSessionThreadPanel.tsx +++ b/desktop/src/features/channels/ui/AgentSessionThreadPanel.tsx @@ -247,7 +247,7 @@ export function AgentSessionThreadPanel({ preferResolvedSelfLabel: true, }); const viewLabel = showRawFeed ? "Raw ACP activity" : "Activity"; - const headerMetadata = `${viewLabel} · ${scopeLabel} · ${lastUpdatedLabel}`; + const headerScopeLabel = `${viewLabel} · ${scopeLabel}`; const animateActivity = useTranscriptAnimationEnabled(); const showTimestamps = useTranscriptTimestampsEnabled(); async function handleInterruptTurn() { @@ -442,13 +442,24 @@ export function AgentSessionThreadPanel({ > {agentLabel} -

- {headerMetadata} -

+
+

+ {headerScopeLabel} +

+ + + {lastUpdatedLabel} + +
{agentHeaderActions} diff --git a/desktop/tests/e2e/activity-scope-label-screenshots.spec.ts b/desktop/tests/e2e/activity-scope-label-screenshots.spec.ts index 7cd0900ae2..4ed0a211e5 100644 --- a/desktop/tests/e2e/activity-scope-label-screenshots.spec.ts +++ b/desktop/tests/e2e/activity-scope-label-screenshots.spec.ts @@ -63,15 +63,31 @@ test.describe("activity panel scope label", () => { "Observer Agent", ); await expect(page.getByTestId("agent-session-agent-avatar")).toBeVisible(); - await expect(page.getByTestId("agent-session-scope-label")).toContainText( - "Activity · #agents · No updates yet", - ); + const scope = page.getByTestId("agent-session-scope-label"); + await expect(scope).toHaveText("Activity · #agents"); + const recency = page.getByTestId("agent-session-recency-label"); + await expect(recency).toHaveText("No updates yet"); + await expect(recency).toBeVisible(); + + // Simulate long-scope pressure deterministically: scope owns truncation + // while the independently shrinking recency stays visible. + await scope.evaluate((element) => { + element.style.width = "5rem"; + element.style.flex = "none"; + }); + expect( + await scope.evaluate((element) => element.scrollWidth), + ).toBeGreaterThan(await scope.evaluate((element) => element.clientWidth)); + await expect(recency).toBeVisible(); await page.getByTestId("agent-session-settings-menu-trigger").click(); await page.getByTestId("agent-session-toggle-raw-feed").click(); - await expect(page.getByTestId("agent-session-scope-label")).toContainText( - "Raw ACP activity · #agents · No updates yet", - ); + await expect(scope).toHaveText("Raw ACP activity · #agents"); + expect( + await scope.evaluate((element) => element.scrollWidth), + ).toBeGreaterThan(await scope.evaluate((element) => element.clientWidth)); + await expect(recency).toHaveText("No updates yet"); + await expect(recency).toBeVisible(); await page.keyboard.press("Escape"); await waitForAnimations(page); @@ -119,10 +135,28 @@ test.describe("activity panel scope label", () => { ).toBeGreaterThan( await agentName.evaluate((element) => element.clientWidth), ); - await expect(page.getByTestId("agent-session-scope-label")).toContainText( - "Activity · All channels · No updates yet", + const scope = page.getByTestId("agent-session-scope-label"); + await expect(scope).toHaveText("Activity · All channels"); + const recency = page.getByTestId("agent-session-recency-label"); + await expect(recency).toHaveText("No updates yet"); + await expect(recency).toBeVisible(); + + await page.setViewportSize({ width: 720, height: 700 }); + await expect(scope).toBeVisible(); + await expect(recency).toBeVisible(); + const recencyWidth = await recency.evaluate( + (element) => element.clientWidth, ); + await page.getByTestId("agent-session-settings-menu-trigger").click(); + await page.getByTestId("agent-session-toggle-raw-feed").click(); + await expect(scope).toHaveText("Raw ACP activity · All channels"); + await expect(recency).toBeVisible(); + expect(await recency.evaluate((element) => element.clientWidth)).toBe( + recencyWidth, + ); + await page.keyboard.press("Escape"); + await waitForAnimations(page); await panel.screenshot({ path: `${SHOTS}/02-all-channels.png` }); });