feat(profile): embed live activity feed in profile aux panel#1380
Conversation
62606eb to
618f550
Compare
36b91b0 to
be9f530
Compare
7ab64c8 to
9aba17c
Compare
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Synthesize a minimal profile activity agent for declared-owned relay agents so observer and active-turn bridges track the same pubkey. - Relax the profile live activity embed to accept the shared activity-agent shape instead of requiring a full local managed-agent record. - Extract the activity-agent resolver from the oversized profile panel to keep desktop file-size guards intact. - Add an E2E regression covering a viewer-owned relay-only agent switching from the static activity row to the live activity embed. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Derive profile embed scope from observer feed data so the pane stays mounted after turn_completed, matching full activity panel behavior without changing active-turn store semantics for working badges. - Add profileActivityFeedScope helper subscribing to observer + active-turn stores - Render embed when feed has content, not only during live turns - Switch header to "Recent activity" and drop elapsed timer after completion - Export syncAgentObserverEvents for test harness replay - Extend E2E seed helper with turn_completed and regression coverage Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Turn the embedded profile activity preview into a full-card ingress that opens the full activity feed scoped to the currently selected channel. - Replace the explicit open-full label with a flattened accent pill that displays friendly last-live relative time such as "Just now", "1m ago", and "1h ago". - Track latest activity timestamps per channel so persisted and live previews can render accurate last-live labels. - Disable embedded transcript row pointer events and auto-tail the compact transcript so preview clicks route to the activity feed while new turns stay visible. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Tighten the embedded activity preview so auto-tailed transcripts use a real flex height chain and include scrollable bottom breathing room. - Flatten compact preview message rendering by adding data-role hooks for assistant and user message shells, avatars, and bubbles. - Scope compact preview typography and line-height overrides so embedded activity rows read denser without changing the full activity feed. - Restyle the preview surface with a muted fill, top and bottom gradient overlays, a Latest Activity footer label, and a floating last-live pill. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Adjust the compact activity preview edge fades so the top fade is shorter and the bottom label fade has more vertical coverage. - Keep the Latest Activity label inside the non-interactive overlay while preserving the muted preview treatment. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Remove Markdown compact/tight variants so Markdown inherits font sizing and line height from its rendering container. - Add an explicit compact transcript variant for the profile activity preview instead of relying on deep selector overrides. - Render agent sent-message previews through Markdown so formatting is consistent with other transcript messages. - Keep compact preview text small while preserving the full activity feed's normal chat bubble layout. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Remove the visible assistant avatar, name, and timestamp header from activity feed message rows so agent output no longer reads like a chat-authored message. - Move assistant message timestamps to the message body hover title, matching the timestamp tooltip pattern used by other activity rows. - Increase transcript row spacing to `gap-4` across top-level rows and turn groups for a less cramped feed. - Apply `leading-5` to non-compact agent activity markdown renderers while preserving the compact profile preview at `text-xs leading-4`. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Restyle runtime activity user messages as transparent bordered cards and agent sent-message cards as muted bubbles. - Add overflow-aware max-height clamping with matching bottom fades for clipped transcript cards. - Open source channel messages when clicking non-compact transcript bubbles that have message links. - Make non-compact user and agent avatars open the matching profile panel while keeping compact preview avatars passive. - Pass the agent pubkey through compact message summaries so avatar profile navigation can target the right agent. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Increase the profile live activity embed from h-48 to h-56 so the compact transcript preview shows another h-8 of content. - Use tighter compact-preview transcript spacing for top-level rows and turn groups while preserving the full activity feed spacing. - Keep the existing preview ingress overlay and auto-tail behavior unchanged so clicks still open the full activity feed. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Show the active channel name under the Latest Activity label when the embedded activity preview is channel-scoped. - Increase the bottom gradient overlay from h-20 to h-28 so both overlay text lines remain readable over transcript content. - Preserve the existing preview click behavior and channel switcher state while adding the scoped label. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Increase the Latest Activity overlay label to text-base and the scoped channel label to text-sm for better readability. - Expand the lower gradient overlay from h-28 to h-36 so the larger two-line label has enough contrast over transcript content. - Remove the top gradient overlay so the compact activity preview content remains unobscured above the footer label. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Replace the profile activity channel chip row with an Embla carousel that switches channel previews inside the clipped embed card, with progress dots and a fixed overlay that updates from the active slide index. - Add shadcn-style Carousel wrapper and embla-carousel-react dependency - Refactor ProfileLiveActivityEmbed to one slide per channel with lazy-mounted ManagedAgentSessionPanel instances (data-mounted on each slide) - Keep overlay gradient, Latest Activity label, channel name, and dots static while only slide content translates within the rounded frame - Update channels E2E for current labels and add multi-channel dot switching coverage including lazy-mount assertions Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Make compact activity feed typography consistently use compact text sizing across tool rows, sent-message previews, todo summaries, and shared activity row labels. - Avoid conflicting `text-sm` and `text-xs` classes in compact message containers so compact sizing wins reliably. - Remove the top overlay fade from the profile activity card and strengthen the bottom fade for better label and carousel-dot readability. - Preserve the refined carousel dot hit targets and compact activity label treatment in the profile preview card. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Only render pagination when two or more channel slides exist, and update the single-channel profile activity E2E to assert dots stay hidden. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Make expandable activity row summaries full-width instead of shrink-wrapped so grouped labels stay aligned to the left edge in compact profile previews. - Preserve the existing row spacing, chevron behavior, and open-state coloring while preventing centered-looking group labels such as `Ran 4 commands`. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Add a loading empty state for agent transcripts so active profile activity embeds show a spinner while waiting for ACP events to arrive. - Pass the live pending state from the profile activity feed into the managed session panel with copy that sets expectations for incoming events. - Move compact embed vertical padding from the panel wrapper to the transcript scroll container so transcript content can scroll and clip against the card bounds correctly. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Move compact activity embed vertical padding from the transcript scroll wrapper to the inner transcript content container so rows scroll and clip against the card bounds correctly. - Rename the managed session panel hook from scroll-container styling to transcript-content styling to match where the padding is applied. - Allow the profile embed to disable the managed session panel's default wrapper padding while preserving its horizontal inset. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Remove the live working-channel badge from the profile panel summary now that the live indicator window owns that status surface. - Keep active turn state wired into the profile activity tab so live feed scoping continues to work. - Drop the now-unused profile panel navigation, elapsed-time, and ticker helpers that only supported the old summary pill. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- ShellCommandBlock.tsx: wrap stdout output in ScrollFadeMonoPanel (was a plain overflow pre with no fade affordances) so both the command input and output get top/bottom fade gradients - Reduce max height of both panels from max-h-64 (256px) to max-h-36 (144px) - Switch terminal icon from text-accent to text-primary - Solidify panel background (bg-muted/40 -> bg-muted) to match full-opacity from-muted fades, and add overflow-hidden so the rectangular fade overlays no longer paint over the rounded corners - FileContentBlock.tsx: fix ScrollFadeMonoPanel overflow clamp - max-height lived on the outer wrapper while the scroller used h-full, which cannot resolve against a max-height-only parent, so content bled past the cap; the max-height class now sits on the overflow-auto element itself - Move horizontal padding (px-3) into the scroll content so the scrollbar affixes to the panel's right edge instead of floating 12px inside it - Bump fade default to from-muted and modernize gradient utilities to Tailwind 4 bg-linear-to-* syntax Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Move overflow scrolling from the pre element to a flex child wrapper so the scroll area respects max-height within the column layout - Pin the footer with shrink-0 and matching background so path/range text stays below the code block instead of painting over the last lines Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Add skill-read render class and classify load_skill by tool name - Build skill body into FileReadContent with SKILL.md footer labels - Reuse FileContentBlock in expanded tool detail instead of Parameters/Result JSON - Group consecutive skill loads as "Read N skills" in transcript summaries Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Vendor BuzzLogoAnimation from buzz-website into desktop/src/shared/ui/buzz-logo - Add FuzzyLogo wrapper with fuzz prop to disable CPU-heavy feTurbulence filter - Add buzz-logo--compact sizing (1.75rem) for embedded non-fullscreen usage - Add TurnLivenessIndicator shown at transcript bottom while turn is active - Wire useActiveAgentTurns + channelId through AgentSessionTranscriptList - Replace loading-state Spinner with compact FuzzyLogo in transcript empty state Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Give the individual ToolItem <summary> the same `min-h-6` (24px)
baseline as ActivityRow's grouped summary rows ("Ran N commands"),
which were ~3-4px taller because ungrouped tool rows collapsed to
the text-sm line height (~20px)
- Switch from inline-flex to flex to match ActivityRow's summary layout
- Drop the `presentation === "inline"` conditional — the "message"
presentation returns early above, so the branch was always true
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Add loopRestSeconds prop to BuzzLogoAnimation: stretches the SMIL loop period to morph + rest, packing the morph keyframes into the start of the cycle at native speed via scaleVariant - Add RestWindowFade group opacity animation that hides the mark during the rest window (quick 0.15s fade after the morph completes) - Forward loopRestSeconds through FuzzyLogo; skip the CSS pulse when a rest window is active so the two opacity animations don't fight - TurnLivenessIndicator: 2s rest between plays, dimmed to 25% opacity with foreground ink - Shrink compact logo size from 1.75rem to 1.5rem Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
The rebased branch pulls the shared markdown graph into unit-tested
components (CompactMessageSummary now renders Markdown), which drags in
emoji-mart transitively. Node's ESM resolver then fails two ways the
app bundler does not:
- @emoji-mart/data's json entrypoint needs 'with { type: "json" }' on
every import hop; serve .json from the loader instead
- emoji-mart's bundled CJS main defeats cjs-module-lexer named-export
detection, so 'import { init }' throws; serve inert ESM stubs for
emoji-mart and @emoji-mart/react since tests never open the picker
Fixes RawRailActivity.render.test.mjs (and the full suite) on the
rebased branch; main was unaffected because nothing under test reached
markdown.tsx before.
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
…toggle - AgentSessionTranscriptList.tsx: wrap each transcript display block in a motion/react motion.div — new blocks fade in and slide up 12px, and layout="position" springs rows to their new position when blocks regroup. content-visibility-auto moved to a non-animated inner child so motion's layout measurements never force skipped offscreen rows to render, keeping the CSS virtualization intact. Rows mounted on initial history load skip the enter animation via a first-render ref. Compact preview row gap tightened from gap-2 to gap-1. - transcriptAnimationPreference.ts (new): localStorage-backed useSyncExternalStore preference (buzz:animate-transcript-activity, default on) shared across all transcript surfaces; device-level UI preference, intentionally not workspace-scoped. - AgentSessionThreadPanel.tsx: add "Show Animations" Switch row to the activity settings cog menu; disabled while the raw feed is on since raw rows don't animate in. Convert the existing Raw feed toggle from DropdownMenuCheckboxItem to a matching Switch row; both rows toggle via onSelect with preventDefault so the menu stays open, with decorative pointer-events-none switches. - TurnLivenessIndicator.tsx: when Show Animations is on (and reduced motion is off), render three Buzz marks in a row that fade in and rise, hold, then subtly fade out and continue upward on a 1.8s loop with a 0.25s stagger; the original single pulsing logo remains the fallback. - FuzzyLogo.tsx: add pulse prop (default true) so the staggered indicator can opt out of the built-in CSS opacity pulse that would fight the motion-driven fade. - UserProfilePanelTabs.tsx: bump both "Latest Activity" overlay titles down (preview state text-base to text-sm; carousel state and its channel label text-sm to text-xs). Animations respect prefers-reduced-motion via useReducedMotion in both the transcript list and the liveness indicator. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- TurnLivenessIndicator.tsx: size each mark in the staggered three-logo row with w-5! (1.25rem), down from the logo's built-in 1.5rem compact size. The important modifier is required because buzz-logo--compact's inline-size lives in unlayered CSS, which otherwise wins over layered Tailwind utilities. - The single-logo fallback (Show Animations off) keeps its original size. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
…en layout springs - AgentSessionTranscriptList.tsx: streaming tool calls append as segments inside the current turn block (key turn:<id> stays stable), so the block-level enter animation never fired for them — wrap each turn segment in its own motion.div enter animation in TranscriptDisplayBlockView so tool calls, summaries, and messages animate in individually as they stream. - Extract useHasCompletedInitialRender hook, used per block and per list: segments present at block mount (history load, or a new turn's first paint, which the block wrapper already animates) skip the transition, preventing double animation and static-history flicker. - Make the transcript scroll container a motion.div with layoutScroll so auto-tail scrolls are subtracted from layout measurements — previously each turn's scroll-to-bottom registered as false position deltas and rows visibly sprang back toward the top event. - Gate layout="position" to autoTail surfaces only, where this component owns the scroll container and layoutScroll applies; ancestor-scrolled surfaces (thread panel) keep enter animations but skip position springs to avoid the same false-delta artifact. - Share ROW_ENTER_FROM/ROW_ENTER_TO/ROW_ENTER_SPRING constants across the block- and segment-level animations. Segment animations respect the Show Animations preference and prefers-reduced-motion. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- observer-feed-screenshots: settleAnimations awaited every animation's finished promise, but TurnLivenessIndicator's staggered marks loop infinitely so finished never resolves — filter out infinite-iteration animations before awaiting (tests 10/11 hit the 30s timeout). - profile-active-turn 01/02: the profile panel no longer renders 'Working in #channel' badges; assert the live-activity embed and its per-channel carousel dots instead (popover test 03 unchanged — the popover keeps the badge). - active-turn-resilience: same removed-badge assertion, but the Agents view has no AgentSessionProvider so the embed can't render there. Assert prune resilience via the sidebar channel-working badges, which read the same activeAgentTurnsStore the test exercises. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
…l drift Desktop Smoke E2E (3) fails deterministically on CI Linux at 28.5px anchor drift vs the 28px budget in "preserves user scroll while older channel history loads" — all retries produce the identical 28.5 reading, and a layout probe shows branch and main render identical timeline metrics, so this is subpixel settle variance, not a layout regression from this branch. Bump the budget to 32px, still far below the row-sized jump (~46px) that the real anchor-shove bug produces. The budget has tracked density changes before: 2 -> 16 (#1426) -> 28 (#1429). Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
…container - Add h-full to the empty-state wrapper in AgentSessionTranscriptList so it fills the scroll container instead of stopping at min-h-40 (160px) - Fixes the FuzzyLogo loading indicator sitting above center in the profile Latest Activity card (h-56), which gave the wrapper a taller resolved height than its min-height - No behavior change when autoTail is off: without a fixed-height parent, h-full resolves to auto and min-h-40 still governs Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
… center - Add h-full to the embla viewport wrapper inside CarouselContent — the extra overflow-hidden div had no height class, breaking the h-full chain from the profile Latest Activity card (h-56) down to the transcript empty state, so the loading indicator centered in the top 160px (min-h-40) instead of the full card - Completes the centering fix from 2a0a8cbe for the multi-slide carousel path; the single-slide path doesn't route through the carousel - CarouselContent is only used by the profile live-activity card; when the carousel parent is unconstrained, h-full resolves to auto (no change) - Verified via Playwright bounding-box check: indicator center matches card center exactly (delta 0.0px) Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
…age bubbles - Add MessageLinkHoverCue component — a small top-right pill with an external-link arrow that fades in (150ms) on bubble hover or keyboard focus; aria-hidden since the bubbles already expose role="link" - UserMessageBubble: mark linked bubbles as group/bubble, add a hover:bg-muted/40 tint alongside the existing border shift, and render the cue when a message link exists - CompactMessageSummary (agent "Sent message" bubbles): same group/bubble + cue treatment layered on the existing hover background change - Cue only renders when the bubble actually navigates (canOpenMessage / messageLink), so compact profile-card previews are unaffected - Verified via Playwright: cue opacity 0 at rest and 1 on hover for both bubble types; observer-feed, profile-active-turn, and active-turn-resilience suites pass (15/15) Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
PR #1412 made per-turn prompt context (and the session/new system prompt) render inline in the observer feed after every user message bubble. The intended UX is the pre-#1412 behavior: the feed stays clean and the context is only revealed on demand via the CheckCheck ("Checks") ingress in the message footer. - AgentSessionTranscriptList.tsx: - Remove PromptContextInline (and its "View full" expander) so no context sections render in the feed - Restore the CheckCheck footer Toggle (transcript-prompt-context-toggle) whenever the turn has prompt context; it opens the restored PromptContextDialog modal - Restore the pre-#1412 dialog chrome: "Prompt context" title plus the turn-setup summary line (formatPromptSetupSummary) in the header - Merge system-prompt sections (Base/System — new since #1412) ahead of the prompt-context sections in the same dialog instead of dropping them - observer-feed-screenshots.spec.ts: - Tests 01/05/11 now assert context is absent from the feed, click the toggle, and assert/screenshot the dialog (including Base → System → context section ordering in test 11) Verified: biome, tsc, 1488 desktop unit tests, and all 11 observer-feed Playwright specs pass. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Add a group/row scope to the expandable <summary> elements in ActivityRow and ToolItem so hover styling is confined to the summary row — hovering expanded content below a row no longer affects it - ActivityRowLabel verb/object spans and the chevron gain transition-colors + group-hover/row:text-foreground, matching the tone rows already use when expanded (e.g. "Ran 3 commands", "Read 4 files", "Edited useAnchoredScroll.ts") - compactSummaryTone() (label fallback, preview, duration, chevron in CompactToolSummaryRow) picks up the same hover variant so the whole row highlights consistently - Non-expandable ActivityRow branch gets no scope and stays static - Verified via Playwright: object span computed color flips from muted to foreground on hover for both grouped summaries and single tool rows Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Remove border and shadow-sm from MessageLinkHoverCue for a flatter look - Keep the bg-background/95 backdrop for readability over message text, plus the rounded corners and fade-in hover/focus behavior Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
…l hook
- Retype `prevMessagesRef` from `TimelineMessage[]` to `Array<{ id: string }>`
in `useAnchoredScroll.ts` — this branch loosened the hook's `messages` option
to `Array<{ id: string }>` while main's new snapshot-delta tracking typed the
ref against the full `TimelineMessage` shape, producing TS2322 errors after
the rebase onto main
- Drop the now-unused `TimelineMessage` type import;
`classifyTimelineMessageDelta` only requires `Pick<TimelineMessage, "id">`,
so the narrower element type satisfies it without widening the hook API
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
41c2464 to
7756b34
Compare
wesbillman
left a comment
There was a problem hiding this comment.
Pinky review: I found two user-visible regressions that should be fixed before merge. The profile carousel can silently retarget the selected channel when its slide set changes, and the global Markdown typography change alters unrelated surfaces that relied on the component's default text size/color. CI and the local desktop unit/typecheck suites are green, but neither behavior is covered by the current tests.
| return; | ||
| } | ||
|
|
||
| const currentChannelId = slides[carouselApi.selectedScrollSnap()]; |
There was a problem hiding this comment.
[P1] Preserve selection by channel id when the slide set changes. selectedIndex is positional, but slides is recomputed as live turns begin/end (and switches from the live subset to sorted historical channels when the last turn completes). After such a change, slides[carouselApi.selectedScrollSnap()] is necessarily a member of the new slides, so this condition is tautological and never restores the previous/preferred channel. A user viewing channel B can therefore silently be moved to whichever channel now occupies B's old index, and the card/open action targets that different channel. Track the selected channel id across slide changes (or compare against the previous slide array) and explicitly scroll to its new index, falling back to preferredIndex only when that id disappeared. Please add a test that selects a nonzero slide, changes the channel set without changing its length (and covers live→recent), then verifies the label and open target remain correct.
| MESSAGE_MARKDOWN_CLASS, | ||
| [ | ||
| "max-w-none [overflow-wrap:anywhere] text-sm leading-5 text-foreground", | ||
| "max-w-none wrap-anywhere", |
There was a problem hiding this comment.
[P1] Keep the shared Markdown default typography, or migrate every caller explicitly. This removes text-sm leading-5 text-foreground globally so typography inherits from the parent. Several unrelated callers do not establish those values—for example ChannelCanvas renders <Markdown> in a padding/border div with no text class—so canvas body text changes from 14px/foreground to the browser/inherited default (typically 16px), despite this PR being about the profile activity embed. Other bare callers now depend accidentally on whatever ancestor happens to provide. Please retain the old defaults and override them only in the compact transcript surfaces, or update every Markdown call site to declare its intended typography and add visual coverage for affected non-transcript surfaces.
Restore shared Markdown typography defaults and keep profile activity selection anchored to the channel ID as the slide set changes. Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co> Signed-off-by: Wes <wesbillman@users.noreply.github.com>
wesbillman
left a comment
There was a problem hiding this comment.
Fixed the two blocking findings directly on the branch in b5503ef: carousel selection is now preserved by channel ID across slide reorder/live-to-recent transitions (with focused regression tests), and shared Markdown typography defaults are restored. Desktop typecheck, lint, and all 1,560 unit tests pass locally.
Take main's AttachmentMediaLightbox extraction (#1380) for the composer attachment preview, then re-apply this PR's one-attribute change: add disableHoverableContent to the remove-attachment Tooltips so they dismiss when the cursor leaves the trigger. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Category: improvement
User Impact: Agents who are actively working now show a live activity preview directly in their Profile side panel, with a click-through to the full Activity view.
Problem: The Profile auxiliary panel only exposed Activity through a static
Activity log → Viewrow, so users had to leave the profile summary to understand what a live agent was doing. That made active agents feel disconnected from the profile surface where people already check identity, status, and membership.Solution: Replace the static ingress with a compact live/recent activity card when activity exists, keep the original row for idle agents, and route the card’s explicit “Open full activity” action into the existing full Activity panel. The preview reuses the shared agent-session transcript renderer so profile, channel, and full-panel activity stay visually and behaviorally aligned.
File changes
desktop/package.json / pnpm-lock.yaml
Add the carousel dependency used by the profile activity preview’s in-frame multi-channel switcher.
desktop/src/features/profile/lib/profileActivityAgent.ts
Resolve the activity-agent shape used by the profile panel so locally managed agents and relay-owned agents can both render the same preview surface.
desktop/src/features/profile/lib/profileActivityFeedScope.ts
Derive the best profile activity scope from observer-feed and active-turn state, including persisted recent activity after a turn completes.
desktop/src/features/profile/ui/UserProfilePanel.tsx / UserProfilePanelSections.tsx / UserProfilePanelTabs.tsx / UserProfilePopover.tsx
Replace the idle Activity Log row with a compact live/recent preview card, support per-channel carousel previews, and preserve the full Activity click-through behavior with explicit channel scoping.
desktop/src/features/agents/observerRelayStore.ts / desktop/src/testing/e2eBridge.ts
Expose the observer-event synchronization hooks needed for profile preview scoping and regression coverage.
desktop/src/features/agents/ui/ManagedAgentSessionPanel.tsx / AgentSessionTranscriptList.tsx / agentSessionTranscriptContext.ts / agentSessionTypes.ts / agentSessionUtils.ts
Extend the shared transcript panel so the profile preview can render compact, auto-tailed activity while the full Activity view keeps its standard transcript layout.
desktop/src/features/agents/ui/activityRenderClasses/ and AgentSessionToolItem/
Polish activity rows, tool summaries, message cards, shell/file/image blocks, and compact transcript typography so the embedded preview reads as an activity feed rather than a chat transcript.
desktop/src/features/agents/ui/FileContentBlock.tsx / FileEditDiffView.tsx / agentSessionFileRead.ts / agentSessionImageContent.ts / related tests
Formalize reusable file-read and image-content renderers for expanded tool details shown in activity transcripts.
desktop/src/features/agents/ui/TurnLivenessIndicator.tsx / transcriptAnimationPreference.ts / desktop/src/shared/ui/buzz-logo/
Add the Buzz mark liveness indicator, transcript-row entrance animations, and the Show Animations preference used by live transcript surfaces.
desktop/src/features/channels/ui/AgentSessionThreadPanel.tsx / BotActivityBar.tsx / ChannelPane.tsx / ChannelScreen.tsx / related channel hooks/types
Carry selected channel context into the full Activity panel and keep channel activity state aligned with the profile preview.
desktop/src/features/messages/ui/ComposerAttachments.tsx / useAnchoredScroll.ts
Reuse the anchored-scroll behavior so live activity tails only when appropriate instead of yanking users away from the content they are reading.
desktop/src/shared/ui/carousel.tsx
Add the shared Carousel wrapper used by the profile preview’s in-frame channel slides.
desktop/src/shared/ui/markdown.tsx / markdown/types.ts / SimpleImageLightbox.tsx
Let Markdown inherit typography from its container and keep shared rich-content rendering consistent across compact and full activity surfaces.
desktop/test-loader-hooks.mjs
Teach the node test loader to handle the markdown graph’s emoji-mart/json imports in unit tests.
desktop/tests/e2e/active-turn-resilience.spec.ts / channels.spec.ts / observer-feed-screenshots.spec.ts / profile-active-turn.spec.ts / scroll-history.spec.ts
Update smoke and profile coverage for the live activity embed, infinite liveness animations, and CI scroll-settle behavior.
Reproduction Steps
Activity log → Viewrow is replaced by a compact activity preview card while the agent has live or recent activity.Screenshots/Demos
Screen.Recording.2026-07-02.at.4.29.50.PM.mov
Captured fresh at current head
7756b34avia a Playwright screenshot pass against the built desktop app (tests/e2e/profile-live-activity-screenshots.spec.ts). Transcript rows are seeded from real observer events (__BUZZ_E2E_SEED_OBSERVER_EVENTS__) — a user prompt bundle plus assistant message chunks — so the previews show genuine activity content, not structural placeholders.Activity log → Viewrow is preserved when there is no live/recent activity.#channellabel.Click-through into full Activity — clicking the preview overtakes the full Activity panel (existing behavior preserved):
Validation
pnpm --dir desktop check✅pnpm --dir desktop typecheck✅pnpm --dir desktop test✅pnpm --dir desktop build✅28580138465at41c24646✅ (green; head has since advanced to7756b34awith UI-only polish and a type/scroll alignment fix)Coordination
buzz://message?channel=a9f57da5-5845-4dac-934c-e9126fdd10be&thread=da8eb3ef5907e0b0c0e70b488574e1d7643b4a594c6e2258ed4597ae76bcd8e0