diff --git a/apps/web/features/issues/components/agent-live-card.tsx b/apps/web/features/issues/components/agent-live-card.tsx index 620fb8ee8..29363c861 100644 --- a/apps/web/features/issues/components/agent-live-card.tsx +++ b/apps/web/features/issues/components/agent-live-card.tsx @@ -107,11 +107,9 @@ interface TaskState { interface AgentLiveCardProps { issueId: string; - /** Scroll container ref — used to auto-collapse timeline on outer scroll. */ - scrollContainerRef?: React.RefObject; } -export function AgentLiveCard({ issueId, scrollContainerRef }: AgentLiveCardProps) { +export function AgentLiveCard({ issueId }: AgentLiveCardProps) { const { getActorName } = useActorName(); const [taskStates, setTaskStates] = useState>(new Map()); const seenSeqs = useRef(new Set()); @@ -208,20 +206,35 @@ export function AgentLiveCard({ issueId, scrollContainerRef }: AgentLiveCardProp if (taskStates.size === 0) return null; const entries = Array.from(taskStates.values()); + const [firstEntry, ...restEntries] = entries; + if (!firstEntry) return null; return ( -
- {entries.map(({ task, items }) => ( + <> + {/* Primary agent — sticky at top of the Activity section */} +
- ))} -
+
+ {/* Additional agents — scroll with the page */} + {restEntries.length > 0 && ( +
+ {restEntries.map(({ task, items }) => ( + + ))} +
+ )} + ); } @@ -232,17 +245,15 @@ interface SingleAgentLiveCardProps { items: TimelineItem[]; issueId: string; agentName: string; - scrollContainerRef?: React.RefObject; } -function SingleAgentLiveCard({ task, items, issueId, agentName, scrollContainerRef }: SingleAgentLiveCardProps) { +function SingleAgentLiveCard({ task, items, issueId, agentName }: SingleAgentLiveCardProps) { const [elapsed, setElapsed] = useState(""); const [open, setOpen] = useState(false); const [autoScroll, setAutoScroll] = useState(true); const [cancelling, setCancelling] = useState(false); const [transcriptOpen, setTranscriptOpen] = useState(false); const scrollRef = useRef(null); - const ignoreScrollRef = useRef(false); // Elapsed time useEffect(() => { @@ -253,20 +264,6 @@ function SingleAgentLiveCard({ task, items, issueId, agentName, scrollContainerR return () => clearInterval(interval); }, [task.started_at, task.dispatched_at]); - // Auto-collapse timeline when outer scroll container scrolls - useEffect(() => { - const container = scrollContainerRef?.current; - if (!container) return; - - const handleOuterScroll = () => { - if (ignoreScrollRef.current) return; - setOpen(false); - }; - - container.addEventListener("scroll", handleOuterScroll, { passive: true }); - return () => container.removeEventListener("scroll", handleOuterScroll); - }, [scrollContainerRef]); - // Auto-scroll timeline to bottom useEffect(() => { if (autoScroll && scrollRef.current) { @@ -281,10 +278,6 @@ function SingleAgentLiveCard({ task, items, issueId, agentName, scrollContainerR }, []); const toggleOpen = useCallback(() => { - if (!open) { - ignoreScrollRef.current = true; - setTimeout(() => { ignoreScrollRef.current = false; }, 300); - } setOpen(!open); }, [open]); @@ -302,7 +295,7 @@ function SingleAgentLiveCard({ task, items, issueId, agentName, scrollContainerR const toolCount = items.filter((i) => i.type === "tool_use").length; return ( -
+
{/* Header — click to toggle timeline */}
- {/* Agent live output */} - + {/* Agent live output — sticky inside the Activity section so it + stays pinned while scrolling through TaskRunHistory + comments. */} + {/* Agent execution history */}