From 9aaa93bb06b1d9e92adce53710c19f3e784ed66c Mon Sep 17 00:00:00 2001 From: AlphaCat Date: Sat, 1 Aug 2026 06:54:02 +0800 Subject: [PATCH 1/2] fix(chat): stabilize live transcript activity Keep each active assistant turn under one stable outer row, update thinking and tool activity in place, and unify bottom-follow scroll ownership across GUI and Gateway WebUI. Add mirrored overlay/scroll models, lifecycle and stress regressions, runtime acceptance evidence, and status-width/caret fixes. --- .../agent-gateway/web/src/app/GatewayApp.tsx | 1 + .../web/src/components/GatewayTranscript.tsx | 80 +++----- .../src/components/chat/ThinkingActivity.tsx | 149 ++++++++++++++ .../src/lib/chat-scroll/framePinController.ts | 31 +++ .../src/lib/chat-scroll/useScrollFollow.ts | 37 +++- .../web/src/lib/chat/thinkingOverlayModel.ts | 59 ++++++ .../liveScrollAdjustPolicy.ts | 16 +- .../chat/assistant-bubble/RoundContent.tsx | 77 +------ .../chat/assistant-bubble/StatusText.tsx | 6 +- .../chat/assistant-bubble/ToolTraceGroup.tsx | 13 ++ .../assistant-bubble/assistantBubbleUtils.ts | 25 +-- .../web/test/assistant-bubble-utils.test.mjs | 54 ++++- .../web/test/assistant-status.test.mjs | 5 + .../web/test/chat-file-links.test.mjs | 13 +- .../web/test/frame-pin-controller.test.mjs | 30 +++ .../web/test/live-markdown-caret.test.mjs | 12 ++ .../test/live-scroll-adjust-policy.test.mjs | 5 +- .../web/test/live-status-layout.test.mjs | 20 ++ .../web/test/thinking-overlay-model.test.mjs | 44 ++++ .../web/test/transcript-rows.test.mjs | 110 ++++++++++ .../src/components/chat/ThinkingActivity.tsx | 149 ++++++++++++++ .../src/lib/chat-scroll/framePinController.ts | 31 +++ .../src/lib/chat-scroll/useScrollFollow.ts | 37 +++- .../src/lib/chat/thinkingOverlayModel.ts | 59 ++++++ .../liveScrollAdjustPolicy.ts | 16 +- .../pages/chat/components/AssistantBubble.tsx | 42 +--- .../assistant-bubble/RoundContent.tsx | 80 +------- .../assistant-bubble/StatusText.tsx | 6 +- .../assistant-bubble/ToolTraceGroup.tsx | 11 + .../assistant-bubble/assistantBubbleUtils.ts | 25 +-- .../chat/transcript/AssistantActivityRow.tsx | 65 ++++++ .../pages/chat/transcript/ChatTranscript.tsx | 1 + .../pages/chat/transcript/TranscriptList.tsx | 45 +++-- .../src/pages/chat/transcript/rowModel.ts | 188 ++++++++++++------ .../test/chat/block-round-keys.test.mjs | 58 ++++++ .../test/chat/frame-pin-controller.test.mjs | 53 +++++ .../test/chat/live-markdown-caret.test.mjs | 12 ++ .../chat/live-scroll-adjust-policy.test.mjs | 5 +- .../test/chat/live-status-width.test.mjs | 19 ++ .../test/chat/thinking-overlay-model.test.mjs | 50 +++++ .../test/chat/transcript-row-model.test.mjs | 182 +++++++++++++++-- docs/worklog/live-transcript-jitter.md | 173 ++++++++++++++++ scripts/mirror-manifest.json | 3 + 43 files changed, 1680 insertions(+), 417 deletions(-) create mode 100644 crates/agent-gateway/web/src/components/chat/ThinkingActivity.tsx create mode 100644 crates/agent-gateway/web/src/lib/chat-scroll/framePinController.ts create mode 100644 crates/agent-gateway/web/src/lib/chat/thinkingOverlayModel.ts create mode 100644 crates/agent-gateway/web/test/frame-pin-controller.test.mjs create mode 100644 crates/agent-gateway/web/test/live-markdown-caret.test.mjs create mode 100644 crates/agent-gateway/web/test/live-status-layout.test.mjs create mode 100644 crates/agent-gateway/web/test/thinking-overlay-model.test.mjs create mode 100644 crates/agent-gui/src/components/chat/ThinkingActivity.tsx create mode 100644 crates/agent-gui/src/lib/chat-scroll/framePinController.ts create mode 100644 crates/agent-gui/src/lib/chat/thinkingOverlayModel.ts create mode 100644 crates/agent-gui/src/pages/chat/transcript/AssistantActivityRow.tsx create mode 100644 crates/agent-gui/test/chat/frame-pin-controller.test.mjs create mode 100644 crates/agent-gui/test/chat/live-markdown-caret.test.mjs create mode 100644 crates/agent-gui/test/chat/live-status-width.test.mjs create mode 100644 crates/agent-gui/test/chat/thinking-overlay-model.test.mjs create mode 100644 docs/worklog/live-transcript-jitter.md diff --git a/crates/agent-gateway/web/src/app/GatewayApp.tsx b/crates/agent-gateway/web/src/app/GatewayApp.tsx index a8dce2858..e44d6595b 100644 --- a/crates/agent-gateway/web/src/app/GatewayApp.tsx +++ b/crates/agent-gateway/web/src/app/GatewayApp.tsx @@ -4900,6 +4900,7 @@ export default function GatewayApp() { activeTurnKey={displayedTranscript.activeTurnKey} contentWidth={settings.customSettings.chatTranscript.width} isViewportFollowing={transcriptFollow.isFollowing} + viewportFollowing={transcriptFollowing} navRef={transcriptNavRef} onAnchorUserRowChange={setActiveFloorKey} error={transcriptError} diff --git a/crates/agent-gateway/web/src/components/GatewayTranscript.tsx b/crates/agent-gateway/web/src/components/GatewayTranscript.tsx index f3a110549..4e9149042 100644 --- a/crates/agent-gateway/web/src/components/GatewayTranscript.tsx +++ b/crates/agent-gateway/web/src/components/GatewayTranscript.tsx @@ -17,7 +17,7 @@ import { useLocale } from "@/i18n/LocaleContext"; import type { ChatFileLink } from "@/lib/chat/chatFileLinks"; import { normalizeLiveToolStatus, VIBING_STATUS } from "@/lib/chat/chatPageHelpers"; import type { HistoryMessageRef } from "@/lib/chat/conversationState"; -import { getRoundText, getRoundToolTrace } from "@/lib/chat/uiMessages"; +import { getRoundText } from "@/lib/chat/uiMessages"; import { formatUploadedFileSize, type PendingUploadedFile, @@ -60,7 +60,6 @@ import { } from "@/pages/chat/AssistantBubble"; import type { RetryAttemptRecord, TranscriptRow } from "../lib/chat/transcript/types"; -import type { GatewayTranscriptRound } from "../lib/chatUi"; import type { SectionId } from "../pages/settings/types"; import { ChatEmptyState } from "./chat/ChatEmptyState"; import { getUploadedFileTypeIcon } from "./chat/fileTypeIcons"; @@ -92,6 +91,7 @@ type GatewayTranscriptProps = { // Whether the scroll-follow engine is attached to the bottom; gates the // virtualizer's resize-compensation carve-out for live-row growth. isViewportFollowing?: () => boolean; + viewportFollowing?: boolean; // Imperative jump handle for the floor navigation rail. navRef?: MutableRefObject; // Reports the user row at the viewport's top edge (the "current floor"). @@ -168,50 +168,18 @@ function resolveNearestScrollViewport(element: HTMLElement | null) { function LiveStatusFooter(props: { status: string; isCompaction?: boolean }) { const { status, isCompaction = false } = props; return ( -
+
{isCompaction ? ( - + ) : status === VIBING_STATUS ? ( - + ) : ( - {status} + {status} )}
); } -function shouldShowLiveStatusForRounds(rounds: GatewayTranscriptRound[]) { - const activeRound = rounds[rounds.length - 1]; - if (!activeRound) { - return true; - } - const visibleToolKeys = new Set( - getRoundToolTrace(activeRound).map((item) => `${item.toolCall.id}\u0000${item.toolCall.name}`), - ); - - for (let index = activeRound.blocks.length - 1; index >= 0; index -= 1) { - const block = activeRound.blocks[index]; - if (!block) { - continue; - } - if (block.kind === "tool") { - if (visibleToolKeys.has(`${block.item.toolCall.id}\u0000${block.item.toolCall.name}`)) { - return true; - } - continue; - } - if (block.kind === "hostedSearch") { - return false; - } - if (block.text.trim() === "") { - continue; - } - return block.kind !== "text"; - } - - return true; -} - function HistoryLoadingState(props: { title?: string }) { const title = props.title?.trim(); return ( @@ -1184,6 +1152,7 @@ const GatewayTranscriptListRegion = memo(function GatewayTranscriptListRegion(pr contentWidth: number; scrollViewport: HTMLDivElement | null; isViewportFollowing?: () => boolean; + viewportFollowing: boolean; navRef?: MutableRefObject; onAnchorUserRowChange?: (rowKey: string | null) => void; hasMoreHistory?: boolean; @@ -1218,6 +1187,7 @@ const GatewayTranscriptListRegion = memo(function GatewayTranscriptListRegion(pr contentWidth, scrollViewport, isViewportFollowing, + viewportFollowing, navRef, onAnchorUserRowChange, hasMoreHistory, @@ -1361,16 +1331,10 @@ const GatewayTranscriptListRegion = memo(function GatewayTranscriptListRegion(pr gap: TRANSCRIPT_ROW_GAP, overscan: TRANSCRIPT_ROW_OVERSCAN_COUNT, enabled: scrollViewport !== null, - // End-anchored: prepends (loading earlier history) keep the visible item - // stable upstream via keyed anchoring, growth of the last row while the - // viewport is virtually at the end compensates by the total-size delta, - // and estimate→measure corrections keep the bottom pinned. The threshold - // matches scrollFollowCore's BOTTOM_ATTACH_THRESHOLD_PX so both engines - // agree on what "at the bottom" means. followOnAppend stays off: its - // DOM-distance re-follow would conflict with the follow reducer's - // "shrink clamps never re-attach" contract — appends while following are - // already pinned by the reducer. - anchorTo: "end", + // End anchoring is enabled only for a detached reader so keyed prepends + // preserve the visible row. While following, start anchoring disables the + // virtualizer's bottom correction and leaves live growth to useScrollFollow. + anchorTo: viewportFollowing ? "start" : "end", scrollEndThreshold: 8, initialMeasurementsCache, rangeExtractor: (range) => extractLiveRange(range, forceMountStartRef.current), @@ -1378,8 +1342,8 @@ const GatewayTranscriptListRegion = memo(function GatewayTranscriptListRegion(pr // TanStack exposes the resize-compensation predicate as an instance field, // not an option; reassigning per render keeps the closure's inputs current. - // It only governs the detached reader — while virtually at the end, the - // upstream end-anchor compensation takes priority over this predicate. + // While following it rejects every virtualizer correction; while detached + // it retains estimate/measurement anchoring for rows above the viewport. transcriptVirtualizer.shouldAdjustScrollPositionOnItemSizeChange = createLiveRowScrollAdjustPolicy({ getLiveStartIndex: () => forceMountStartRef.current, @@ -1701,16 +1665,11 @@ const GatewayTranscriptListRegion = memo(function GatewayTranscriptListRegion(pr const rowIndex = virtualRow.index - leadingOffset; const isLatestLiveAssistant = rowIndex === liveAssistantIndex; const isLatestLiveStreaming = isStreaming && isLatestLiveAssistant; - const shouldShowLiveStatus = - isLatestLiveStreaming && - Boolean(displayedToolStatus) && - !displayedToolStatusIsCompaction && - shouldShowLiveStatusForRounds(row.rounds); - const liveStatusText = shouldShowLiveStatus ? (displayedToolStatus ?? "") : ""; return (
- {shouldShowLiveStatus ? : null} + {isLatestLiveStreaming ? ( + + ) : null} {isLatestLiveStreaming && !shouldShowPendingLiveBubble && retryAttempts && @@ -1796,6 +1760,7 @@ export function GatewayTranscript({ activeTurnKey = null, contentWidth = DEFAULT_CHAT_TRANSCRIPT_WIDTH, isViewportFollowing, + viewportFollowing = false, navRef, onAnchorUserRowChange, error, @@ -1884,6 +1849,7 @@ export function GatewayTranscript({ contentWidth={contentWidth} scrollViewport={transcriptScrollViewport} isViewportFollowing={isViewportFollowing} + viewportFollowing={viewportFollowing} navRef={navRef} onAnchorUserRowChange={onAnchorUserRowChange} hasMoreHistory={hasMoreHistory} diff --git a/crates/agent-gateway/web/src/components/chat/ThinkingActivity.tsx b/crates/agent-gateway/web/src/components/chat/ThinkingActivity.tsx new file mode 100644 index 000000000..8389245df --- /dev/null +++ b/crates/agent-gateway/web/src/components/chat/ThinkingActivity.tsx @@ -0,0 +1,149 @@ +import { useCallback, useId, useLayoutEffect, useRef, useState } from "react"; +import { createPortal } from "react-dom"; +import { useLocale } from "../../i18n"; +import type { ChatFileLink } from "../../lib/chat/chatFileLinks"; +import { + resolveThinkingOverlayPlacement, + type ThinkingOverlayPlacement, +} from "../../lib/chat/thinkingOverlayModel"; +import { ChevronRight, Lightbulb } from "../icons"; +import { Markdown } from "../Markdown"; + +export function ThinkingActivity(props: { + text: string; + isRunning?: boolean; + renderMode: "streaming" | "static"; + workdir?: string; + onOpenFileLink?: (link: ChatFileLink) => void; +}) { + const { text, isRunning = false, renderMode, workdir, onOpenFileLink } = props; + const { t } = useLocale(); + const [open, setOpen] = useState(false); + const [placement, setPlacement] = useState(null); + const triggerRef = useRef(null); + const panelRef = useRef(null); + const panelId = useId(); + const hasText = /\S/.test(text); + + const updatePlacement = useCallback(() => { + const trigger = triggerRef.current; + if (!trigger) return; + setPlacement( + resolveThinkingOverlayPlacement(trigger.getBoundingClientRect(), { + width: window.innerWidth, + height: window.innerHeight, + }), + ); + }, []); + + const close = useCallback((restoreFocus = false) => { + setOpen(false); + setPlacement(null); + if (restoreFocus) { + requestAnimationFrame(() => triggerRef.current?.focus({ preventScroll: true })); + } + }, []); + + useLayoutEffect(() => { + if (!open) return; + updatePlacement(); + const focusFrame = requestAnimationFrame(() => + panelRef.current?.focus({ preventScroll: true }), + ); + const handlePointerDown = (event: PointerEvent) => { + const target = event.target; + if (!(target instanceof Node)) return; + if (triggerRef.current?.contains(target) || panelRef.current?.contains(target)) return; + close(); + }; + const handleFocusIn = (event: FocusEvent) => { + const target = event.target; + if (!(target instanceof Node)) return; + if (triggerRef.current?.contains(target) || panelRef.current?.contains(target)) return; + close(); + }; + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key !== "Escape") return; + event.preventDefault(); + event.stopPropagation(); + close(true); + }; + window.addEventListener("pointerdown", handlePointerDown, true); + window.addEventListener("focusin", handleFocusIn, true); + window.addEventListener("keydown", handleKeyDown, true); + window.addEventListener("resize", updatePlacement); + window.addEventListener("scroll", updatePlacement, true); + return () => { + cancelAnimationFrame(focusFrame); + window.removeEventListener("pointerdown", handlePointerDown, true); + window.removeEventListener("focusin", handleFocusIn, true); + window.removeEventListener("keydown", handleKeyDown, true); + window.removeEventListener("resize", updatePlacement); + window.removeEventListener("scroll", updatePlacement, true); + }; + }, [close, open, updatePlacement]); + + if (!hasText) return null; + + return ( +
+ + {open && placement + ? createPortal( + , + document.body, + ) + : null} +
+ ); +} diff --git a/crates/agent-gateway/web/src/lib/chat-scroll/framePinController.ts b/crates/agent-gateway/web/src/lib/chat-scroll/framePinController.ts new file mode 100644 index 000000000..c92bd5440 --- /dev/null +++ b/crates/agent-gateway/web/src/lib/chat-scroll/framePinController.ts @@ -0,0 +1,31 @@ +export type ScheduleFrame = (callback: () => void) => number; +export type CancelFrame = (handle: number) => void; + +export function createFramePinController( + write: () => void, + scheduleFrame: ScheduleFrame, + cancelFrame: CancelFrame, +) { + let pendingFrame: number | null = null; + + const cancel = () => { + if (pendingFrame === null) return; + cancelFrame(pendingFrame); + pendingFrame = null; + }; + + const schedule = () => { + if (pendingFrame !== null) return; + pendingFrame = scheduleFrame(() => { + pendingFrame = null; + write(); + }); + }; + + const flush = () => { + cancel(); + write(); + }; + + return { cancel, flush, schedule }; +} diff --git a/crates/agent-gateway/web/src/lib/chat-scroll/useScrollFollow.ts b/crates/agent-gateway/web/src/lib/chat-scroll/useScrollFollow.ts index 78b0eac76..302e2b72c 100644 --- a/crates/agent-gateway/web/src/lib/chat-scroll/useScrollFollow.ts +++ b/crates/agent-gateway/web/src/lib/chat-scroll/useScrollFollow.ts @@ -1,5 +1,5 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; - +import { createFramePinController } from "./framePinController"; import { createFollowState, DEFAULT_FOLLOW_CONFIG, @@ -113,6 +113,18 @@ export function useScrollFollow(args: UseScrollFollowArgs): { configRef.current = { ...DEFAULT_FOLLOW_CONFIG, ...args.config }; const [following, setFollowing] = useState(true); const jumpRafRef = useRef(null); + const pinController = useMemo( + () => + createFramePinController( + () => { + const el = boundViewportRef.current; + if (el) el.scrollTop = el.scrollHeight; + }, + (callback) => requestAnimationFrame(callback), + (handle) => cancelAnimationFrame(handle), + ), + [], + ); const cancelJumpAnimation = useCallback(() => { if (jumpRafRef.current !== null) { @@ -124,25 +136,28 @@ export function useScrollFollow(args: UseScrollFollowArgs): { const pinToBottom = useCallback(() => { // An instant pin supersedes any in-flight jump animation. cancelJumpAnimation(); - const el = boundViewportRef.current; - if (el) { - el.scrollTop = el.scrollHeight; - } - }, [cancelJumpAnimation]); + pinController.flush(); + }, [cancelJumpAnimation, pinController]); + + const schedulePinToBottom = useCallback(() => { + cancelJumpAnimation(); + pinController.schedule(); + }, [cancelJumpAnimation, pinController]); const dispatch = useCallback( - (event: FollowEvent) => { + (event: FollowEvent, pinMode: "immediate" | "frame" = "immediate") => { const wasFollowing = stateRef.current.following; const step = reduceFollowEvent(stateRef.current, event, configRef.current); stateRef.current = step.state; if (step.pin) { - pinToBottom(); + if (pinMode === "frame") schedulePinToBottom(); + else pinToBottom(); } if (step.state.following !== wasFollowing) { setFollowing(step.state.following); } }, - [pinToBottom], + [pinToBottom, schedulePinToBottom], ); const stickToBottom = useCallback(() => { @@ -350,7 +365,7 @@ export function useScrollFollow(args: UseScrollFollowArgs): { typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => { - dispatch({ type: "contentGrowth", gap: getGap() }); + dispatch({ type: "contentGrowth", gap: getGap() }, "frame"); }); resizeObserver?.observe(viewport); if (growthTarget instanceof Element) { @@ -372,6 +387,7 @@ export function useScrollFollow(args: UseScrollFollowArgs): { } document.removeEventListener("visibilitychange", handleVisibilityChange); resizeObserver?.disconnect(); + pinController.cancel(); cancelJumpAnimation(); boundViewportRef.current = null; }; @@ -382,6 +398,7 @@ export function useScrollFollow(args: UseScrollFollowArgs): { enabled, listenerRoot, pinToBottom, + pinController, trackKeys, viewport, ]); diff --git a/crates/agent-gateway/web/src/lib/chat/thinkingOverlayModel.ts b/crates/agent-gateway/web/src/lib/chat/thinkingOverlayModel.ts new file mode 100644 index 000000000..9afe7ab3f --- /dev/null +++ b/crates/agent-gateway/web/src/lib/chat/thinkingOverlayModel.ts @@ -0,0 +1,59 @@ +export type ThinkingOverlayRect = { + left: number; + right: number; + top: number; + bottom: number; + width: number; + height: number; +}; + +export type ThinkingOverlayViewport = { width: number; height: number }; + +export type ThinkingOverlayPlacement = { + side: "above" | "below"; + left: number; + width: number; + maxHeight: number; + top?: number; + bottom?: number; +}; + +const VIEWPORT_MARGIN_PX = 12; +const OVERLAY_GAP_PX = 8; +const MAX_OVERLAY_WIDTH_PX = 640; +const MIN_PREFERRED_HEIGHT_PX = 180; + +export function resolveThinkingOverlayPlacement( + trigger: ThinkingOverlayRect, + viewport: ThinkingOverlayViewport, +): ThinkingOverlayPlacement { + const viewportWidth = Math.max(1, viewport.width); + const horizontalMargin = Math.min(VIEWPORT_MARGIN_PX, Math.max(0, (viewportWidth - 1) / 2)); + const availableWidth = Math.max(1, viewportWidth - horizontalMargin * 2); + const width = Math.min(MAX_OVERLAY_WIDTH_PX, availableWidth); + const centeredLeft = trigger.left + (trigger.width - width) / 2; + const left = Math.min( + Math.max(horizontalMargin, centeredLeft), + Math.max(horizontalMargin, viewportWidth - horizontalMargin - width), + ); + const above = Math.max(0, trigger.top - OVERLAY_GAP_PX - VIEWPORT_MARGIN_PX); + const below = Math.max(0, viewport.height - trigger.bottom - OVERLAY_GAP_PX - VIEWPORT_MARGIN_PX); + const side = above >= MIN_PREFERRED_HEIGHT_PX || above >= below ? "above" : "below"; + + if (side === "above") { + return { + side, + left, + width, + maxHeight: above, + bottom: viewport.height - trigger.top + OVERLAY_GAP_PX, + }; + } + return { + side, + left, + width, + maxHeight: below, + top: trigger.bottom + OVERLAY_GAP_PX, + }; +} diff --git a/crates/agent-gateway/web/src/lib/transcript-virtual/liveScrollAdjustPolicy.ts b/crates/agent-gateway/web/src/lib/transcript-virtual/liveScrollAdjustPolicy.ts index d2ad8f63e..a03eb7864 100644 --- a/crates/agent-gateway/web/src/lib/transcript-virtual/liveScrollAdjustPolicy.ts +++ b/crates/agent-gateway/web/src/lib/transcript-virtual/liveScrollAdjustPolicy.ts @@ -3,10 +3,9 @@ import type { VirtualItem, Virtualizer } from "@tanstack/react-virtual"; // Resize-compensation policy for the transcript virtualizer (virtual-core // 3.17.x semantics). // -// With `anchorTo: 'end'`, virtual-core handles the bottom-pinned case itself: -// while the viewport is virtually at the end, `resizeItem` compensates by the -// total-size delta and this predicate's verdict is ignored. This policy -// therefore only governs the detached reader. +// `useScrollFollow` is the sole owner of live bottom pinning. While following, +// this predicate rejects every virtualizer resize correction so one content +// growth batch cannot first move by an estimate delta and then pin again. // // It replicates the upstream default and carves out exactly one case the // default gets wrong: the live streaming row grown taller than the viewport. @@ -21,8 +20,7 @@ import type { VirtualItem, Virtualizer } from "@tanstack/react-virtual"; // measurement always compensates (the estimate→actual delta must land // regardless of scroll direction) and a re-measurement is skipped during // backward scroll (the upstream "items jump while scrolling up" fix); -// - while following, the compensation cooperates with the scroll-follow pin, -// so it stays on; +// - while following, all compensation is delegated to scroll-follow; // - live-row shrinks (delta < 0, e.g. a thinking block collapsing near the // row's top) keep compensating so content under the reader stays put. export type LiveRowScrollAdjustPolicyArgs = { @@ -45,6 +43,9 @@ export function createLiveRowScrollAdjustPolicy< ) => boolean { const { getLiveStartIndex, isFollowing } = args; return (item, delta, instance) => { + if (isFollowing()) { + return false; + } // Un-echoed scroll writes accumulate in a private field until the next // scroll event; the upstream default folds them into the comparison, so // mirror that (fall back to 0 if the field ever disappears). @@ -70,8 +71,7 @@ export function createLiveRowScrollAdjustPolicy< liveStartIndex >= 0 && item.index >= liveStartIndex && delta > 0 && - item.end > viewportTop && - !isFollowing() + item.end > viewportTop ) { return false; } diff --git a/crates/agent-gateway/web/src/pages/chat/assistant-bubble/RoundContent.tsx b/crates/agent-gateway/web/src/pages/chat/assistant-bubble/RoundContent.tsx index 9afdf1ad9..cf136c812 100644 --- a/crates/agent-gateway/web/src/pages/chat/assistant-bubble/RoundContent.tsx +++ b/crates/agent-gateway/web/src/pages/chat/assistant-bubble/RoundContent.tsx @@ -1,5 +1,6 @@ -import { memo, useEffect, useMemo, useRef, useState } from "react"; -import { ChevronRight, Lightbulb, RefreshCw } from "../../../components/icons"; +import { memo, useMemo, useState } from "react"; +import { ThinkingActivity } from "../../../components/chat/ThinkingActivity"; +import { ChevronRight, RefreshCw } from "../../../components/icons"; import { Markdown } from "../../../components/Markdown"; import { useLocale } from "../../../i18n"; import type { ChatFileLink } from "../../../lib/chat/chatFileLinks"; @@ -17,74 +18,6 @@ import { UsagePanel } from "./UsagePanel"; const EMPTY_RUNNING_TOOL_CALL_IDS: string[] = []; -const ThinkingBlock = memo(function ThinkingBlock({ - text, - open, - isRunning, - renderMode, - workdir, - onOpenFileLink, -}: { - text: string; - open?: boolean; - isRunning?: boolean; - renderMode: "streaming" | "static"; - workdir?: string; - onOpenFileLink?: (link: ChatFileLink) => void; -}) { - const hasText = /\S/.test(text || ""); - const { t } = useLocale(); - const [isOpen, setIsOpen] = useState(typeof open === "boolean" ? open : false); - const userInteractedRef = useRef(false); - useEffect(() => { - if (!userInteractedRef.current && typeof open === "boolean") { - setIsOpen(open); - } - }, [open]); - - if (!hasText) return null; - - return ( -
- - - {() => ( -
- -
- )} -
-
- ); -}); - // Expandable per-attempt stream-retry history for the live run, mirrored // from the desktop app's RetryDetailsBlock (agent-gui RoundContent.tsx). export const RetryDetailsBlock = memo(function RetryDetailsBlock({ @@ -261,10 +194,9 @@ export const RoundContent = memo(function RoundContent(props: { {visibleGroupedBlocks.map((block) => { if (block.kind === "thinking") { return ( - @@ -36,7 +36,9 @@ export function AssistantStatus({ aria-hidden="true" className={cn("h-3.5 w-3.5 shrink-0 animate-spin", iconClassName)} /> - {children} + + {children} + ); } diff --git a/crates/agent-gateway/web/src/pages/chat/assistant-bubble/ToolTraceGroup.tsx b/crates/agent-gateway/web/src/pages/chat/assistant-bubble/ToolTraceGroup.tsx index b01ccb6f9..7cb86f0d1 100644 --- a/crates/agent-gateway/web/src/pages/chat/assistant-bubble/ToolTraceGroup.tsx +++ b/crates/agent-gateway/web/src/pages/chat/assistant-bubble/ToolTraceGroup.tsx @@ -84,6 +84,19 @@ function ToolTraceGroupInner(props: { const ToolIcon = allBash ? Terminal : meta.Icon; const [open, setOpen] = useState(false); + if (items.length === 1) { + const item = items[0]; + return item ? ( + + ) : null; + } + const statusLabel = counts.failed > 0 ? `${counts.failed} ${t("chat.tool.failed")}` diff --git a/crates/agent-gateway/web/src/pages/chat/assistant-bubble/assistantBubbleUtils.ts b/crates/agent-gateway/web/src/pages/chat/assistant-bubble/assistantBubbleUtils.ts index 8ab692758..96a99023a 100644 --- a/crates/agent-gateway/web/src/pages/chat/assistant-bubble/assistantBubbleUtils.ts +++ b/crates/agent-gateway/web/src/pages/chat/assistant-bubble/assistantBubbleUtils.ts @@ -244,23 +244,14 @@ export function groupRoundBlocks(blocks: UiRound["blocks"]): GroupedRoundBlock[] const flushPendingTools = () => { if (pendingTools.length === 0) return; - if (pendingTools.length === 1) { - const item = pendingTools[0]; - groupedBlocks.push({ - kind: "tool", - key: `tool-${getToolTraceKey(item, pendingStartIndex)}`, - item, - }); - } else { - groupedBlocks.push({ - kind: "toolGroup", - // Anchored to the group's start only: appending tools to a streaming - // group must keep the key stable, or the remount would wipe the - // user's manual expand/collapse state mid-run. - key: `tool-group-${pendingStartIndex}-${getToolTraceKey(pendingTools[0], pendingStartIndex)}`, - items: pendingTools, - }); - } + groupedBlocks.push({ + kind: "toolGroup", + // The wrapper exists from the first ordinary tool onward. Appending a + // second tool therefore updates one activity in place instead of + // replacing a `tool` row with a differently keyed `toolGroup` row. + key: `tool-group-${getToolTraceKey(pendingTools[0], pendingStartIndex)}`, + items: pendingTools, + }); pendingTools = []; }; diff --git a/crates/agent-gateway/web/test/assistant-bubble-utils.test.mjs b/crates/agent-gateway/web/test/assistant-bubble-utils.test.mjs index 201d874b2..6844d65ed 100644 --- a/crates/agent-gateway/web/test/assistant-bubble-utils.test.mjs +++ b/crates/agent-gateway/web/test/assistant-bubble-utils.test.mjs @@ -7,7 +7,7 @@ import { createWebModuleLoader } from "../../test/helpers/load-web-module.mjs"; const rootDir = fileURLToPath(new URL("../", import.meta.url)); const loader = createWebModuleLoader({ rootDir }); const { BUILTIN_TOOL_CATALOG } = loader.loadModule("src/lib/tools/builtinToolCatalog.ts"); -const { isBuiltinShareToolName } = loader.loadModule( +const { groupRoundBlocks, isBuiltinShareToolName } = loader.loadModule( "src/pages/chat/assistant-bubble/assistantBubbleUtils.ts", ); @@ -18,3 +18,55 @@ test("shared history recognizes every catalog tool as builtin", () => { assert.equal(isBuiltinShareToolName("mcp_docs_search"), true); assert.equal(isBuiltinShareToolName("CustomTool"), false); }); + +test("ordinary tool activity keeps one group identity as later tools append", () => { + const tool = (id) => ({ + kind: "tool", + item: { toolCall: { type: "toolCall", id, name: "Bash", arguments: {} } }, + }); + const first = groupRoundBlocks([tool("call-1")]); + const appended = groupRoundBlocks([tool("call-1"), tool("call-2")]); + + assert.equal(first.length, 1); + assert.equal(appended.length, 1); + assert.equal(first[0].kind, "toolGroup"); + assert.equal(appended[0].kind, "toolGroup"); + assert.equal(appended[0].key, first[0].key); +}); + +test("special tool result updates preserve their direct activity identity", () => { + for (const name of ["TodoWrite", "AskUserQuestion", "Image", "Agent"]) { + const pendingItem = { + toolCall: { type: "toolCall", id: `call-${name}`, name, arguments: {} }, + }; + const settledItem = { + ...pendingItem, + toolResult: { + role: "toolResult", + toolCallId: `call-${name}`, + content: [], + isError: name === "Image", + }, + }; + const pending = groupRoundBlocks([{ kind: "tool", item: pendingItem }]); + const settled = groupRoundBlocks([{ kind: "tool", item: settledItem }]); + + assert.equal(pending.length, 1, name); + assert.equal(settled.length, 1, name); + assert.equal(pending[0].kind, "tool", name); + assert.equal(settled[0].kind, "tool", name); + assert.equal(settled[0].key, pending[0].key, name); + } +}); + +test("hosted search activity keeps one group identity as later searches append", () => { + const first = groupRoundBlocks([{ kind: "hostedSearch", item: { id: "search-1" } }]); + const appended = groupRoundBlocks([ + { kind: "hostedSearch", item: { id: "search-1" } }, + { kind: "hostedSearch", item: { id: "search-2" } }, + ]); + + assert.equal(first[0].kind, "hostedSearchGroup"); + assert.equal(appended[0].kind, "hostedSearchGroup"); + assert.equal(appended[0].key, first[0].key); +}); diff --git a/crates/agent-gateway/web/test/assistant-status.test.mjs b/crates/agent-gateway/web/test/assistant-status.test.mjs index b4d335a2b..8b046d3cc 100644 --- a/crates/agent-gateway/web/test/assistant-status.test.mjs +++ b/crates/agent-gateway/web/test/assistant-status.test.mjs @@ -24,8 +24,13 @@ const { AssistantStatus } = loader.loadModule( test("assistant running status keeps its spinner animated", () => { const status = AssistantStatus({ children: "Vibing" }); const icon = status.props.children[0]; + const text = status.props.children[1]; assert.equal(icon.type, Loader2); assert.match(icon.props.className, /(?:^|\s)animate-spin(?:\s|$)/); assert.doesNotMatch(icon.props.className, /(?:^|\s)motion-reduce:animate-none(?:\s|$)/); + assert.match(status.props.className, /(?:^|\s)min-w-0(?:\s|$)/); + assert.match(status.props.className, /(?:^|\s)max-w-full(?:\s|$)/); + assert.match(text.props.className, /(?:^|\s)truncate(?:\s|$)/); + assert.match(text.props.className, /(?:^|\s)whitespace-nowrap(?:\s|$)/); }); diff --git a/crates/agent-gateway/web/test/chat-file-links.test.mjs b/crates/agent-gateway/web/test/chat-file-links.test.mjs index dd12466dd..ea9eea710 100644 --- a/crates/agent-gateway/web/test/chat-file-links.test.mjs +++ b/crates/agent-gateway/web/test/chat-file-links.test.mjs @@ -83,6 +83,7 @@ test("Gateway historical and streaming rows keep the explicit file-open prop cha const files = [ "../src/app/GatewayApp.tsx", "../src/components/GatewayTranscript.tsx", + "../src/components/chat/ThinkingActivity.tsx", "../src/pages/chat/AssistantBubble.tsx", "../src/pages/chat/assistant-bubble/RoundContent.tsx", ]; @@ -96,8 +97,16 @@ test("Gateway historical and streaming rows keep the explicit file-open prop cha "utf8", ); assert.match(roundContent, /isStreaming \? "streaming" : "static"/); - assert.ok((roundContent.match(/onOpenFileLink=\{onOpenFileLink\}/g) ?? []).length >= 3); - assert.ok((roundContent.match(/workdir=\{workdir\}/g) ?? []).length >= 3); + assert.ok((roundContent.match(/onOpenFileLink=\{onOpenFileLink\}/g) ?? []).length >= 2); + assert.ok((roundContent.match(/workdir=\{workdir\}/g) ?? []).length >= 2); + + const thinkingActivity = fs.readFileSync( + fileURLToPath(new URL("../src/components/chat/ThinkingActivity.tsx", import.meta.url)), + "utf8", + ); + assert.match(thinkingActivity, / { + const callbacks = []; + let writes = 0; + const controller = createFramePinController( + () => { + writes += 1; + }, + (callback) => { + callbacks.push(callback); + return callbacks.length; + }, + () => {}, + ); + controller.schedule(); + controller.schedule(); + controller.schedule(); + assert.equal(callbacks.length, 1); + callbacks.shift()(); + assert.equal(writes, 1); +}); diff --git a/crates/agent-gateway/web/test/live-markdown-caret.test.mjs b/crates/agent-gateway/web/test/live-markdown-caret.test.mjs new file mode 100644 index 000000000..393e7cc0b --- /dev/null +++ b/crates/agent-gateway/web/test/live-markdown-caret.test.mjs @@ -0,0 +1,12 @@ +import assert from "node:assert/strict"; +import fs from "node:fs"; +import test from "node:test"; + +const roundContentSource = fs.readFileSync( + new URL("../src/pages/chat/assistant-bubble/RoundContent.tsx", import.meta.url), + "utf8", +); + +test("live assistant text does not render a trailing caret row", () => { + assert.doesNotMatch(roundContentSource, /showCaret=/); +}); diff --git a/crates/agent-gateway/web/test/live-scroll-adjust-policy.test.mjs b/crates/agent-gateway/web/test/live-scroll-adjust-policy.test.mjs index bd5603acd..7fe4853e1 100644 --- a/crates/agent-gateway/web/test/live-scroll-adjust-policy.test.mjs +++ b/crates/agent-gateway/web/test/live-scroll-adjust-policy.test.mjs @@ -78,10 +78,11 @@ test("detached reader inside the growing live row is left alone (streaming creep assert.equal(policy(item, 60, makeInstance({ scrollOffset: 3000, measuredKeys: [5] })), false); }); -test("the same live-row growth while following keeps compensating (pin assist)", () => { +test("following delegates every resize correction to the scroll-follow owner", () => { const policy = makePolicy({ liveStartIndex: 5, following: true }); const item = makeItem({ index: 5, start: 400, size: 5000 }); - assert.equal(policy(item, 60, makeInstance({ scrollOffset: 3000, measuredKeys: [5] })), true); + assert.equal(policy(item, 60, makeInstance({ scrollOffset: 3000, measuredKeys: [5] })), false); + assert.equal(policy(item, -80, makeInstance({ scrollOffset: 3000, measuredKeys: [5] })), false); }); test("live-row shrink keeps compensating so content under the reader stays put", () => { diff --git a/crates/agent-gateway/web/test/live-status-layout.test.mjs b/crates/agent-gateway/web/test/live-status-layout.test.mjs new file mode 100644 index 000000000..2a412d624 --- /dev/null +++ b/crates/agent-gateway/web/test/live-status-layout.test.mjs @@ -0,0 +1,20 @@ +import assert from "node:assert/strict"; +import fs from "node:fs"; +import test from "node:test"; + +const transcriptSource = fs.readFileSync( + new URL("../src/components/GatewayTranscript.tsx", import.meta.url), + "utf8", +); + +test("the streaming assistant always owns one stable live-status footer", () => { + assert.doesNotMatch(transcriptSource, /function shouldShowLiveStatusForRounds/); + assert.match( + transcriptSource, + /isLatestLiveStreaming\s*\?\s*\(\s* { + const above = resolveThinkingOverlayPlacement( + { left: 200, right: 700, top: 500, bottom: 532, width: 500, height: 32 }, + { width: 1200, height: 800 }, + ); + assert.equal(above.side, "above"); + const narrow = resolveThinkingOverlayPlacement( + { left: 8, right: 312, top: 60, bottom: 92, width: 304, height: 32 }, + { width: 320, height: 480 }, + ); + assert.equal(narrow.width, 296); +}); + +test("keeps a renderable overlay inside an extremely narrow viewport", () => { + const placement = resolveThinkingOverlayPlacement( + { left: 0, right: 8, top: 60, bottom: 92, width: 8, height: 32 }, + { width: 8, height: 480 }, + ); + assert.equal(placement.left, 3.5); + assert.equal(placement.width, 1); + assert.ok(placement.left + placement.width <= 8); +}); + +test("thinking details use a portal overlay instead of inline collapse", () => { + assert.match(componentSource, /createPortal/); + assert.match(componentSource, /role="dialog"/); + assert.match(componentSource, /className="fixed/); + assert.doesNotMatch(componentSource, /LazyCollapse/); +}); diff --git a/crates/agent-gateway/web/test/transcript-rows.test.mjs b/crates/agent-gateway/web/test/transcript-rows.test.mjs index c7ef4222a..fc8ca1a5c 100644 --- a/crates/agent-gateway/web/test/transcript-rows.test.mjs +++ b/crates/agent-gateway/web/test/transcript-rows.test.mjs @@ -115,6 +115,116 @@ test("buildTurnRows emits the user bubble before any assistant content, tagged w assert.equal(rows[1].turnKey, "req:c1"); }); +test("interleaved thinking and tool results keep one assistant row and stable block identities", () => { + const prefixEntries = [ + { id: "think-1", kind: "thinking", text: "reasoning", round: 1 }, + { + id: "tool-call-1", + kind: "tool_call", + round: 1, + toolCall: { type: "toolCall", id: "call-1", name: "Bash", arguments: {} }, + }, + ]; + const prefix = buildRowsFromEntries(prefixEntries, "stream"); + const complete = buildRowsFromEntries( + [ + ...prefixEntries, + { + id: "tool-result-1", + kind: "tool_result", + round: 1, + toolResult: { + role: "toolResult", + toolCallId: "call-1", + content: [], + isError: false, + }, + }, + { id: "think-2", kind: "thinking", text: "next reasoning", round: 1 }, + ], + "stream", + ); + + assert.equal(prefix.length, 1); + assert.equal(complete.length, 1); + assert.equal(complete[0].key, prefix[0].key); + const blockIdentity = (row) => + row.rounds[0].blocks.map((block) => + block.kind === "tool" ? `tool:${block.item.toolCall.id}` : `${block.kind}:${block.id}`, + ); + assert.deepEqual(blockIdentity(complete[0]).slice(0, 2), blockIdentity(prefix[0])); + assert.equal(complete[0].rounds[0].blocks.at(-1).id, "thinking-2"); +}); + +test("out-of-order and duplicate tool results update their first-seen tools in place", () => { + let turn = createTurn({ key: "req:out-of-order", runId: "run-out-of-order" }); + turn = applyEventToTurn(turn, { type: "thinking", text: "before tools", round: 1 }); + turn = applyEventToTurn(turn, { + type: "tool_call", + id: "call-a", + name: "Bash", + arguments: { command: "A" }, + round: 1, + }); + turn = applyEventToTurn(turn, { + type: "tool_call", + id: "call-b", + name: "Read", + arguments: { path: "B" }, + round: 1, + }); + const prefix = buildTurnRows(turn).find((row) => row.kind === "assistant"); + assert.ok(prefix); + const prefixBlocks = prefix.rounds[0].blocks.map((block) => + block.kind === "tool" ? `tool:${block.item.toolCall.id}` : `${block.kind}:${block.id}`, + ); + + const resultB = { + type: "tool_result", + id: "call-b", + name: "Read", + content: [{ type: "text", text: "B complete" }], + isError: false, + round: 1, + }; + turn = applyEventToTurn(turn, resultB); + const afterFirstB = turn; + turn = applyEventToTurn(turn, resultB); + assert.deepEqual(turn.entries, afterFirstB.entries, "duplicate result is idempotent"); + turn = applyEventToTurn(turn, { + type: "tool_result", + id: "call-a", + name: "Bash", + content: [{ type: "text", text: "A failed" }], + isError: true, + round: 1, + }); + turn = applyEventToTurn(turn, { type: "thinking", text: "after tools", round: 1 }); + + const complete = buildTurnRows(turn).find((row) => row.kind === "assistant"); + assert.ok(complete); + assert.equal(complete.key, prefix.key); + const completeBlocks = complete.rounds[0].blocks; + assert.deepEqual( + completeBlocks.slice(0, prefixBlocks.length).map((block) => + block.kind === "tool" ? `tool:${block.item.toolCall.id}` : `${block.kind}:${block.id}`, + ), + prefixBlocks, + ); + const trace = completeBlocks + .filter((block) => block.kind === "tool") + .map((block) => ({ + id: block.item.toolCall.id, + result: block.item.toolResult?.content?.[0]?.text, + isError: block.item.toolResult?.isError, + })); + assert.deepEqual(trace, [ + { id: "call-a", result: "A failed", isError: true }, + { id: "call-b", result: "B complete", isError: false }, + ]); + assert.equal(completeBlocks.at(-1).kind, "thinking"); +}); + test("dedupeRowKeys suffixes collisions deterministically without touching unique keys", () => { const rows = [ { key: "a", origin: "history", kind: "error", text: "1" }, diff --git a/crates/agent-gui/src/components/chat/ThinkingActivity.tsx b/crates/agent-gui/src/components/chat/ThinkingActivity.tsx new file mode 100644 index 000000000..8389245df --- /dev/null +++ b/crates/agent-gui/src/components/chat/ThinkingActivity.tsx @@ -0,0 +1,149 @@ +import { useCallback, useId, useLayoutEffect, useRef, useState } from "react"; +import { createPortal } from "react-dom"; +import { useLocale } from "../../i18n"; +import type { ChatFileLink } from "../../lib/chat/chatFileLinks"; +import { + resolveThinkingOverlayPlacement, + type ThinkingOverlayPlacement, +} from "../../lib/chat/thinkingOverlayModel"; +import { ChevronRight, Lightbulb } from "../icons"; +import { Markdown } from "../Markdown"; + +export function ThinkingActivity(props: { + text: string; + isRunning?: boolean; + renderMode: "streaming" | "static"; + workdir?: string; + onOpenFileLink?: (link: ChatFileLink) => void; +}) { + const { text, isRunning = false, renderMode, workdir, onOpenFileLink } = props; + const { t } = useLocale(); + const [open, setOpen] = useState(false); + const [placement, setPlacement] = useState(null); + const triggerRef = useRef(null); + const panelRef = useRef(null); + const panelId = useId(); + const hasText = /\S/.test(text); + + const updatePlacement = useCallback(() => { + const trigger = triggerRef.current; + if (!trigger) return; + setPlacement( + resolveThinkingOverlayPlacement(trigger.getBoundingClientRect(), { + width: window.innerWidth, + height: window.innerHeight, + }), + ); + }, []); + + const close = useCallback((restoreFocus = false) => { + setOpen(false); + setPlacement(null); + if (restoreFocus) { + requestAnimationFrame(() => triggerRef.current?.focus({ preventScroll: true })); + } + }, []); + + useLayoutEffect(() => { + if (!open) return; + updatePlacement(); + const focusFrame = requestAnimationFrame(() => + panelRef.current?.focus({ preventScroll: true }), + ); + const handlePointerDown = (event: PointerEvent) => { + const target = event.target; + if (!(target instanceof Node)) return; + if (triggerRef.current?.contains(target) || panelRef.current?.contains(target)) return; + close(); + }; + const handleFocusIn = (event: FocusEvent) => { + const target = event.target; + if (!(target instanceof Node)) return; + if (triggerRef.current?.contains(target) || panelRef.current?.contains(target)) return; + close(); + }; + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key !== "Escape") return; + event.preventDefault(); + event.stopPropagation(); + close(true); + }; + window.addEventListener("pointerdown", handlePointerDown, true); + window.addEventListener("focusin", handleFocusIn, true); + window.addEventListener("keydown", handleKeyDown, true); + window.addEventListener("resize", updatePlacement); + window.addEventListener("scroll", updatePlacement, true); + return () => { + cancelAnimationFrame(focusFrame); + window.removeEventListener("pointerdown", handlePointerDown, true); + window.removeEventListener("focusin", handleFocusIn, true); + window.removeEventListener("keydown", handleKeyDown, true); + window.removeEventListener("resize", updatePlacement); + window.removeEventListener("scroll", updatePlacement, true); + }; + }, [close, open, updatePlacement]); + + if (!hasText) return null; + + return ( +
+ + {open && placement + ? createPortal( + , + document.body, + ) + : null} +
+ ); +} diff --git a/crates/agent-gui/src/lib/chat-scroll/framePinController.ts b/crates/agent-gui/src/lib/chat-scroll/framePinController.ts new file mode 100644 index 000000000..c92bd5440 --- /dev/null +++ b/crates/agent-gui/src/lib/chat-scroll/framePinController.ts @@ -0,0 +1,31 @@ +export type ScheduleFrame = (callback: () => void) => number; +export type CancelFrame = (handle: number) => void; + +export function createFramePinController( + write: () => void, + scheduleFrame: ScheduleFrame, + cancelFrame: CancelFrame, +) { + let pendingFrame: number | null = null; + + const cancel = () => { + if (pendingFrame === null) return; + cancelFrame(pendingFrame); + pendingFrame = null; + }; + + const schedule = () => { + if (pendingFrame !== null) return; + pendingFrame = scheduleFrame(() => { + pendingFrame = null; + write(); + }); + }; + + const flush = () => { + cancel(); + write(); + }; + + return { cancel, flush, schedule }; +} diff --git a/crates/agent-gui/src/lib/chat-scroll/useScrollFollow.ts b/crates/agent-gui/src/lib/chat-scroll/useScrollFollow.ts index 78b0eac76..302e2b72c 100644 --- a/crates/agent-gui/src/lib/chat-scroll/useScrollFollow.ts +++ b/crates/agent-gui/src/lib/chat-scroll/useScrollFollow.ts @@ -1,5 +1,5 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; - +import { createFramePinController } from "./framePinController"; import { createFollowState, DEFAULT_FOLLOW_CONFIG, @@ -113,6 +113,18 @@ export function useScrollFollow(args: UseScrollFollowArgs): { configRef.current = { ...DEFAULT_FOLLOW_CONFIG, ...args.config }; const [following, setFollowing] = useState(true); const jumpRafRef = useRef(null); + const pinController = useMemo( + () => + createFramePinController( + () => { + const el = boundViewportRef.current; + if (el) el.scrollTop = el.scrollHeight; + }, + (callback) => requestAnimationFrame(callback), + (handle) => cancelAnimationFrame(handle), + ), + [], + ); const cancelJumpAnimation = useCallback(() => { if (jumpRafRef.current !== null) { @@ -124,25 +136,28 @@ export function useScrollFollow(args: UseScrollFollowArgs): { const pinToBottom = useCallback(() => { // An instant pin supersedes any in-flight jump animation. cancelJumpAnimation(); - const el = boundViewportRef.current; - if (el) { - el.scrollTop = el.scrollHeight; - } - }, [cancelJumpAnimation]); + pinController.flush(); + }, [cancelJumpAnimation, pinController]); + + const schedulePinToBottom = useCallback(() => { + cancelJumpAnimation(); + pinController.schedule(); + }, [cancelJumpAnimation, pinController]); const dispatch = useCallback( - (event: FollowEvent) => { + (event: FollowEvent, pinMode: "immediate" | "frame" = "immediate") => { const wasFollowing = stateRef.current.following; const step = reduceFollowEvent(stateRef.current, event, configRef.current); stateRef.current = step.state; if (step.pin) { - pinToBottom(); + if (pinMode === "frame") schedulePinToBottom(); + else pinToBottom(); } if (step.state.following !== wasFollowing) { setFollowing(step.state.following); } }, - [pinToBottom], + [pinToBottom, schedulePinToBottom], ); const stickToBottom = useCallback(() => { @@ -350,7 +365,7 @@ export function useScrollFollow(args: UseScrollFollowArgs): { typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => { - dispatch({ type: "contentGrowth", gap: getGap() }); + dispatch({ type: "contentGrowth", gap: getGap() }, "frame"); }); resizeObserver?.observe(viewport); if (growthTarget instanceof Element) { @@ -372,6 +387,7 @@ export function useScrollFollow(args: UseScrollFollowArgs): { } document.removeEventListener("visibilitychange", handleVisibilityChange); resizeObserver?.disconnect(); + pinController.cancel(); cancelJumpAnimation(); boundViewportRef.current = null; }; @@ -382,6 +398,7 @@ export function useScrollFollow(args: UseScrollFollowArgs): { enabled, listenerRoot, pinToBottom, + pinController, trackKeys, viewport, ]); diff --git a/crates/agent-gui/src/lib/chat/thinkingOverlayModel.ts b/crates/agent-gui/src/lib/chat/thinkingOverlayModel.ts new file mode 100644 index 000000000..9afe7ab3f --- /dev/null +++ b/crates/agent-gui/src/lib/chat/thinkingOverlayModel.ts @@ -0,0 +1,59 @@ +export type ThinkingOverlayRect = { + left: number; + right: number; + top: number; + bottom: number; + width: number; + height: number; +}; + +export type ThinkingOverlayViewport = { width: number; height: number }; + +export type ThinkingOverlayPlacement = { + side: "above" | "below"; + left: number; + width: number; + maxHeight: number; + top?: number; + bottom?: number; +}; + +const VIEWPORT_MARGIN_PX = 12; +const OVERLAY_GAP_PX = 8; +const MAX_OVERLAY_WIDTH_PX = 640; +const MIN_PREFERRED_HEIGHT_PX = 180; + +export function resolveThinkingOverlayPlacement( + trigger: ThinkingOverlayRect, + viewport: ThinkingOverlayViewport, +): ThinkingOverlayPlacement { + const viewportWidth = Math.max(1, viewport.width); + const horizontalMargin = Math.min(VIEWPORT_MARGIN_PX, Math.max(0, (viewportWidth - 1) / 2)); + const availableWidth = Math.max(1, viewportWidth - horizontalMargin * 2); + const width = Math.min(MAX_OVERLAY_WIDTH_PX, availableWidth); + const centeredLeft = trigger.left + (trigger.width - width) / 2; + const left = Math.min( + Math.max(horizontalMargin, centeredLeft), + Math.max(horizontalMargin, viewportWidth - horizontalMargin - width), + ); + const above = Math.max(0, trigger.top - OVERLAY_GAP_PX - VIEWPORT_MARGIN_PX); + const below = Math.max(0, viewport.height - trigger.bottom - OVERLAY_GAP_PX - VIEWPORT_MARGIN_PX); + const side = above >= MIN_PREFERRED_HEIGHT_PX || above >= below ? "above" : "below"; + + if (side === "above") { + return { + side, + left, + width, + maxHeight: above, + bottom: viewport.height - trigger.top + OVERLAY_GAP_PX, + }; + } + return { + side, + left, + width, + maxHeight: below, + top: trigger.bottom + OVERLAY_GAP_PX, + }; +} diff --git a/crates/agent-gui/src/lib/transcript-virtual/liveScrollAdjustPolicy.ts b/crates/agent-gui/src/lib/transcript-virtual/liveScrollAdjustPolicy.ts index d2ad8f63e..a03eb7864 100644 --- a/crates/agent-gui/src/lib/transcript-virtual/liveScrollAdjustPolicy.ts +++ b/crates/agent-gui/src/lib/transcript-virtual/liveScrollAdjustPolicy.ts @@ -3,10 +3,9 @@ import type { VirtualItem, Virtualizer } from "@tanstack/react-virtual"; // Resize-compensation policy for the transcript virtualizer (virtual-core // 3.17.x semantics). // -// With `anchorTo: 'end'`, virtual-core handles the bottom-pinned case itself: -// while the viewport is virtually at the end, `resizeItem` compensates by the -// total-size delta and this predicate's verdict is ignored. This policy -// therefore only governs the detached reader. +// `useScrollFollow` is the sole owner of live bottom pinning. While following, +// this predicate rejects every virtualizer resize correction so one content +// growth batch cannot first move by an estimate delta and then pin again. // // It replicates the upstream default and carves out exactly one case the // default gets wrong: the live streaming row grown taller than the viewport. @@ -21,8 +20,7 @@ import type { VirtualItem, Virtualizer } from "@tanstack/react-virtual"; // measurement always compensates (the estimate→actual delta must land // regardless of scroll direction) and a re-measurement is skipped during // backward scroll (the upstream "items jump while scrolling up" fix); -// - while following, the compensation cooperates with the scroll-follow pin, -// so it stays on; +// - while following, all compensation is delegated to scroll-follow; // - live-row shrinks (delta < 0, e.g. a thinking block collapsing near the // row's top) keep compensating so content under the reader stays put. export type LiveRowScrollAdjustPolicyArgs = { @@ -45,6 +43,9 @@ export function createLiveRowScrollAdjustPolicy< ) => boolean { const { getLiveStartIndex, isFollowing } = args; return (item, delta, instance) => { + if (isFollowing()) { + return false; + } // Un-echoed scroll writes accumulate in a private field until the next // scroll event; the upstream default folds them into the comparison, so // mirror that (fall back to 0 if the field ever disappears). @@ -70,8 +71,7 @@ export function createLiveRowScrollAdjustPolicy< liveStartIndex >= 0 && item.index >= liveStartIndex && delta > 0 && - item.end > viewportTop && - !isFollowing() + item.end > viewportTop ) { return false; } diff --git a/crates/agent-gui/src/pages/chat/components/AssistantBubble.tsx b/crates/agent-gui/src/pages/chat/components/AssistantBubble.tsx index 85236e056..53412de59 100644 --- a/crates/agent-gui/src/pages/chat/components/AssistantBubble.tsx +++ b/crates/agent-gui/src/pages/chat/components/AssistantBubble.tsx @@ -38,36 +38,13 @@ export const AssistantBubbleUnit = memo(function AssistantBubbleUnit(props: { const isVibingStatus = toolStatus === VIBING_STATUS; let status: ReactNode = null; - if (row.mutable && unit.kind === "placeholder") { - if (unit.showFallbackStatus) { - status = isCompactionRunning ? ( - - ) : isVibingStatus || !toolStatus ? ( - - ) : ( - {toolStatus} - ); - } else if (toolStatus) { - status = isCompactionRunning ? ( - - ) : isVibingStatus ? ( - - ) : ( - {toolStatus} - ); - } - } else if ( - row.mutable && - unit.kind === "block" && - toolStatus && - (!unit.hasRunningToolCall || isCompactionRunning || isVibingStatus) - ) { + if (unit.kind === "status") { status = isCompactionRunning ? ( - - ) : isVibingStatus ? ( - + + ) : isVibingStatus || !toolStatus ? ( + ) : ( - {toolStatus} + {toolStatus} ); } @@ -80,14 +57,10 @@ export const AssistantBubbleUnit = memo(function AssistantBubbleUnit(props: { )}
- {status ?
{status}
: null} + {status ?
{status}
: null} {row.mutable && retryAttempts && retryAttempts.length > 0 ? ( @@ -97,7 +70,6 @@ export const AssistantBubbleUnit = memo(function AssistantBubbleUnit(props: { void; -}) { - const hasText = /\S/.test(text || ""); - const { t } = useLocale(); - const [isOpen, setIsOpen] = useState(typeof open === "boolean" ? open : false); - const userInteractedRef = useRef(false); - useEffect(() => { - if (!userInteractedRef.current && typeof open === "boolean") { - setIsOpen(open); - } - }, [open]); - - if (!hasText) return null; - - return ( -
- - - {() => ( -
- -
- )} -
-
- ); -}); - export const RetryDetailsBlock = memo(function RetryDetailsBlock({ attempts, }: { @@ -132,7 +64,6 @@ export const RetryDetailsBlock = memo(function RetryDetailsBlock({ export const RoundBlockContent = memo(function RoundBlockContent(props: { block: GroupedRoundBlock; isLive: boolean; - isMutable: boolean; renderMode: "streaming" | "static"; runningToolCallIds: string[]; thinkingOpen: boolean; @@ -144,7 +75,6 @@ export const RoundBlockContent = memo(function RoundBlockContent(props: { const { block, isLive, - isMutable, renderMode, runningToolCallIds, thinkingOpen, @@ -158,9 +88,8 @@ export const RoundBlockContent = memo(function RoundBlockContent(props: { if (block.kind === "thinking") { const isRunning = isLive && thinkingOpen && isLatestThinking; content = ( - diff --git a/crates/agent-gui/src/pages/chat/components/assistant-bubble/StatusText.tsx b/crates/agent-gui/src/pages/chat/components/assistant-bubble/StatusText.tsx index f06adc85f..4546a4002 100644 --- a/crates/agent-gui/src/pages/chat/components/assistant-bubble/StatusText.tsx +++ b/crates/agent-gui/src/pages/chat/components/assistant-bubble/StatusText.tsx @@ -28,7 +28,7 @@ export function AssistantStatus({ @@ -39,7 +39,9 @@ export function AssistantStatus({ iconClassName, )} /> - {children} + + {children} + ); } diff --git a/crates/agent-gui/src/pages/chat/components/assistant-bubble/ToolTraceGroup.tsx b/crates/agent-gui/src/pages/chat/components/assistant-bubble/ToolTraceGroup.tsx index 37d546a50..2e0c0e40e 100644 --- a/crates/agent-gui/src/pages/chat/components/assistant-bubble/ToolTraceGroup.tsx +++ b/crates/agent-gui/src/pages/chat/components/assistant-bubble/ToolTraceGroup.tsx @@ -36,6 +36,17 @@ function ToolTraceGroupInner(props: { const ToolIcon = allBash ? Terminal : meta.Icon; const [open, setOpen] = useState(false); + if (items.length === 1) { + const item = items[0]; + return item ? ( + + ) : null; + } + const statusLabel = counts.failed > 0 ? `${counts.failed} ${t("chat.tool.failed")}` diff --git a/crates/agent-gui/src/pages/chat/components/assistant-bubble/assistantBubbleUtils.ts b/crates/agent-gui/src/pages/chat/components/assistant-bubble/assistantBubbleUtils.ts index c7caf6562..2dc0cec1f 100644 --- a/crates/agent-gui/src/pages/chat/components/assistant-bubble/assistantBubbleUtils.ts +++ b/crates/agent-gui/src/pages/chat/components/assistant-bubble/assistantBubbleUtils.ts @@ -277,23 +277,14 @@ export function groupRoundBlocks(blocks: UiRound["blocks"]): GroupedRoundBlock[] const flushPendingTools = () => { if (pendingTools.length === 0) return; - if (pendingTools.length === 1) { - const item = pendingTools[0]; - groupedBlocks.push({ - kind: "tool", - key: `tool-${getToolTraceKey(item, pendingStartIndex)}`, - item, - }); - } else { - groupedBlocks.push({ - kind: "toolGroup", - // Anchored to the group's start only: appending tools to a streaming - // group must keep the key stable, or the remount would wipe the - // user's manual expand/collapse state mid-run. - key: `tool-group-${pendingStartIndex}-${getToolTraceKey(pendingTools[0], pendingStartIndex)}`, - items: pendingTools, - }); - } + groupedBlocks.push({ + kind: "toolGroup", + // The wrapper exists from the first ordinary tool onward. Appending a + // second tool therefore updates one activity in place instead of + // replacing a `tool` row with a differently keyed `toolGroup` row. + key: `tool-group-${getToolTraceKey(pendingTools[0], pendingStartIndex)}`, + items: pendingTools, + }); pendingTools = []; }; diff --git a/crates/agent-gui/src/pages/chat/transcript/AssistantActivityRow.tsx b/crates/agent-gui/src/pages/chat/transcript/AssistantActivityRow.tsx new file mode 100644 index 000000000..1390aafb8 --- /dev/null +++ b/crates/agent-gui/src/pages/chat/transcript/AssistantActivityRow.tsx @@ -0,0 +1,65 @@ +import { memo } from "react"; + +import type { ChatFileLink } from "../../../lib/chat/chatFileLinks"; +import type { HistoryMessageRef } from "../../../lib/chat/conversation/conversationState"; +import type { RetryAttemptRecord } from "../../../lib/chat/conversation/liveTranscriptStore"; +import type { PendingUploadedFile } from "../../../lib/chat/messages/uploadedFiles"; +import { AssistantRenderUnit } from "./AssistantRenderUnit"; +import type { AssistantActivityRow as AssistantActivityRowModel } from "./rowModel"; + +export const AssistantActivityRow = memo(function AssistantActivityRow(props: { + row: AssistantActivityRowModel; + showUsage?: boolean; + usageContextWindow?: number; + isAgentMode: boolean; + isCompactionRunning: boolean; + toolStatus: string | null; + retryAttempts?: RetryAttemptRecord[]; + workdir?: string; + onOpenFileLink?: (link: ChatFileLink) => void; + onResendFromEdit: ( + messageRef: HistoryMessageRef, + text: string, + attachments: PendingUploadedFile[], + ) => void; + onBranchConversation?: (messageRef: HistoryMessageRef) => void; +}) { + const { + row, + showUsage, + usageContextWindow, + isAgentMode, + isCompactionRunning, + toolStatus, + retryAttempts, + workdir, + onOpenFileLink, + onResendFromEdit, + onBranchConversation, + } = props; + + return ( +
+ {row.units.map((unit, index) => ( +
+ + {unit.gapAfter > 0 && index < row.units.length - 1 ? ( + + ))} +
+ ); +}); diff --git a/crates/agent-gui/src/pages/chat/transcript/ChatTranscript.tsx b/crates/agent-gui/src/pages/chat/transcript/ChatTranscript.tsx index bf3fb1335..32070a9fd 100644 --- a/crates/agent-gui/src/pages/chat/transcript/ChatTranscript.tsx +++ b/crates/agent-gui/src/pages/chat/transcript/ChatTranscript.tsx @@ -317,6 +317,7 @@ export const ChatTranscript = memo(function ChatTranscript(props: ChatTranscript scrollViewport={scrollViewport} layoutWidth={contentWidth} isViewportFollowing={scrollFollowHandle.isFollowing} + viewportFollowing={following} isSending={isSending} isAgentMode={isAgentMode} isCompactionRunning={isCompactionRunning} diff --git a/crates/agent-gui/src/pages/chat/transcript/TranscriptList.tsx b/crates/agent-gui/src/pages/chat/transcript/TranscriptList.tsx index 6f775dc14..2f1ba1e8c 100644 --- a/crates/agent-gui/src/pages/chat/transcript/TranscriptList.tsx +++ b/crates/agent-gui/src/pages/chat/transcript/TranscriptList.tsx @@ -36,12 +36,13 @@ import { buildTranscriptLayoutKey, createTranscriptMeasurementsLru, } from "../../../lib/transcript-virtual/measurementsLru"; +import { AssistantActivityRow } from "./AssistantActivityRow"; import { AssistantRenderUnit } from "./AssistantRenderUnit"; import { extractRenderUnitRange } from "./renderUnitRangeExtractor"; import { createTranscriptRowModel } from "./rowModel"; import { UserMessageRow } from "./UserMessageRow"; -const TRANSCRIPT_MEASUREMENT_LAYOUT_VERSION = "assistant-units-v1"; +const TRANSCRIPT_MEASUREMENT_LAYOUT_VERSION = "assistant-activity-v2"; function buildVersionedTranscriptLayoutKey(viewportWidth: number, contentWidth: number) { const layoutKey = buildTranscriptLayoutKey(viewportWidth, contentWidth); @@ -111,6 +112,7 @@ export type TranscriptListProps = { // Whether the scroll-follow engine is attached to the bottom; gates the // virtualizer's resize-compensation carve-out for live-row growth. isViewportFollowing?: () => boolean; + viewportFollowing: boolean; isSending: boolean; isAgentMode: boolean; isCompactionRunning: boolean; @@ -137,8 +139,8 @@ export type TranscriptListProps = { }; // The whole transcript lives in one virtualized container. Assistant replies -// are block-level render units, so a long reply no longer becomes one giant -// row; only its mutable live tail stays force-mounted. +// are block-level render units. The currently active reply is one stable outer +// activity row; static history keeps block-level virtualization. export const TranscriptList = memo(function TranscriptList(props: TranscriptListProps) { const { conversationId, @@ -147,6 +149,7 @@ export const TranscriptList = memo(function TranscriptList(props: TranscriptList scrollViewport, layoutWidth, isViewportFollowing, + viewportFollowing, isSending, isAgentMode, isCompactionRunning, @@ -282,23 +285,18 @@ export const TranscriptList = memo(function TranscriptList(props: TranscriptList initialMeasurementsCache, directDomUpdates: true, directDomUpdatesMode: "transform", - // End-anchored: while the viewport sits within the threshold of the end, - // growth of the last row (streaming) compensates by the total-size delta - // upstream, and estimate→measure corrections keep the bottom pinned. The - // threshold matches scrollFollowCore's BOTTOM_ATTACH_THRESHOLD_PX so both - // engines agree on what "at the bottom" means. followOnAppend stays off: - // its DOM-distance re-follow would conflict with the follow reducer's - // "shrink clamps never re-attach" contract — appends while following are - // already pinned by the reducer. - anchorTo: "end", + // End anchoring is enabled only for a detached reader so keyed prepends + // preserve the visible row. While following, start anchoring disables the + // virtualizer's bottom correction and leaves live growth to useScrollFollow. + anchorTo: viewportFollowing ? "start" : "end", scrollEndThreshold: 8, rangeExtractor: extractVirtualRange, }); // TanStack exposes the resize-compensation predicate as an instance field, // not an option; reassigning per render keeps the closure's inputs current. - // It only governs the detached reader — while virtually at the end, the - // upstream end-anchor compensation takes priority over this predicate. + // While following it rejects every virtualizer correction; while detached + // it retains estimate/measurement anchoring for rows above the viewport. virtualizer.shouldAdjustScrollPositionOnItemSizeChange = createLiveRowScrollAdjustPolicy({ getLiveStartIndex: () => liveStartIndexRef.current, isFollowing: () => isViewportFollowing?.() ?? false, @@ -514,6 +512,24 @@ export const TranscriptList = memo(function TranscriptList(props: TranscriptList />
); + } else if (row.kind === "assistant-activity") { + body = ( +
+ +
+ ); } else { body = (
@@ -537,6 +553,7 @@ export const TranscriptList = memo(function TranscriptList(props: TranscriptList return (
total + unit.estimate + (index < lastIndex ? unit.gapAfter : 0), + 0, + ), + renderCost: Math.min( + 32, + Math.max( + 1, + units.reduce((total, unit) => total + unit.renderCost, 0), + ), + ), + gapAfter: units.at(-1)?.gapAfter ?? TRANSCRIPT_ROW_GAP_PX, + anchorUserKey: units[0]?.anchorUserKey ?? null, + live: units.some((unit) => unit.live), + units, + }; +} + type BuildAssistantUnitsInput = { replyKey: string; live: boolean; @@ -296,7 +340,7 @@ function buildAssistantUnits(input: BuildAssistantUnitsInput): AssistantUnitRow[ const isAborted = rounds.some((round) => round.meta?.stopReason === "aborted"); const rows: AssistantUnitRow[] = []; - rounds.forEach((round, roundIndex) => { + rounds.forEach((round) => { const groupedBlocks = groupRoundBlocks(round.blocks).filter((block) => isVisibleGroupedBlock(block, latestTodoItem), ); @@ -340,33 +384,23 @@ function buildAssistantUnits(input: BuildAssistantUnitsInput): AssistantUnitRow[ }, }); }); + }); - if (live && roundIndex === rounds.length - 1 && groupedBlocks.length === 0) { - rows.push({ - kind: "assistant-unit", - key: `${replyKey}:round:${round.key}:placeholder`, - replyKey, - estimate: 64, - renderCost: 1, - gapAfter: TRANSCRIPT_ROW_GAP_PX, - anchorUserKey, - live: true, + if (live) { + const contentTailIndex = rows.length - 1; + const contentTail = rows[contentTailIndex]; + if (contentTail) { + rows[contentTailIndex] = { + ...contentTail, + gapAfter: ASSISTANT_UNIT_GAP_PX, mutable: true, - renderMode, - compacted, - showAvatar: rows.length === 0, - isAborted, - unit: { kind: "placeholder", showFallbackStatus: false }, - }); + }; } - }); - - if (live && rows.length === 0) { rows.push({ kind: "assistant-unit", - key: `${replyKey}:placeholder`, + key: `${replyKey}:footer`, replyKey, - estimate: 64, + estimate: rows.length === 0 ? 64 : 32, renderCost: 1, gapAfter: TRANSCRIPT_ROW_GAP_PX, anchorUserKey, @@ -374,21 +408,10 @@ function buildAssistantUnits(input: BuildAssistantUnitsInput): AssistantUnitRow[ mutable: true, renderMode, compacted, - showAvatar: true, + showAvatar: rows.length === 0, isAborted, - unit: { kind: "placeholder", showFallbackStatus: true }, + unit: { kind: "status" }, }); - } else if (live) { - const tailIndex = rows.length - 1; - const tail = rows[tailIndex]; - if (tail) { - rows[tailIndex] = { - ...tail, - estimate: tail.estimate + 36, - gapAfter: TRANSCRIPT_ROW_GAP_PX, - mutable: true, - }; - } } else { const changedFilesCandidate = hasChangedFilesCandidate(rounds); const contentTailIndex = rows.length - 1; @@ -467,8 +490,11 @@ export function createTranscriptRowModel(options?: TranscriptRowModelOptions): T replyKey: string; historyLenAtStart: number; liveUnitCache: Map; + lastLiveUnits: AssistantUnitRow[]; + settlingUnits: AssistantUnitRow[] | null; } | null = null; let pendingSettle: { replyKey: string; historyLenAtStart: number } | null = null; + let deferredSettles: { replyKey: string; historyLenAtStart: number }[] = []; let draftRoundCache: { text: string; round: LiveRound } | null = null; const reset = () => { @@ -480,6 +506,7 @@ export function createTranscriptRowModel(options?: TranscriptRowModelOptions): T turnSeq = 0; activeTurn = null; pendingSettle = null; + deferredSettles = []; draftRoundCache = null; }; @@ -505,7 +532,7 @@ export function createTranscriptRowModel(options?: TranscriptRowModelOptions): T ) => { for (let index = historyItems.length - 1; index >= turn.historyLenAtStart; index -= 1) { const item = historyItems[index]; - if (item?.kind === "assistant") { + if (item?.kind === "assistant" && !streamOrigins.has(item.key)) { streamOrigins.set(item.key, turn.replyKey); if (rowCache.has(item)) { rowCache.delete(item); @@ -554,7 +581,7 @@ export function createTranscriptRowModel(options?: TranscriptRowModelOptions): T ]; } else { const originKey = streamOrigins.get(item.key); - rows = buildAssistantUnits({ + const assistantUnits = buildAssistantUnits({ replyKey: originKey ?? item.key, live: false, renderMode: originKey ? "streaming" : "static", @@ -565,6 +592,7 @@ export function createTranscriptRowModel(options?: TranscriptRowModelOptions): T retryTarget, anchorUserKey, }); + rows = originKey ? [buildAssistantActivityRow(originKey, assistantUnits)] : assistantUnits; } rowCache.set(item, { anchorUserKey, retryTarget, rows }); return rows; @@ -578,25 +606,44 @@ export function createTranscriptRowModel(options?: TranscriptRowModelOptions): T const isInitialBuild = !hasBuilt; hasBuilt = true; - if (liveTailVisible && !activeTurn) { + if (liveTailVisible && pendingSettle && activeTurn) { + if (!adoptSettledTwin(historyItems, pendingSettle)) { + deferredSettles.push(pendingSettle); + } + pendingSettle = null; + activeTurn = { + replyKey: `live-turn-${++turnSeq}`, + historyLenAtStart: historyItems.length, + liveUnitCache: new Map(), + lastLiveUnits: [], + settlingUnits: null, + }; + } else if (liveTailVisible && !activeTurn) { pendingSettle = null; activeTurn = { replyKey: `live-turn-${++turnSeq}`, historyLenAtStart: historyItems.length, liveUnitCache: new Map(), + lastLiveUnits: [], + settlingUnits: null, }; } else if (!liveTailVisible && activeTurn) { - if (!adoptSettledTwin(historyItems, activeTurn)) { + const adopted = adoptSettledTwin(historyItems, activeTurn); + if (!adopted) { pendingSettle = { replyKey: activeTurn.replyKey, historyLenAtStart: activeTurn.historyLenAtStart, }; } - activeTurn = null; + if (adopted) activeTurn = null; } else if (!liveTailVisible && pendingSettle) { if (adoptSettledTwin(historyItems, pendingSettle)) pendingSettle = null; } + if (deferredSettles.length > 0) { + deferredSettles = deferredSettles.filter((turn) => !adoptSettledTwin(historyItems, turn)); + } + const bornKeys: string[] = []; const trackBirth = (key: string) => { if (!knownKeys.has(key)) { @@ -622,27 +669,42 @@ export function createTranscriptRowModel(options?: TranscriptRowModelOptions): T let rows = historyRows; let liveStartIndex = -1; - if (liveTailVisible && activeTurn) { - const rounds: (UiRound | LiveRound)[] = - live.liveRounds.length > 0 - ? live.liveRounds - : live.draftAssistantText - ? [draftRound(live.draftAssistantText)] - : []; - const liveRows = buildAssistantUnits({ - replyKey: activeTurn.replyKey, - live: true, - renderMode: "streaming", - rounds, - compacted: false, - replyText: "", - retryTarget: null, - anchorUserKey: historyRows.at(-1)?.anchorUserKey ?? null, - liveUnitCache: activeTurn.liveUnitCache, - }); - rows = [...historyRows, ...liveRows]; + if ((liveTailVisible || pendingSettle) && activeTurn) { + let liveUnits = activeTurn.lastLiveUnits; + if (liveTailVisible) { + const rounds: (UiRound | LiveRound)[] = + live.liveRounds.length > 0 + ? live.liveRounds + : live.draftAssistantText + ? [draftRound(live.draftAssistantText)] + : []; + liveUnits = buildAssistantUnits({ + replyKey: activeTurn.replyKey, + live: true, + renderMode: "streaming", + rounds, + compacted: false, + replyText: "", + retryTarget: null, + anchorUserKey: historyRows.at(-1)?.anchorUserKey ?? null, + liveUnitCache: activeTurn.liveUnitCache, + }); + activeTurn.lastLiveUnits = liveUnits; + activeTurn.settlingUnits = null; + } else { + if (!activeTurn.settlingUnits) { + activeTurn.settlingUnits = activeTurn.lastLiveUnits.map((row) => ({ + ...row, + live: false, + mutable: false, + })); + } + liveUnits = activeTurn.settlingUnits; + } + const liveActivity = buildAssistantActivityRow(activeTurn.replyKey, liveUnits); + rows = [...historyRows, liveActivity]; liveStartIndex = rows.length - 1; - for (const row of liveRows) trackBirth(row.key); + trackBirth(liveActivity.key); } if (bornKeys.length > 0 || isInitialBuild) { diff --git a/crates/agent-gui/test/chat/block-round-keys.test.mjs b/crates/agent-gui/test/chat/block-round-keys.test.mjs index e4f91dade..3ec6eb693 100644 --- a/crates/agent-gui/test/chat/block-round-keys.test.mjs +++ b/crates/agent-gui/test/chat/block-round-keys.test.mjs @@ -93,6 +93,64 @@ test("groupRoundBlocks keys survive a block being inserted before them", () => { assert.equal(keysAfter[0], "thinking-1"); }); +test("ordinary tool activity keeps one group identity as later tools append", () => { + const tool = (id) => ({ + kind: "tool", + item: { toolCall: { type: "toolCall", id, name: "Bash", arguments: {} } }, + }); + const first = bubbleUtils.groupRoundBlocks([tool("call-1")]); + const appended = bubbleUtils.groupRoundBlocks([tool("call-1"), tool("call-2")]); + + assert.equal(first.length, 1); + assert.equal(appended.length, 1); + assert.equal(first[0].kind, "toolGroup"); + assert.equal(appended[0].kind, "toolGroup"); + assert.equal(appended[0].key, first[0].key); + assert.deepEqual( + appended[0].items.map((item) => item.toolCall.id), + ["call-1", "call-2"], + ); +}); + +test("special tool result updates preserve their direct activity identity", () => { + for (const name of ["TodoWrite", "AskUserQuestion", "Image", "Agent"]) { + const pendingItem = { + toolCall: { type: "toolCall", id: `call-${name}`, name, arguments: {} }, + }; + const settledItem = { + ...pendingItem, + toolResult: { + role: "toolResult", + toolCallId: `call-${name}`, + content: [], + isError: name === "Image", + }, + }; + const pending = bubbleUtils.groupRoundBlocks([{ kind: "tool", item: pendingItem }]); + const settled = bubbleUtils.groupRoundBlocks([{ kind: "tool", item: settledItem }]); + + assert.equal(pending.length, 1, name); + assert.equal(settled.length, 1, name); + assert.equal(pending[0].kind, "tool", name); + assert.equal(settled[0].kind, "tool", name); + assert.equal(settled[0].key, pending[0].key, name); + } +}); + +test("hosted search activity keeps one group identity as later searches append", () => { + const first = bubbleUtils.groupRoundBlocks([ + { kind: "hostedSearch", item: { id: "search-1" } }, + ]); + const appended = bubbleUtils.groupRoundBlocks([ + { kind: "hostedSearch", item: { id: "search-1" } }, + { kind: "hostedSearch", item: { id: "search-2" } }, + ]); + + assert.equal(first[0].kind, "hostedSearchGroup"); + assert.equal(appended[0].kind, "hostedSearchGroup"); + assert.equal(appended[0].key, first[0].key); +}); + // --------------------------------------------------------------------------- // Round keys: history rounds are r; rebuilds are deterministic diff --git a/crates/agent-gui/test/chat/frame-pin-controller.test.mjs b/crates/agent-gui/test/chat/frame-pin-controller.test.mjs new file mode 100644 index 000000000..09998c2b4 --- /dev/null +++ b/crates/agent-gui/test/chat/frame-pin-controller.test.mjs @@ -0,0 +1,53 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { createTsModuleLoader } from "../helpers/load-ts-module.mjs"; + +const { createFramePinController } = createTsModuleLoader().loadModule( + "src/lib/chat-scroll/framePinController.ts", +); + +test("coalesces repeated live growth into one pin per frame", () => { + const callbacks = []; + let writes = 0; + const controller = createFramePinController( + () => { + writes += 1; + }, + (callback) => { + callbacks.push(callback); + return callbacks.length; + }, + () => {}, + ); + + controller.schedule(); + controller.schedule(); + controller.schedule(); + assert.equal(callbacks.length, 1); + assert.equal(writes, 0); + callbacks.shift()(); + assert.equal(writes, 1); + + controller.schedule(); + assert.equal(callbacks.length, 1); +}); + +test("an immediate pin cancels the queued frame and writes once", () => { + const callbacks = []; + const cancelled = []; + let writes = 0; + const controller = createFramePinController( + () => { + writes += 1; + }, + (callback) => { + callbacks.push(callback); + return callbacks.length; + }, + (handle) => cancelled.push(handle), + ); + controller.schedule(); + controller.flush(); + assert.deepEqual(cancelled, [1]); + assert.equal(writes, 1); +}); diff --git a/crates/agent-gui/test/chat/live-markdown-caret.test.mjs b/crates/agent-gui/test/chat/live-markdown-caret.test.mjs new file mode 100644 index 000000000..a0d6adfee --- /dev/null +++ b/crates/agent-gui/test/chat/live-markdown-caret.test.mjs @@ -0,0 +1,12 @@ +import assert from "node:assert/strict"; +import fs from "node:fs"; +import test from "node:test"; + +const roundContentSource = fs.readFileSync( + new URL("../../src/pages/chat/components/assistant-bubble/RoundContent.tsx", import.meta.url), + "utf8", +); + +test("live assistant text does not render a trailing caret row", () => { + assert.doesNotMatch(roundContentSource, /showCaret=/); +}); diff --git a/crates/agent-gui/test/chat/live-scroll-adjust-policy.test.mjs b/crates/agent-gui/test/chat/live-scroll-adjust-policy.test.mjs index d04714e90..9b97266ac 100644 --- a/crates/agent-gui/test/chat/live-scroll-adjust-policy.test.mjs +++ b/crates/agent-gui/test/chat/live-scroll-adjust-policy.test.mjs @@ -75,10 +75,11 @@ test("detached reader inside the growing live row is left alone (streaming creep assert.equal(policy(item, 60, makeInstance({ scrollOffset: 3000, measuredKeys: [5] })), false); }); -test("the same live-row growth while following keeps compensating (pin assist)", () => { +test("following delegates every resize correction to the scroll-follow owner", () => { const policy = makePolicy({ liveStartIndex: 5, following: true }); const item = makeItem({ index: 5, start: 400, size: 5000 }); - assert.equal(policy(item, 60, makeInstance({ scrollOffset: 3000, measuredKeys: [5] })), true); + assert.equal(policy(item, 60, makeInstance({ scrollOffset: 3000, measuredKeys: [5] })), false); + assert.equal(policy(item, -80, makeInstance({ scrollOffset: 3000, measuredKeys: [5] })), false); }); test("live-row shrink keeps compensating so content under the reader stays put", () => { diff --git a/crates/agent-gui/test/chat/live-status-width.test.mjs b/crates/agent-gui/test/chat/live-status-width.test.mjs new file mode 100644 index 000000000..047ade658 --- /dev/null +++ b/crates/agent-gui/test/chat/live-status-width.test.mjs @@ -0,0 +1,19 @@ +import assert from "node:assert/strict"; +import fs from "node:fs"; +import test from "node:test"; + +const activitySource = fs.readFileSync( + new URL("../../src/pages/chat/transcript/AssistantActivityRow.tsx", import.meta.url), + "utf8", +); +const bubbleSource = fs.readFileSync( + new URL("../../src/pages/chat/components/AssistantBubble.tsx", import.meta.url), + "utf8", +); + +test("desktop live status cannot widen the transcript", () => { + assert.match(activitySource, /min-w-0 w-full max-w-full/); + assert.match(bubbleSource, /min-w-0 max-w-full overflow-hidden py-1\.5/); + assert.match(bubbleSource, / { + const placement = resolveThinkingOverlayPlacement( + { left: 200, right: 700, top: 500, bottom: 532, width: 500, height: 32 }, + { width: 1200, height: 800 }, + ); + assert.equal(placement.side, "above"); + assert.equal(placement.bottom, 308); + assert.ok(placement.maxHeight >= 180); +}); + +test("falls below on a short viewport and clamps narrow widths", () => { + const placement = resolveThinkingOverlayPlacement( + { left: 8, right: 312, top: 60, bottom: 92, width: 304, height: 32 }, + { width: 320, height: 480 }, + ); + assert.equal(placement.side, "below"); + assert.equal(placement.left, 12); + assert.equal(placement.width, 296); +}); + +test("keeps a renderable overlay inside an extremely narrow viewport", () => { + const placement = resolveThinkingOverlayPlacement( + { left: 0, right: 8, top: 60, bottom: 92, width: 8, height: 32 }, + { width: 8, height: 480 }, + ); + assert.equal(placement.left, 3.5); + assert.equal(placement.width, 1); + assert.ok(placement.left + placement.width <= 8); +}); + +test("thinking details use a portal overlay instead of inline collapse", () => { + assert.match(componentSource, /createPortal/); + assert.match(componentSource, /role="dialog"/); + assert.match(componentSource, /className="fixed/); + assert.match(componentSource, /event\.key !== "Escape"/); + assert.doesNotMatch(componentSource, /LazyCollapse/); +}); diff --git a/crates/agent-gui/test/chat/transcript-row-model.test.mjs b/crates/agent-gui/test/chat/transcript-row-model.test.mjs index 63725eb05..7cf0bdb1b 100644 --- a/crates/agent-gui/test/chat/transcript-row-model.test.mjs +++ b/crates/agent-gui/test/chat/transcript-row-model.test.mjs @@ -52,15 +52,15 @@ function round(key, text) { } function blockRows(snapshot) { - return snapshot.rows.filter( - (row) => row.kind === "assistant-unit" && row.unit.kind === "block", - ); + return snapshot.rows + .flatMap((row) => (row.kind === "assistant-activity" ? row.units : [row])) + .filter((row) => row.kind === "assistant-unit" && row.unit.kind === "block"); } function footerRows(snapshot) { - return snapshot.rows.filter( - (row) => row.kind === "assistant-unit" && row.unit.kind === "footer", - ); + return snapshot.rows + .flatMap((row) => (row.kind === "assistant-activity" ? row.units : [row])) + .filter((row) => row.kind === "assistant-unit" && row.unit.kind === "footer"); } const idleLive = { @@ -89,7 +89,7 @@ test("settling a live turn preserves every block-unit key and adds one footer un const settledHistory = [userItem("u1"), assistantItem("a1", [round("r1", "full reply")])]; const settled = model.build(settledHistory, idleLive); assert.equal(settled.liveStartIndex, -1); - assert.equal(settled.rows.length, 3); + assert.equal(settled.rows.length, 2); assert.equal(blockRows(settled)[0].key, liveBlockKey); assert.equal(blockRows(settled)[0].renderMode, "streaming"); assert.equal(footerRows(settled).length, 1); @@ -112,7 +112,13 @@ test("persist lag: block-unit aliases still land one build later", () => { }); const liveBlockKey = blockRows(streaming)[0].key; - assert.equal(model.build(history, idleLive).rows.length, 1); + const waitingForHistory = model.build(history, idleLive); + assert.equal(waitingForHistory.rows.length, 2, "the live activity must not disappear while persistence lags"); + assert.equal(blockRows(waitingForHistory)[0].key, liveBlockKey); + assert.equal(waitingForHistory.rows.at(-1).kind, "assistant-activity"); + assert.equal(waitingForHistory.rows.at(-1).live, false); + assert.equal(waitingForHistory.rows.at(-1).units.at(-1).unit.kind, "status"); + assert.equal("active" in waitingForHistory.rows.at(-1).units.at(-1).unit, false); const settled = model.build( [userItem("u1"), assistantItem("a1", [round("r1", "full reply")])], idleLive, @@ -128,15 +134,29 @@ test("a new turn supersedes an unresolved settle so aliases never cross turns", liveRounds: [{ ...round("r1", "x"), runningToolCallIds: [], thinkingOpen: false }], }; - model.build([userItem("u1")], sendingLive); + const firstStreaming = model.build([userItem("u1")], sendingLive); + const firstLiveBlockKey = blockRows(firstStreaming).at(-1).key; model.build([userItem("u1")], idleLive); const secondStreaming = model.build([userItem("u1"), userItem("u2")], sendingLive); const secondLiveBlockKey = blockRows(secondStreaming).at(-1).key; + const delayedFirstTwin = model.build( + [userItem("u1"), assistantItem("a1", [round("r1", "reply 1")]), userItem("u2")], + sendingLive, + ); + assert.equal(blockRows(delayedFirstTwin)[0].key, firstLiveBlockKey); + assert.equal(blockRows(delayedFirstTwin).at(-1).key, secondLiveBlockKey); + const settled = model.build( - [userItem("u1"), userItem("u2"), assistantItem("a2", [round("r1", "reply 2")])], + [ + userItem("u1"), + assistantItem("a1", [round("r1", "reply 1")]), + userItem("u2"), + assistantItem("a2", [round("r1", "reply 2")]), + ], idleLive, ); + assert.equal(blockRows(settled)[0].key, firstLiveBlockKey); assert.equal(blockRows(settled).at(-1).key, secondLiveBlockKey); }); @@ -235,7 +255,7 @@ test("a committed twin that races persistence is re-keyed at settle", () => { assert.equal(blockRows(racing)[0].key, "a1:round:r1:block:text-1"); const settled = model.build(midRun, idleLive); - assert.equal(settled.rows.length, 3); + assert.equal(settled.rows.length, 2); assert.equal(blockRows(settled)[0].key, liveBlockKey); }); @@ -255,19 +275,20 @@ test("terminal settlement removes the live tail before sending clears", () => { const committed = [userItem("u1"), assistantItem("a1", [round("r1", "full reply")])]; const finalizing = model.build(committed, { ...store.getSnapshot(), isSending: true }); - assert.equal(finalizing.rows.length, 3); + assert.equal(finalizing.rows.length, 2); assert.equal(finalizing.liveStartIndex, -1); assert.equal(blockRows(finalizing)[0].key, liveBlockKey); assert.equal(blockRows(finalizing)[0].live, false); const released = model.build(committed, { ...store.getSnapshot(), isSending: false }); - assert.equal(released.rows.length, 3); + assert.equal(released.rows.length, 2); store.reset(); const nextPending = model.build(committed, { ...store.getSnapshot(), isSending: true }); - assert.equal(nextPending.rows.length, 4); - assert.equal(nextPending.liveStartIndex, 3); - assert.equal(nextPending.rows[3].mutable, true); + assert.equal(nextPending.rows.length, 3); + assert.equal(nextPending.liveStartIndex, 2); + assert.equal(nextPending.rows[2].kind, "assistant-activity"); + assert.equal(nextPending.rows[2].units.at(-1).mutable, true); }); test("assistant rounds flatten into grouped top-level render units", () => { @@ -311,7 +332,7 @@ test("Markdown text blocks stay whole instead of being string-sliced", () => { assert.ok(blockRows(snapshot)[0].renderCost > 1); }); -test("only the mutable live tail is pinned while completed prefix units virtualize", () => { +test("one live activity is pinned while its completed prefix units keep stable keys", () => { const model = createTranscriptRowModel(); const liveRound = { round: 1, @@ -335,10 +356,133 @@ test("only the mutable live tail is pinned while completed prefix units virtuali units.map((row) => row.mutable), [false, false, true], ); - assert.equal(snapshot.liveStartIndex, snapshot.rows.indexOf(units[2])); + const activity = snapshot.rows.find((row) => row.kind === "assistant-activity"); + assert.ok(activity); + assert.deepEqual( + activity.units.filter((unit) => unit.unit.kind === "block").map((unit) => unit.key), + units.map((unit) => unit.key), + ); + assert.equal(activity.units.at(-1).unit.kind, "status"); + assert.equal(snapshot.liveStartIndex, snapshot.rows.indexOf(activity)); assert.equal(snapshot.liveStartIndex, snapshot.rows.length - 1); }); +test("the active assistant turn stays one outer activity row through growth and settlement", () => { + const model = createTranscriptRowModel(); + const history = [userItem("u1")]; + const firstRound = { + round: 1, + key: "r1", + blocks: [{ kind: "thinking", id: "thinking-1", text: "first thought" }], + runningToolCallIds: [], + thinkingOpen: true, + }; + const first = model.build(history, { + ...idleLive, + isSending: true, + liveRounds: [firstRound], + }); + const firstActivity = first.rows.find((row) => row.kind === "assistant-activity"); + assert.ok(firstActivity); + assert.equal(first.rows.filter((row) => row.kind === "assistant-activity").length, 1); + const stableStatusKey = firstActivity.units.at(-1).key; + assert.equal(firstActivity.units.at(-1).unit.kind, "status"); + + const toolItem = { + toolCall: { type: "toolCall", id: "call-1", name: "Bash", arguments: { command: "pwd" } }, + }; + const grownRound = { + ...firstRound, + blocks: [...firstRound.blocks, { kind: "tool", item: toolItem }], + runningToolCallIds: ["call-1"], + thinkingOpen: false, + }; + const grown = model.build(history, { + ...idleLive, + isSending: true, + liveRounds: [grownRound], + }); + const grownActivity = grown.rows.find((row) => row.kind === "assistant-activity"); + assert.ok(grownActivity); + assert.equal(grownActivity.key, firstActivity.key); + assert.equal(grown.liveStartIndex, grown.rows.indexOf(grownActivity)); + assert.equal(grownActivity.units.at(-1).key, stableStatusKey); + assert.equal(grownActivity.units.at(-1).unit.kind, "status"); + assert.deepEqual( + grownActivity.units + .filter((unit) => unit.unit.kind !== "status") + .slice(0, firstActivity.units.length - 1) + .map((unit) => unit.key), + firstActivity.units.filter((unit) => unit.unit.kind !== "status").map((unit) => unit.key), + ); + + const settledHistory = [ + userItem("u1"), + assistantItem("a1", [ + { round: grownRound.round, key: grownRound.key, blocks: grownRound.blocks }, + ]), + ]; + const settled = model.build(settledHistory, idleLive); + const settledActivity = settled.rows.find((row) => row.kind === "assistant-activity"); + assert.ok(settledActivity); + assert.equal(settledActivity.key, firstActivity.key); + assert.equal(settledActivity.units.at(-1).key, stableStatusKey); + assert.equal(settledActivity.units.at(-1).unit.kind, "footer"); + assert.deepEqual( + settledActivity.units + .filter((unit) => unit.unit.kind === "block") + .map((unit) => unit.key), + grownActivity.units.filter((unit) => unit.unit.kind === "block").map((unit) => unit.key), + ); +}); + +test("one outer activity row stays stable across one hundred appended tools", () => { + const model = createTranscriptRowModel(); + const history = [userItem("u1")]; + let outerKey = ""; + let toolActivityKey = ""; + + for (let count = 1; count <= 100; count += 1) { + const blocks = Array.from({ length: count }, (_, index) => ({ + kind: "tool", + item: { + toolCall: { + type: "toolCall", + id: `call-${index + 1}`, + name: "Bash", + arguments: { command: `Write-Output ${index + 1}` }, + }, + }, + })); + const snapshot = model.build(history, { + ...idleLive, + isSending: true, + liveRounds: [ + { + round: 1, + key: "r1", + blocks, + runningToolCallIds: [`call-${count}`], + thinkingOpen: false, + }, + ], + }); + const activity = snapshot.rows.find((row) => row.kind === "assistant-activity"); + assert.ok(activity); + const groupedTool = activity.units.find( + (unit) => unit.unit.kind === "block" && unit.unit.block.kind === "toolGroup", + ); + assert.ok(groupedTool); + if (count === 1) { + outerKey = activity.key; + toolActivityKey = groupedTool.key; + } else { + assert.equal(activity.key, outerKey); + assert.equal(groupedTool.key, toolActivityKey); + } + } +}); + test("assistant unit keys do not depend on the history-window-relative index", () => { const model = createTranscriptRowModel(); const assistant = assistantItem("assistant-stable", [round("r1", "reply")]); @@ -438,6 +582,8 @@ test("transcript virtualizer keeps scroll updates off the full React measurement assert.match(transcriptListSource, /estimateSize:\s*estimateRowSize/); assert.match(transcriptListSource, /getItemKey:\s*getRowKey/); assert.match(transcriptListSource, /rangeExtractor:\s*extractVirtualRange/); + assert.match(transcriptListSource, /anchorTo:\s*viewportFollowing \? "start" : "end"/); + assert.match(transcriptListSource, /data-row-key=\{row\.key\}/); assert.match(transcriptListSource, /directDomUpdates:\s*true/); assert.match(transcriptListSource, /directDomUpdatesMode:\s*"transform"/); assert.match(transcriptListSource, /ref=\{virtualizer\.containerRef\}/); diff --git a/docs/worklog/live-transcript-jitter.md b/docs/worklog/live-transcript-jitter.md new file mode 100644 index 000000000..1f817e2a7 --- /dev/null +++ b/docs/worklog/live-transcript-jitter.md @@ -0,0 +1,173 @@ +# Live transcript activity stability + +## Goal + +Keep the active assistant turn structurally stable while thinking, tools, tool results, and status updates stream into the desktop GUI and Gateway WebUI. Existing activity must update in place, bottom following must have one owner, and detached readers must keep their viewport anchor. + +## Baseline and isolation + +- Baseline: `upstream/main` at `849daf269762846557cc8243c5fe6e7fb155ed72`. +- Post-acceptance fetch on 2026-08-01 advanced `upstream/main` to `7de95a20bf93cfe026a57f6367c453e74a50acef` (two commits affecting only `.github/workflows/pr-governance.yml`). A read-only merge-tree check found no conflict; the accepted branch was intentionally not rebased or rewritten. +- Branch: `codex/fix-live-transcript-jitter`. +- Worktree: `D:\Documents\Projects\Web\LiveAgent\target\codex-live-transcript-jitter-worktree`. +- The main worktree and its existing `crates/agent-gui/src-tauri/Cargo.toml` edit remain untouched. +- The older `target\codex-transcript-order-scroll-jitter-worktree` is not reused or modified. + +## Confirmed causes + +1. A live thinking block automatically expands its Markdown body inline. When a tool starts, `thinkingOpen` closes it and the virtual row loses that height in one commit. +2. One ordinary tool is projected as `tool`, while a second consecutive tool replaces it with a differently keyed `toolGroup`, remounting the visible activity at the same logical position. +3. Desktop live content is split into several outer virtual rows; only the mutable tail is force-mounted. The active turn therefore changes the virtual row set as blocks arrive. +4. `anchorTo: "end"` in the transcript virtualizer and `useScrollFollow` both compensate the same bottom growth. Resize measurement and bottom pin writes can land sequentially and create a visible direction reversal. +5. Gateway already keeps one outer assistant row per turn, but shares the inline thinking expansion, tool grouping transition, end anchoring, and scroll-follow competition. +6. Runtime frame sampling exposed a second height oscillator after scroll ownership was unified: the live status footer was conditionally removed between tool phases, and long `正在执行…` text wrapped to two lines before returning to one-line `Vibing...`. Each cycle changed the measured height by about 15.2px, so the browser clamped upward before the next bottom pin. +7. Desktop settlement cleared the active activity before its persisted history twin was guaranteed to exist. A one-render persistence lag therefore removed the whole live row; a second turn could also discard the first turn's unresolved stream-origin alias. + +## Approved implementation direction + +- Project the active desktop assistant turn as one outer live activity row with stable identity; keep its child activity keys stable through settlement. +- Keep ordinary tool activity under one stable group identity from the first tool onward. A single tool may retain its direct visual treatment inside that stable wrapper. +- Render full thinking details in a fixed/absolute overlay. Opening, closing, and automatic running-state changes must not change transcript height. +- Make `useScrollFollow` the only writer for live bottom growth. The virtualizer may still measure and compensate detached/history readers, but must not perform end-anchor writes while following. +- Preserve Gateway-specific store architecture while applying the same activity and scroll invariants. + +## Implemented model and rendering decisions + +- Desktop live and stream-origin-settled replies now use one `assistantActivity` virtual row keyed by `${replyKey}:activity`. Child unit keys survive tool arrival, result updates, and settlement. +- Consecutive ordinary tools use a stable group keyed by the first tool from the first item onward. The singleton group keeps the existing single-tool visual treatment, avoiding a visible design change while preventing the one-to-many remount. +- `ThinkingActivity` is a props-only mirrored component. The compact row remains in flow; details render through a fixed portal and close on Escape, outside pointer, or focus departure. Placement is clamped for ordinary narrow windows and remains non-zero even for an extremely narrow synthetic viewport. +- Streaming growth is coalesced by `framePinController`, so repeated ResizeObserver notifications schedule at most one bottom write per animation frame. While following, virtualizer resize compensation is disabled and `anchorTo` is `start`; while detached, the existing virtualizer compensation path and `anchorTo: end` preserve history/prepend anchoring. +- Gateway keeps its existing one-row-per-turn store shape, but receives the same stable tool grouping, thinking overlay, frame pinning, and following/detached anchoring policy. +- Both clients keep one compact status tail from the start of streaming. Status text is single-line and truncated, so tool summaries cannot change the footer height. Desktop reuses the same `${replyKey}:footer` key when the settled footer takes over. +- Desktop retains cached activity units while persistence catches up. The same visible Vibing status and footer key remain until the persisted twin takes over, delayed history twins recover their original stream identity, and unresolved aliases survive a newer live turn until hydration can match them. +- Final visual feedback removed Streamdown's trailing live-text caret in both clients. The caret could render as a standalone white bar and reserve an otherwise empty line between a completed text block and the next tool; activity progress is already communicated by the stable status tail, so the duplicate cue is no longer emitted. +- Status width is now bounded through the complete flex chain: the desktop activity row occupies the transcript width, status wrappers allow shrinking and clip overflow, and the status text itself owns the ellipsis. WebUI applies the same footer constraint, so long tool summaries cannot widen either transcript. + +## TodoWrite compatibility + +The task-progress PR worktree is based on a different stack and changes GUI `rowModel.ts` to hide all `TodoWrite` blocks. This task remains independent of that PR. A read-only `git apply --check` of this task's relevant projection patches against `codex/feat-task-progress-indicator-stacked` at `7fb096839d5fd423a981f384227bdd3a08876515` passed. No TodoWrite implementation was copied and no Git dependency was introduced. + +## Verification status + +- Git/worktree gate: passed. +- Architecture and prior task-progress worklog review: complete. +- Parallel read-only GUI, WebUI, scroll, test/mirror, and compatibility exploration: complete. +- GUI build/typecheck: passed. +- Gateway WebUI build/typecheck: passed. +- GUI full frontend tests after all additions: 1,423/1,428 passed. The five failures exactly match the unmodified `849daf26` baseline (four mention source-extraction failures and one provider-preset byte-sync failure); baseline had 1,410/1,415 passed with the same five failures. +- Gateway WebUI full tests after all additions: 504/504 passed. +- Focused activity/identity/scroll tests: passed, including 100 appended tools, stable live-to-settled keys, interleaved reasoning/tool/result order, and one-frame pin coalescing. +- Mirrored live-caret regression tests assert that neither GUI nor WebUI round content requests a Markdown caret; both focused tests and both builds pass. +- GUI/WebUI status-width regression tests assert the non-expanding container chain and full-width truncation target; focused tests, touched-file lint, both builds, Mirror Check, and diff hygiene pass. +- Coverage audit follow-up: mirrored special-tool identity tests now cover `TodoWrite`, `AskUserQuestion`, `Image`, `Agent`, and hosted-search singleton-to-group stability. Gateway row tests now explicitly apply result B before result A, repeat result B, and assert the original A/B order, result ownership, error status, and outer assistant key remain stable. Focused rerun passed GUI 9/9 and WebUI 24/24. +- GUI lint: 419 errors / 358 warnings / 9 infos versus baseline 428 / 358 / 9. A final targeted Biome check of all 14 touched GUI source files exited successfully with three existing warnings and no errors. +- Gateway WebUI lint: 289 errors / 310 warnings / 10 infos versus baseline 296 / 310 / 10. A final targeted Biome check of all 11 touched WebUI source files exited successfully with 22 existing warnings and no errors. +- Mirror Check: 122/122 passed. +- `git diff --check`: passed; line-ending notices are working-tree conversion warnings, not whitespace errors. +- Independent read-only review: no P0/P1 finding. The final review identified delayed-twin alias loss and settling-status lifecycle as P2 risks. Alias retention is covered by the new-turn hydration test; the settling status intentionally remains visible until the persisted twin atomically takes over, matching the accepted GUI/WebUI behavior. +- Same-worktree Gateway WebUI runtime acceptance: frame-level bottom-follow and detached-reader probes passed after the status-height fix. +- Same-worktree Tauri and Gateway WebUI manual acceptance: passed by the user on 2026-08-01, including the follow-up removal of the stray Markdown caret, preservation of the visible Vibing status, and truncation of overlong status text without transcript-width growth. + +## Runtime provenance and preliminary browser checks + +- An older Tauri instance from `target\codex-transcript-order-scroll-jitter-worktree` owned port 1420. Only its verified running process tree was stopped; the old worktree was not modified or cleaned. +- Tauri was launched from this task worktree with `pnpm --dir crates/agent-gui tauri dev`; `LIBCLANG_PATH` was resolved from the local Python clang runtime without changing repository configuration. +- Task Vite's command line was rooted at this task worktree and listened on `127.0.0.1:1420`. +- The desktop binary resolved to this worktree's `target\debug\liveagent.exe`, was rebuilt for the acceptance run, and Windows reported the `LiveAgent` window responsive. Source HEAD remained `849daf269762846557cc8243c5fe6e7fb155ed72` plus the uncommitted task diff. +- Gateway was started from this task source with `go run ./cmd/gateway`, listening at `127.0.0.1:18080` with an isolated temporary agent database; no credential value is recorded in this worklog. +- WebUI Vite was rooted in this task worktree. Because the package script forwarded an extra literal `--`, Vite ignored the requested 15173 value; with an older unrelated server already on 5173, this verified task server selected `http://127.0.0.1:5174`. Its root returned HTTP 200 and the expected title. +- A headed Playwright browser authenticated against the task Gateway, and the desktop agent connected to that independent Gateway. The real acceptance conversation executed tools from the task worktree and reported the required branch and baseline HEAD. +- At 390x844, document and body widths remain 390px with no horizontal overflow. Sidebar overlay interception followed the normal close-sidebar path. Dark mode applied (`html.dark`, `color-scheme: dark`) and emulated `prefers-reduced-motion: reduce` matched true. Screenshot: `output/playwright/webui-narrow-dark-reduced.png` (acceptance artifact only, not a task source file). +- The first 12-step live run kept two outer transcript rows (one user and one assistant activity) while more than 24 internal activity buttons accumulated, proving that live growth stayed inside one assistant row. +- Diagnostic sampling before the final status fix recorded 57 explicit scroll writes, all owned by `useScrollFollow`, and repeated `+15.2px/-15.2px` pairs. This ruled out a second JavaScript writer and identified conditional/wrapping status height as the remaining oscillator. +- After the stable single-line status fix, a new real six-tool run sampled 8,820 frames. All 20 explicit writes came from `useScrollFollow`; the repeated negative 15.2px deltas disappeared. After the initial pending-to-assistant measurement (`+236px`, then one `-4px` estimate correction), every live tool increment was non-negative and the final bottom gap was 0px. +- A trusted wheel gesture detached the same page by about 700px during a later live run. Across 7,396 animation-frame samples, the selected visible row had 0px maximum/final top drift, 0 removals, 0 reinsertions, and the bottom gap grew from about 700px to 1,361.6px. Live output therefore did not steal the detached reader's position. +- Browser frame probes are prepared under `output/playwright/`: bottom-follow and detached variants sample every animation frame and track the exact row node with a `MutationObserver`; the stop probe reports sample count, node removals/reinsertions, direction reversals, maximum anchor drift, and final bottom gap. These are acceptance artifacts only and will not be staged. +- Tauri, GUI Vite, Gateway, and WebUI Vite all remained rooted in the task worktree throughout the probes. No commit, push, or PR update had occurred before manual acceptance. + +## Manual acceptance matrix + +All prompts below are read-only unless the row explicitly asks the user to press Stop or toggle the Remote connection. Run the observable rows once in the same-worktree Tauri window and once in the task WebUI. The automated-only rows are covered by the commands/results above and are not represented as manual UI checks. + +| Scenario | Client | Trigger and steps | Expected result | +| --- | --- | --- | --- | +| Thinking → tool → thinking | GUI + WebUI | Send the sequential twelve-step prompt below. Keep the transcript at the bottom for steps 1–4. | Existing thinking/tool rows never exchange positions; each tool updates in place; no up/down direction reversal. | +| Twelve tools, long activity list | GUI + WebUI | Let the complete sequential prompt finish. Expand and scroll the activity region while later steps arrive. | First tool keeps the same DOM identity; new items append; no prior item remounts; scroll remains usable through all twelve steps. | +| Detached reader | GUI + WebUI | During steps 5–8, scroll the transcript upward until the “back to bottom” affordance appears and keep the pointer still. | The visible anchor top stays within about 1px; new activity does not steal the viewport. | +| Return to bottom | GUI + WebUI | Activate the return-to-bottom affordance once, then leave the viewport untouched. | It returns once and subsequent growth stays bottom-pinned with at most one final correction per frame. | +| Thinking details overlay | GUI + WebUI | Activate a compact “Thinking process” row by mouse, keyboard Enter/Space, and touch emulation; then close using Escape, outside click, and focus departure. | A fixed dialog appears without changing transcript/composer height; trigger focus returns on Escape; reduced motion has no height animation. | +| Parallel and out-of-order tools | GUI + WebUI | Send the parallel-subagent prompt below. | Items remain in first-seen order even when the shorter subagent completes first; results update their original items. | +| Tool failure and recovery | GUI + WebUI | Send the failure prompt below. | The failed tool changes to failed in place, later successful tool appends after it, and the activity container remains stable. | +| Stop/cancel | GUI + WebUI | Send the stop prompt; after the long-running tool begins, press Stop once. | Running item becomes cancelled/aborted in place; no duplicate status row; turn settles once without a final jump. | +| Retry | GUI + WebUI | Use the existing retry action on the failed turn exactly once. | A new attempt is represented without reordering the settled prior turn; repeated click is not duplicated. | +| AskUserQuestion | GUI + WebUI | Send the question prompt; wait five seconds, select “继续”, submit once. | Pending card and surrounding activities do not move; answering resumes the same turn; duplicate submission is blocked. | +| TodoWrite compatibility | GUI + WebUI | The twelve-step prompt creates and updates the complete TodoWrite list before every step. | Existing TodoWrite bubble/progress behavior remains available; hidden TodoWrite never splits adjacent ordinary tools or changes their identity. | +| Image | GUI + WebUI | Attach a small image and ask the agent to inspect its dimensions/read visible text, without editing files. | Image tool/activity stays at its original position as result arrives; preview/details still open. | +| Hosted search | GUI + WebUI | Ask: “使用 hosted search 查找 LiveAgent 仓库主页,只返回标题和 URL。” | Search row updates in place and does not regroup neighboring shell/file tools. | +| Subagent | GUI + WebUI | Use the parallel-subagent prompt. | Both subagent activities keep stable identity, progress/result details remain accessible. | +| Narrow/light/dark/reduced motion | WebUI + GUI | Repeat overlay and live-list checks at ~390px, light and dark theme, with reduced motion enabled. | No horizontal overflow; overlay is clamped; no layout-height animation. | +| Conversation switch/history restore | GUI + WebUI | While idle, switch to another conversation and back; reload WebUI once. | Restored settled order equals the live order and no duplicate/remounted activity appears. | +| Gateway reconnect | WebUI | During a long step, disable Remote Access in Tauri for 3–5 seconds, then re-enable with unchanged settings. | Browser reports disconnect/reconnect, rehydrates the same order, and does not duplicate or move existing activities. | +| History prepend/floor navigation | GUI + WebUI | Open a long conversation, scroll upward to load older history, then use floor navigation once. | The visible keyed anchor is preserved; the one explicit navigation owns the scroll; no corrective bounce. | +| Invalid/duplicate/late events | Automated only | GUI/WebUI projection and store tests, including replay/reconnect and delayed-result fixtures. | Existing IDs and relative order remain unchanged; invalid/duplicate events are idempotent. | +| 50/100-item stress | Automated only | `transcript-row-model.test.mjs` and Web projection tests; 100 appended ordinary tools are built incrementally. | One outer activity key and the first tool key survive; no identity churn or maximum-depth/ResizeObserver error. | + +### Sequential twelve-step prompt + +```text +这是实时活动稳定性验收。不要修改任何文件,不要并行、合并、跳过或批量完成步骤。 + +1. 首先调用 TodoWrite,一次性创建下面完整的 12 项任务,名称和顺序后续不得改变;只将第 1 项设为 in_progress,其余设为 pending。 +2. 每完成一项,必须立即重新调用 TodoWrite,提交完整 12 项列表:刚完成项设为 completed,下一项设为 in_progress,其余状态保持不变;一次只能完成一项。 +3. 每次 TodoWrite 更新后执行 Start-Sleep -Seconds 2,再执行下一项。 +4. 每项必须使用一次独立工具调用,严格串行: + 1) 获取当前工作目录 + 2) 获取当前 Git 分支 + 3) 获取当前 HEAD SHA + 4) 查看 git status --short + 5) 获取 Node.js 版本 + 6) 获取 pnpm 版本 + 7) 获取 rustc 版本 + 8) 获取 Cargo 版本 + 9) 获取 Go 版本 + 10) 检查 crates/agent-gui/package.json 是否存在 + 11) 检查 crates/agent-gateway/web/package.json 是否存在 + 12) 只读汇总前面结果 +5. 在相邻工具之间可以简短说明当前进度,但不要修改文件,不要调用 AskUserQuestion。 +``` + +### Parallel/out-of-order subagent prompt + +```text +只读验收,不修改文件。连续启动两个独立 Agent/subagent 活动,保持首次出现顺序:第一个等待 4 秒后读取当前分支;第二个等待 1 秒后读取当前 HEAD。允许并行并让第二个先返回。两者完成后再用一个普通 shell 工具汇总结果。不得重排或重新命名已有活动。 +``` + +### Failure/recovery prompt + +```text +只读验收。先执行一个必然失败且不修改系统的命令,输出固定错误并以非零状态退出;失败后不要重试该命令,继续用新的独立工具调用执行 git rev-parse HEAD,最后说明两个结果。不要并行。 +``` + +### Stop prompt + +```text +只读验收。先说明将开始等待,然后执行一个持续 30 秒的等待命令;等待结束后才允许读取当前分支。不要后台运行,不要并行。我会在等待期间按一次 Stop。 +``` + +### AskUserQuestion prompt + +```text +只读验收。先调用 AskUserQuestion 询问“是否继续稳定性验收?”,只提供“继续”和“取消”两个选项。在我回答前不要调用其他工具;选择继续后读取当前 HEAD 并结束。 +``` + +## Frame-level evidence protocol + +- Browser probe chooses the transcript `[data-scroll-viewport]`, captures the currently stable assistant row node and its `getBoundingClientRect().top`, and samples it with `scrollTop` on every animation frame. +- A `MutationObserver` records whether that exact node is removed/reinserted while later tool rows arrive. +- Bottom-follow acceptance: final bottom gap ≤1px, no repeated sign reversal among meaningful (>0.5px) live-tool deltas, and no more than one final pin per sampled frame. A one-time initial estimate correction is recorded separately from steady-state live growth. +- Detached acceptance: select a visible historical row as anchor after the user scrolls up; maximum absolute top drift target ≤1px while new activity and ResizeObserver measurements land. +- Record sample count, maximum anchor drift, direction reversals, node removal count, and final bottom gap for both desktop-observable and WebUI runs. WebUI is sampled directly through Playwright; desktop uses the same visual scenario plus source/process provenance because the Tauri WebView is not exposed as a Playwright page. + +## Resume + +Manual acceptance is complete. Continue only from the task worktree above: stage task source and this worklog explicitly (excluding `.playwright-cli/`, `output/`, and the content-identical `crates/agent-gui/src-tauri/Cargo.toml` status artifact), review the staged diff, commit, push, create the upstream PR with `Depends-On: none`, and monitor required CI to terminal state. diff --git a/scripts/mirror-manifest.json b/scripts/mirror-manifest.json index 30bd47234..e92e30a3d 100644 --- a/scripts/mirror-manifest.json +++ b/scripts/mirror-manifest.json @@ -31,6 +31,7 @@ "components/project-tools/file-tree/ContextMenu.tsx", "components/chat/promptHistory.ts", "components/chat/NotifyToast.tsx", + "components/chat/ThinkingActivity.tsx", "components/chat/fileTypeIcons.tsx", "components/chat/ComposerAttachmentCard.tsx", "components/chat/AskUserQuestionCard.tsx", @@ -40,6 +41,7 @@ "lib/chat/askUserQuestion.ts", "lib/chat/openChatFileLink.ts", "lib/chat/toolApprovalArgs.ts", + "lib/chat/thinkingOverlayModel.ts", "components/Markdown.tsx", "lib/markdownCodeBlockPolicy.ts", "lib/normalizeLatexDelimiters.ts", @@ -53,6 +55,7 @@ "components/workspace-editor/workspaceMarkdownAssets.ts", "components/workspace-editor/WorkspaceMarkdownPreview.tsx", "lib/chat-scroll/scrollFollowCore.ts", + "lib/chat-scroll/framePinController.ts", "lib/chat-scroll/useScrollFollow.ts", "lib/chat-floor-nav/floorModel.ts", "lib/chat-floor-nav/floorBookmarks.ts", From babfd48d0ec8b7cbdaec8db7d1df24116d456849 Mon Sep 17 00:00:00 2001 From: AlphaCat Date: Sat, 1 Aug 2026 06:59:40 +0800 Subject: [PATCH 2/2] docs(chat): add runtime acceptance preview --- .../images/live-transcript-stability-webui.png | Bin 0 -> 205562 bytes docs/worklog/live-transcript-jitter.md | 1 + 2 files changed, 1 insertion(+) create mode 100644 docs/images/live-transcript-stability-webui.png diff --git a/docs/images/live-transcript-stability-webui.png b/docs/images/live-transcript-stability-webui.png new file mode 100644 index 0000000000000000000000000000000000000000..db4639d7dd028e8457810bb5b61a79df9b955077 GIT binary patch literal 205562 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%0ABW-m{guc>2l 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 S$D)8cAmj~Wc!92M*na^68F;z? literal 0 HcmV?d00001 diff --git a/docs/worklog/live-transcript-jitter.md b/docs/worklog/live-transcript-jitter.md index 1f817e2a7..50a482dcc 100644 --- a/docs/worklog/live-transcript-jitter.md +++ b/docs/worklog/live-transcript-jitter.md @@ -77,6 +77,7 @@ The task-progress PR worktree is based on a different stack and changes GUI `row - Gateway was started from this task source with `go run ./cmd/gateway`, listening at `127.0.0.1:18080` with an isolated temporary agent database; no credential value is recorded in this worklog. - WebUI Vite was rooted in this task worktree. Because the package script forwarded an extra literal `--`, Vite ignored the requested 15173 value; with an older unrelated server already on 5173, this verified task server selected `http://127.0.0.1:5174`. Its root returned HTTP 200 and the expected title. - A headed Playwright browser authenticated against the task Gateway, and the desktop agent connected to that independent Gateway. The real acceptance conversation executed tools from the task worktree and reported the required branch and baseline HEAD. +- Gateway WebUI acceptance preview: `docs/images/live-transcript-stability-webui.png` captures the completed sequential run in the verified task client. - At 390x844, document and body widths remain 390px with no horizontal overflow. Sidebar overlay interception followed the normal close-sidebar path. Dark mode applied (`html.dark`, `color-scheme: dark`) and emulated `prefers-reduced-motion: reduce` matched true. Screenshot: `output/playwright/webui-narrow-dark-reduced.png` (acceptance artifact only, not a task source file). - The first 12-step live run kept two outer transcript rows (one user and one assistant activity) while more than 24 internal activity buttons accumulated, proving that live growth stayed inside one assistant row. - Diagnostic sampling before the final status fix recorded 57 explicit scroll writes, all owned by `useScrollFollow`, and repeated `+15.2px/-15.2px` pairs. This ruled out a second JavaScript writer and identified conditional/wrapping status height as the remaining oscillator.