dsh-smooth-stream 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["css","IconChevronDownOutline14","clamp","css","css","MarkdownText","IconThinkOutline14","ImageGallery","JsonBlock","css","IconChevronDownOutline14","IconRefreshOutline14","SETTINGS_NS"],"sources":["../src/client/AnimatedDisclosure.tsx","../src/client/useSmoothStreamContent.ts","../src/client/useFpsGuard.ts","../src/client/teleprompterGlide.ts","../src/client/FollowHost.tsx","../src/config.ts","../src/settings.ts","../src/client/TypewriterAssistantNodeView.tsx","../src/client/TypewriterToolNodeView.tsx","../src/client/SmoothStreamCard.tsx","../src/client/smooth-stream-card-controller.ts","../src/settings-api.ts","../src/client/smooth-stream-settings-api.ts","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["// AnimatedDisclosure: the harness DisclosureRow chrome (24px row, hover\n// chevron preview, whole-row click/Enter/Space toggle) with one deliberate\n// difference - the expanded body stays mounted while collapsed and animates\n// between 0fr and 1fr grid tracks, so expand/collapse glides instead of\n// snapping. The harness primitive unmounts closed children (`{open &&\n// children}`) and a plugin cannot change that in place, so this fork mirrors\n// its DOM shape and `data-disclosure-row` contract: host styling keyed on the\n// row attribute and the Think chrome keep working unchanged.\n\nimport { type KeyboardEvent, type ReactNode } from 'react'\nimport { IconChevronDownOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'\nimport css from './TypewriterAssistantNodeView.module.css'\n\n/** Class-name join for optional overlay classes over the chrome defaults. */\nfunction cx(...parts: Array<string | undefined>): string {\n return parts.filter(part => part !== undefined && part !== '').join(' ')\n}\n\nexport interface AnimatedDisclosureProps {\n icon: ReactNode\n title: string\n open: boolean\n onToggle: () => void\n collapsedContent?: ReactNode\n children?: ReactNode\n rowClassName?: string | undefined\n leadingClassName?: string | undefined\n titleClassName?: string | undefined\n chevronClassName?: string | undefined\n}\n\n/**\n * Render one disclosure header whose expanded body is height-animated.\n * @param props - Visual content, controlled open state, and the toggle\n * callback fired by row click and Enter/Space.\n * @returns the animated disclosure row.\n */\nexport function AnimatedDisclosure({\n icon,\n title,\n open,\n onToggle,\n collapsedContent,\n children,\n rowClassName,\n leadingClassName,\n titleClassName,\n chevronClassName,\n}: AnimatedDisclosureProps) {\n const toggleFromKeyboard = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key !== 'Enter' && event.key !== ' ') return\n event.preventDefault()\n onToggle()\n }\n return (\n <div className={css.disclosureRoot} data-open={open || undefined}>\n <div\n className={cx(css.disclosureRow, rowClassName)}\n data-disclosure-row\n data-expandable=\"\"\n role=\"button\"\n tabIndex={0}\n aria-expanded={open}\n onClick={onToggle}\n onKeyDown={toggleFromKeyboard}\n >\n <span className={cx(css.disclosureLeading, leadingClassName)}>\n {open\n ? <IconChevronDownOutline14 className={chevronClassName} />\n : (\n <>\n <span className={css.disclosureIconIdle}>{icon}</span>\n <IconChevronDownOutline14 className={cx(chevronClassName, css.disclosureChevronHover)} />\n </>\n )}\n </span>\n <span className={cx(css.disclosureTitle, titleClassName)}>{title}</span>\n {!open && collapsedContent}\n </div>\n <div className={css.disclosureContent} data-disclosure-content data-collapsed={open ? undefined : ''}>\n {children}\n </div>\n </div>\n )\n}\n","/**\n * Stream-smoothing reveal hook.\n *\n * Buffers the model's chunked text and reveals it at a cadence that tracks\n * the observed arrival rate, so a long reply never dumps whole paragraphs at\n * once and a fast stream never stutters. Port of lobe-ui's smoother: EMA\n * arrival cps + chunk size, backlog pressure, commit-interval widening with\n * tail length, and a flush-speed settle drain once the input idles. The\n * reveal decision is the pure {@link computeRevealStep} for unit tests.\n *\n * `shouldHoldBack` is the performance guard's veto: while it returns true the\n * loop keeps measuring but skips the DOM commit, so an offscreen reply never\n * competes with visible frames when the frame rate is degraded.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nexport type StreamSmoothingPreset = 'realtime' | 'balanced' | 'silky'\n\nexport interface StreamSmoothingPresetConfig {\n readonly activeInputWindowMs: number\n readonly defaultCps: number\n readonly emaAlpha: number\n readonly flushCps: number\n readonly largeAppendChars: number\n readonly maxActiveCps: number\n readonly maxCps: number\n readonly maxFlushCps: number\n readonly minCommitIntervalMs: number\n readonly minCps: number\n readonly settleAfterMs: number\n readonly settleDrainMaxMs: number\n readonly settleDrainMinMs: number\n readonly targetBufferMs: number\n}\n\nexport const PRESET_CONFIG: Record<StreamSmoothingPreset, StreamSmoothingPresetConfig> = {\n balanced: {\n activeInputWindowMs: 220,\n defaultCps: 80,\n emaAlpha: 0.35,\n flushCps: 180,\n largeAppendChars: 120,\n maxActiveCps: 360,\n maxCps: 240,\n maxFlushCps: 480,\n minCommitIntervalMs: 16,\n minCps: 24,\n settleAfterMs: 280,\n settleDrainMaxMs: 420,\n settleDrainMinMs: 120,\n targetBufferMs: 40,\n },\n realtime: {\n activeInputWindowMs: 140,\n defaultCps: 120,\n emaAlpha: 0.45,\n flushCps: 240,\n largeAppendChars: 180,\n maxActiveCps: 480,\n maxCps: 320,\n maxFlushCps: 640,\n minCommitIntervalMs: 16,\n minCps: 32,\n settleAfterMs: 200,\n settleDrainMaxMs: 280,\n settleDrainMinMs: 100,\n targetBufferMs: 24,\n },\n silky: {\n activeInputWindowMs: 280,\n defaultCps: 64,\n emaAlpha: 0.28,\n flushCps: 140,\n largeAppendChars: 100,\n maxActiveCps: 280,\n maxCps: 180,\n maxFlushCps: 400,\n minCommitIntervalMs: 16,\n minCps: 20,\n settleAfterMs: 360,\n settleDrainMaxMs: 520,\n settleDrainMinMs: 160,\n targetBufferMs: 56,\n },\n}\n\nconst MAX_COMMIT_INTERVAL_MS = 16\n/** Demo queue divisor: each frame reveals about `backlog / 8` characters. */\nexport const QUEUE_REVEAL_DIVISOR = 8\nconst QUEUE_FRAME_MS = 16.67\n/** Hard cap on how far display may trail a live stream, in characters. */\nexport const LIVE_LAG_CHAR_CEILING = 32\nconst CATCHUP_SECONDS = 0.15\n\nexport const clamp = (value: number, min: number, max: number): number => {\n return Math.min(max, Math.max(min, value))\n}\n\n/**\n * Demo per-frame reveal: drain `backlog / 8` characters, at least 1, scaled\n * by frame time. A small queue types one glyph per frame; a burst raises the\n * step so the display does not fall behind.\n * @param backlog - Unrevealed characters.\n * @param dtMs - Frame delta in ms.\n * @returns Characters to reveal this frame.\n */\nexport function computeQueueReveal(backlog: number, dtMs: number): number {\n if (backlog <= 0 || dtMs <= 0) return 0\n return Math.min(backlog, Math.max(1, Math.ceil((backlog / QUEUE_REVEAL_DIVISOR) * (dtMs / QUEUE_FRAME_MS))))\n}\n\n/** Counts user-perceived characters (code points), not UTF-16 units. */\nexport const countChars = (text: string): number => {\n let count = 0\n for (const char of text) {\n void char\n count += 1\n }\n return count\n}\n\n/**\n * Drain rate for backlog beyond the tail-lag ceiling: the displayed text may\n * trail the stream by at most `backlogCharCeiling` characters for at most\n * `backlogSecondCeiling` seconds. The constants are a smoothness invariant\n * (bounded lag is the reason the reveal never stalls mid-reply), so they are\n * not config fields; the preset multiplier is how a deployment tunes them.\n */\nexport const BACKLOG_CHAR_CEILING = 300\nexport const BACKLOG_SECOND_CEILING = 2\n\nexport interface SettleDrainInput {\n readonly backlog: number\n readonly inputActive: boolean\n readonly settling: boolean\n}\n\n/** Pure settle-drain decision shared by the frame loop and its tests. */\nexport function computeSettleDrain(config: StreamSmoothingPresetConfig, input: SettleDrainInput): number {\n if (input.inputActive || !input.settling) return 0\n // A settled stream must drain fast enough to finish the reply promptly:\n // lag beyond the ceiling drains within the second ceiling.\n const overflow = Math.max(0, input.backlog - BACKLOG_CHAR_CEILING)\n const overflowCps = (overflow * 1000) / BACKLOG_SECOND_CEILING\n const drainTargetMs = clamp(input.backlog * 8, config.settleDrainMinMs, config.settleDrainMaxMs)\n const settleCps = (input.backlog * 1000) / drainTargetMs\n return clamp(Math.max(settleCps, overflowCps), config.flushCps, config.maxFlushCps)\n}\n\n/**\n * Drain rate multiplier once the input ends: leftover backlog reveals at\n * this multiple of the steady rate, so the end never drags.\n */\nexport const SETTLE_DRAIN_MULTIPLIER = 1.8\n\nexport interface RevealStepInput {\n readonly backlog: number\n readonly chunkSizeEma: number\n readonly arrivalCpsEma: number\n readonly emaCps: number\n readonly inputActive: boolean\n readonly settling: boolean\n /** Fixed reveal rate; overrides the arrival-tracking cadence entirely. */\n readonly steadyCps?: number | undefined\n}\n\nexport interface RevealStepResult {\n readonly revealChars: number\n readonly targetLagChars: number\n}\n\n/** Pure per-frame reveal decision shared by the loop and its tests. */\nexport function computeRevealStep(config: StreamSmoothingPresetConfig, input: RevealStepInput, dtSeconds: number): RevealStepResult {\n // Track the faster of the two EMAs and do not clamp to the old low maxCps\n // ceiling — that cap is why a fast model left hundreds of chars unrevealed.\n const trackedCps = Math.max(input.emaCps, input.arrivalCpsEma)\n const baseCps = clamp(trackedCps, config.minCps, config.maxFlushCps)\n const targetLagChars = input.inputActive\n ? Math.max(2, Math.round((baseCps * config.targetBufferMs) / 1000))\n : 0\n\n let currentCps: number\n if (input.steadyCps !== undefined) {\n currentCps = input.inputActive || input.settling\n ? clamp(\n input.steadyCps * (input.inputActive ? 1 : SETTLE_DRAIN_MULTIPLIER),\n config.minCps,\n config.maxFlushCps,\n )\n : 0\n } else if (input.inputActive) {\n const overflow = Math.max(0, input.backlog - LIVE_LAG_CHAR_CEILING)\n const catchup = overflow > 0 ? overflow / CATCHUP_SECONDS : 0\n currentCps = clamp(baseCps * 1.08 + catchup, config.minCps, config.maxFlushCps)\n } else if (input.settling) {\n currentCps = computeSettleDrain(config, input)\n } else {\n const idleFlushCps = Math.max(config.flushCps, baseCps * 1.8, input.arrivalCpsEma * 0.8)\n currentCps = clamp(idleFlushCps, config.flushCps, config.maxFlushCps)\n }\n\n const minRevealChars = input.inputActive ? 1 : 2\n return { revealChars: Math.max(minRevealChars, Math.round(currentCps * dtSeconds)), targetLagChars }\n}\n\nexport interface UseSmoothStreamContentOptions {\n enabled?: boolean\n preset?: StreamSmoothingPreset\n /** Performance guard veto: while true, reveal commits are held back. */\n shouldHoldBack?: (() => boolean) | undefined\n /**\n * Fixed reveal rate in chars/s. When set, the reveal runs at this steady\n * pace while the input streams (instead of tracking the arrival rate) and\n * drains the leftover backlog at {@link SETTLE_DRAIN_MULTIPLIER} once the\n * input ends.\n */\n steadyCps?: number | undefined\n /**\n * Seed for the arrival-rate EMA. When omitted, the preset's `defaultCps`\n * is used. The live rate then tracks observed arrival; this is not a cap.\n */\n defaultCps?: number | undefined\n /** Written each commit with the live arrival-rate EMA for the follow lerp. */\n speedCpsRef?: { current: number } | undefined\n}\n\n/**\n * Smooth a chunked content stream into a reveal-paced display string.\n *\n * @param content - The full accumulated input so far.\n * @param options - Preset, guard, and steady-rate wiring.\n * @returns The displayed content, revealed at the smoothed cadence.\n */\nexport function useSmoothStreamContent(\n content: string,\n { enabled = true, preset = 'balanced', shouldHoldBack, steadyCps, defaultCps, speedCpsRef }: UseSmoothStreamContentOptions = {},\n): string {\n const config = PRESET_CONFIG[preset]\n const seedCps = defaultCps ?? config.defaultCps\n const [displayedContent, setDisplayedContent] = useState(content)\n\n const displayedContentRef = useRef(content)\n const displayedCountRef = useRef(countChars(content))\n const targetContentRef = useRef(content)\n const targetCharsRef = useRef([...content])\n const targetCountRef = useRef(countChars(content))\n\n const emaCpsRef = useRef(seedCps)\n const lastInputTsRef = useRef(0)\n const lastInputCountRef = useRef(countChars(content))\n const chunkSizeEmaRef = useRef(1)\n const arrivalCpsEmaRef = useRef(seedCps)\n\n const rafRef = useRef<number | null>(null)\n const lastFrameTsRef = useRef<number | null>(null)\n const wakeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const holdBackRef = useRef(shouldHoldBack)\n const speedOutRef = useRef(speedCpsRef)\n speedOutRef.current = speedCpsRef\n\n useEffect(() => {\n holdBackRef.current = shouldHoldBack\n }, [shouldHoldBack])\n\n const clearWakeTimer = useCallback(() => {\n if (wakeTimerRef.current !== null) {\n clearTimeout(wakeTimerRef.current)\n wakeTimerRef.current = null\n }\n }, [])\n\n const stopFrameLoop = useCallback(() => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n lastFrameTsRef.current = null\n }, [])\n\n const stopScheduling = useCallback(() => {\n stopFrameLoop()\n clearWakeTimer()\n }, [clearWakeTimer, stopFrameLoop])\n\n const startFrameLoopRef = useRef<() => void>(() => {})\n\n const scheduleFrameWake = useCallback(\n (delayMs: number) => {\n clearWakeTimer()\n wakeTimerRef.current = setTimeout(\n () => {\n wakeTimerRef.current = null\n startFrameLoopRef.current()\n },\n Math.max(1, Math.ceil(delayMs)),\n )\n },\n [clearWakeTimer],\n )\n\n const syncImmediate = useCallback(\n (nextContent: string) => {\n stopScheduling()\n const chars = [...nextContent]\n const now = performance.now()\n targetContentRef.current = nextContent\n targetCharsRef.current = chars\n targetCountRef.current = chars.length\n displayedContentRef.current = nextContent\n displayedCountRef.current = chars.length\n setDisplayedContent(nextContent)\n emaCpsRef.current = seedCps\n chunkSizeEmaRef.current = 1\n arrivalCpsEmaRef.current = seedCps\n lastInputTsRef.current = now\n lastInputCountRef.current = chars.length\n },\n [seedCps, stopScheduling],\n )\n\n const startFrameLoop = useCallback(() => {\n clearWakeTimer()\n if (rafRef.current !== null) return\n\n const tick = () => {\n const targetCount = targetCountRef.current\n const displayedCount = displayedCountRef.current\n const backlog = targetCount - displayedCount\n\n if (backlog <= 0) {\n stopFrameLoop()\n return\n }\n\n const now = performance.now()\n if (lastFrameTsRef.current === null) {\n lastFrameTsRef.current = now\n rafRef.current = requestAnimationFrame(tick)\n return\n }\n\n const commitIntervalMs = Math.min(MAX_COMMIT_INTERVAL_MS, config.minCommitIntervalMs)\n const frameIntervalMs = Math.max(0, now - lastFrameTsRef.current)\n if (frameIntervalMs < commitIntervalMs) {\n rafRef.current = requestAnimationFrame(tick)\n return\n }\n\n const dtSeconds = Math.max(0.001, Math.min(frameIntervalMs / 1000, 0.12))\n lastFrameTsRef.current = now\n\n const idleMs = now - lastInputTsRef.current\n const inputActive = idleMs <= config.activeInputWindowMs\n const settling = !inputActive && idleMs >= config.settleAfterMs\n\n let revealChars: number\n if (steadyCps !== undefined) {\n const step = computeRevealStep(\n config,\n {\n backlog,\n chunkSizeEma: chunkSizeEmaRef.current,\n arrivalCpsEma: arrivalCpsEmaRef.current,\n emaCps: emaCpsRef.current,\n inputActive,\n settling,\n steadyCps,\n },\n dtSeconds,\n )\n revealChars = Math.min(step.revealChars, backlog)\n } else {\n // Same rAF queue drain as the silky markdown demo.\n revealChars = computeQueueReveal(backlog, frameIntervalMs)\n }\n\n // Performance guard: while degraded and the reply is offscreen, skip\n // the DOM commit — the backlog keeps accumulating and flushes when the\n // guard clears or the reply scrolls into view.\n if (holdBackRef.current?.() === true) {\n rafRef.current = requestAnimationFrame(tick)\n return\n }\n\n const speedOut = speedOutRef.current\n if (speedOut !== undefined && frameIntervalMs > 0) {\n const instantCps = (revealChars * 1000) / frameIntervalMs\n speedOut.current = speedOut.current * 0.92 + instantCps * 0.08\n }\n\n const nextCount = displayedCount + revealChars\n const segment = targetCharsRef.current.slice(displayedCount, nextCount).join('')\n if (segment) {\n const nextDisplayed = displayedContentRef.current + segment\n displayedContentRef.current = nextDisplayed\n displayedCountRef.current = nextCount\n setDisplayedContent(nextDisplayed)\n } else {\n displayedContentRef.current = targetContentRef.current\n displayedCountRef.current = targetCount\n setDisplayedContent(targetContentRef.current)\n }\n\n rafRef.current = requestAnimationFrame(tick)\n }\n\n rafRef.current = requestAnimationFrame(tick)\n }, [config, scheduleFrameWake, stopFrameLoop, clearWakeTimer, steadyCps])\n\n useEffect(() => {\n startFrameLoopRef.current = startFrameLoop\n }, [startFrameLoop])\n\n useEffect(() => {\n if (!enabled) {\n syncImmediate(content)\n return\n }\n\n const prevTargetContent = targetContentRef.current\n if (content === prevTargetContent) return\n\n const now = performance.now()\n const appendOnly = content.startsWith(prevTargetContent)\n\n if (!appendOnly) {\n syncImmediate(content)\n return\n }\n\n const appended = content.slice(prevTargetContent.length)\n const appendedChars = [...appended]\n const appendedCount = appendedChars.length\n\n targetContentRef.current = content\n targetCharsRef.current.push(...appendedChars)\n targetCountRef.current += appendedCount\n\n const hadSample = lastInputTsRef.current > 0\n const deltaChars = targetCountRef.current - lastInputCountRef.current\n const deltaMs = Math.max(1, now - lastInputTsRef.current)\n\n // Skip the first sample: lastInputTs starts at 0, so the interval would\n // be \"time since page load\" (or 1ms under fake timers) and poison the EMA.\n if (hadSample && deltaChars > 0) {\n const instantCps = (deltaChars * 1000) / deltaMs\n const normalizedInstantCps = clamp(instantCps, config.minCps, config.maxFlushCps * 3)\n const chunkEmaAlpha = 0.45\n chunkSizeEmaRef.current = chunkSizeEmaRef.current * (1 - chunkEmaAlpha) + appendedCount * chunkEmaAlpha\n arrivalCpsEmaRef.current = arrivalCpsEmaRef.current * (1 - chunkEmaAlpha) + normalizedInstantCps * chunkEmaAlpha\n emaCpsRef.current = emaCpsRef.current * (1 - config.emaAlpha) + normalizedInstantCps * config.emaAlpha\n }\n\n lastInputTsRef.current = now\n lastInputCountRef.current = targetCountRef.current\n\n startFrameLoop()\n }, [content, enabled, config, startFrameLoop, syncImmediate])\n\n useEffect(() => {\n return () => {\n stopScheduling()\n }\n }, [stopScheduling])\n\n return displayedContent\n}\n","/**\n * Performance guard for the streaming reveal.\n *\n * Feeds an EMA-smoothed frame-rate monitor from a rAF loop while streaming\n * and tracks whether the reply is on-screen. The returned `shouldHoldBack`\n * predicate is true only while the frame rate is below the threshold AND the\n * reply is offscreen — exactly the spec's \"skip offscreen DOM updates when\n * FPS < 30\" rule. The smoother consumes the predicate as its commit veto.\n */\n\nimport { useCallback, useEffect, useRef } from 'react'\n\nconst FPS_THRESHOLD = 30\nconst FPS_ALPHA = 0.12\nconst RECOVER_FRAMES = 6\nconst MAX_FRAME_MS = 100\n\ninterface MutableFps {\n emaMs: number\n lastMs: number\n healthyRun: number\n degraded: boolean\n}\n\nexport function useFpsGuard(active: boolean): {\n ref: (element: HTMLElement | null) => void\n shouldHoldBack: () => boolean\n} {\n const fpsRef = useRef<MutableFps>({ emaMs: 0, lastMs: 0, healthyRun: 0, degraded: false })\n const visibleRef = useRef(true)\n const elementRef = useRef<HTMLElement | null>(null)\n\n useEffect(() => {\n if (!active) return\n let rafId = 0\n const frame = (now: number) => {\n rafId = requestAnimationFrame(frame)\n const fps = fpsRef.current\n if (fps.lastMs === 0) {\n fps.lastMs = now\n return\n }\n const delta = Math.min(MAX_FRAME_MS, Math.max(1, now - fps.lastMs))\n fps.lastMs = now\n fps.emaMs = fps.emaMs === 0 ? delta : fps.emaMs + FPS_ALPHA * (delta - fps.emaMs)\n const currentFps = 1000 / fps.emaMs\n if (currentFps < FPS_THRESHOLD) {\n fps.healthyRun = 0\n fps.degraded = true\n } else if (fps.degraded) {\n fps.healthyRun += 1\n if (fps.healthyRun >= RECOVER_FRAMES) fps.degraded = false\n }\n }\n rafId = requestAnimationFrame(frame)\n return () => {\n cancelAnimationFrame(rafId)\n fpsRef.current = { emaMs: 0, lastMs: 0, healthyRun: 0, degraded: false }\n }\n }, [active])\n\n const ref = useCallback((element: HTMLElement | null) => {\n elementRef.current = element\n }, [])\n\n useEffect(() => {\n const element = elementRef.current\n if (element === null || typeof IntersectionObserver === 'undefined') return\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) visibleRef.current = entry.isIntersecting\n },\n { rootMargin: '120px 0px' },\n )\n observer.observe(element)\n return () => observer.disconnect()\n })\n\n const shouldHoldBack = useCallback(() => {\n return active && fpsRef.current.degraded && !visibleRef.current\n }, [active])\n\n return { ref, shouldHoldBack }\n}\n","/**\n * Conversation-port follow while an assistant reply streams.\n *\n * The demo's damped-spring lerp is driven from a float `animatedH` — the\n * smoothed content height — never from the rounded `scrollTop` the browser\n * reports back. A wrap raises the content height by a line; if the engine\n * were allowed to snap `scrollTop` to the new floor, the previous line would\n * hop up in one frame. This overlay:\n *\n * - owns follow via `data-follow-owned` so ChatView does not snap;\n * - sets `overflow-anchor: none` so CSS scroll-anchoring does not snap;\n * - restores `animatedH` in a ResizeObserver (before paint) so a layout\n * pass cannot flash a snapped frame;\n * - while the port has scroll room, writes the interpolated lag as\n * `translate3d` on `[data-chat-transcript]` (message rows only), so the\n * turn-status chrome stays pinned at the floor;\n * - before the port has scroll room (content shorter than the viewport), the\n * same lag is a content-height lag written as a negative translate on\n * `[data-chat-turn-status]`, so the status label descends smoothly with\n * each wrap instead of hopping a line at a time.\n *\n * Handing the port back to the reader (unpin, or the owner going inactive)\n * first writes the effective visual top (`engine - lag`) into `scrollTop`\n * before clearing the transform, so the frame stays continuous. That write\n * also lands in ChatView's observed-top ledger as reader input beyond\n * `FOLLOW_THRESHOLD`, releasing its native snap-follow instead of fighting\n * the gesture for the port.\n *\n * Unpin is a real gesture (wheel / touch / pointer / key) that leaves the\n * floor; a `scrollTop` delta from our own write must not release the pin.\n */\n\nimport { useEffect, useRef, type RefObject } from 'react'\n\n/**\n * Matches ChatView's `FOLLOW_OWNED_ATTR`. The overlay writes the last\n * programmatic `scrollTop` here so ChatView yields snap-follow and does not\n * treat the write as reader input.\n */\nconst FOLLOW_OWNED_ATTR = 'data-follow-owned'\n\n/** Demo `1 - exp(-dt / 18)` time constant, in ms. */\nexport const FOLLOW_LERP_DT_MS = 18\n\n/** Floor / ceiling of the per-frame lerp fraction before the dt term. */\nexport const FOLLOW_LERP_MIN = 0.05\nexport const FOLLOW_LERP_MAX = 0.25\n\n/** Lag (px) at which the lag term of the lerp saturates. */\nexport const FOLLOW_LERP_LAG_REF_PX = 160\n\n/** Reveal cps at which the speed factor is 1. */\nexport const FOLLOW_SPEED_REF_CPS = 35\n\nexport const FOLLOW_SPEED_FACTOR_MIN = 0.7\nexport const FOLLOW_SPEED_FACTOR_MAX = 2.2\n\n/** Reader-return / still-pinned boundary, matching ChatView + the demo. */\nexport const FOLLOW_SLACK_PX = 25\n\n/**\n * Upward wheel/touch distance that releases the pin. The engine `scrollTop`\n * is held on the floor while following, so a small trackpad tick never\n * appears as `reportedLag` and cannot be judged against {@link FOLLOW_SLACK_PX}.\n */\nexport const FOLLOW_UNPIN_GESTURE_PX = 8\n\n/** How long a gesture keeps `isUserInteracting` so the next scroll can unpin. */\nexport const FOLLOW_GESTURE_MS = 800\n\nconst GESTURE_EVENTS = ['wheel', 'touchmove', 'pointerdown', 'keydown'] as const\n\nexport interface FollowGlideInput {\n /** How far the interpolated top trails the floor, in px. */\n readonly lag: number\n /** Observed reveal rate in chars/s; 0 uses {@link FOLLOW_SPEED_REF_CPS}. */\n readonly speedEma: number\n}\n\nexport interface FollowGlideStep {\n /** Pixels to advance `animatedH` this frame (fractional). */\n readonly advancePx: number\n /** Applied lerp fraction, for tests. */\n readonly lerpStep: number\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value))\n}\n\n/**\n * One spring-lerp frame from the silky markdown demo.\n * @param dtMs - Frame delta in ms.\n * @param input - Current lag (from the float top, not the rounded engine top) and reveal-speed EMA.\n * @returns The fractional advance and the lerp fraction.\n */\nexport function computeFollowStep(dtMs: number, input: FollowGlideInput): FollowGlideStep {\n if (input.lag <= 0.1 || dtMs <= 0) return { advancePx: 0, lerpStep: 0 }\n const speed = input.speedEma > 0 ? input.speedEma : FOLLOW_SPEED_REF_CPS\n const speedFactor = clamp(speed / FOLLOW_SPEED_REF_CPS, FOLLOW_SPEED_FACTOR_MIN, FOLLOW_SPEED_FACTOR_MAX)\n const baseLerp = clamp((input.lag / FOLLOW_LERP_LAG_REF_PX) * speedFactor, FOLLOW_LERP_MIN, FOLLOW_LERP_MAX)\n const lerpStep = baseLerp * (1 - Math.exp(-dtMs / FOLLOW_LERP_DT_MS))\n return { advancePx: input.lag * lerpStep, lerpStep }\n}\n\n/** The message-rows box the lag transform rides on, when the host has one. */\nfunction shiftRootOf(port: HTMLElement): HTMLElement | null {\n return port.querySelector('[data-chat-transcript]')\n}\n\n/**\n * Row wrappers that carry only messages/tools. Hosts without a transcript\n * box keep the turn-status chrome as a sibling of the rows inside\n * `[data-chat-flow]`, so shifting that whole flow would drag the chrome\n * along; shifting the rows individually leaves every non-message sibling\n * (turn status, steering bubbles) pinned while the text glides.\n *\n * Only the outermost rows are shifted: a tool call nests its subcalls as\n * descendant `[data-chat-anchor-key]` rows, and writing the lag on each of\n * them would double (or further multiply) the shift, tearing the subcalls\n * away from their parent every frame. Descendants ride the parent's\n * transform instead.\n */\nfunction shiftRowsOf(port: HTMLElement): HTMLElement[] {\n return [...port.querySelectorAll<HTMLElement>('[data-chat-anchor-key]')]\n .filter(row => row.parentElement?.closest('[data-chat-anchor-key]') === null)\n}\n\n/** Element whose resize signals flow growth for the before-paint restore. */\nfunction resizeProxyOf(port: HTMLElement): HTMLElement | null {\n return port.querySelector('[data-chat-transcript]') ?? port.querySelector('[data-chat-flow]')\n}\n\n/** True when the glide expresses its lag as transforms instead of engine top. */\nfunction hasShiftSurface(port: HTMLElement): boolean {\n return shiftRootOf(port) !== null || shiftRowsOf(port).length > 0\n}\n\nfunction setShift(element: HTMLElement, px: number, negative = false): void {\n const value = negative ? -px : px\n if (Math.abs(value) > 0.01) {\n element.style.transform = `translate3d(0, ${value}px, 0)`\n element.style.willChange = 'transform'\n } else {\n element.style.transform = ''\n element.style.willChange = ''\n }\n}\n\n/**\n * The running-turn label. Before the port scrolls (content shorter than the\n * viewport) the content-height lag has no `scrollTop` room to ride, so it is\n * expressed as a negative translate on this sibling: the label descends\n * smoothly with each wrap instead of hopping down a line at a time.\n */\nfunction chromeShiftOf(port: HTMLElement): HTMLElement | null {\n return port.querySelector<HTMLElement>('[data-chat-turn-status]')\n}\n\n/**\n * Render the single smoothed extent `animatedH`. Before the port scrolls\n * (content shorter than the viewport) `animatedH` is clamped to the content\n * height and the content-height lag rides a negative translate on the\n * turn-status label; once the port has scroll room the engine is pinned at\n * the floor and the lag rides `[data-chat-transcript]` (or each message row\n * when the host has no transcript box) so the chrome stays put. Without any\n * shift surface the engine itself carries the interpolated top.\n */\nfunction applyVisual(port: HTMLElement, animatedH: number): void {\n const contentHeight = Math.max(0, port.scrollHeight)\n const floor = Math.max(0, contentHeight - port.clientHeight)\n const extent = Math.min(contentHeight, Math.max(0, animatedH))\n const lag = contentHeight - extent\n port.style.overflowAnchor = 'none'\n port.style.scrollBehavior = 'auto'\n const shiftRoot = shiftRootOf(port)\n if (shiftRoot !== null) {\n if (floor <= 0) {\n port.scrollTop = 0\n port.setAttribute(FOLLOW_OWNED_ATTR, String(port.scrollTop))\n const chrome = chromeShiftOf(port)\n if (chrome !== null) setShift(chrome, lag, true)\n setShift(shiftRoot, 0)\n return\n }\n port.scrollTop = floor\n port.setAttribute(FOLLOW_OWNED_ATTR, String(port.scrollTop))\n setShift(shiftRoot, lag)\n return\n }\n const rows = shiftRowsOf(port)\n if (rows.length > 0) {\n if (floor <= 0) {\n port.scrollTop = 0\n port.setAttribute(FOLLOW_OWNED_ATTR, String(port.scrollTop))\n const chrome = chromeShiftOf(port)\n if (chrome !== null) setShift(chrome, lag, true)\n for (const row of rows) setShift(row, 0)\n return\n }\n port.scrollTop = floor\n port.setAttribute(FOLLOW_OWNED_ATTR, String(port.scrollTop))\n for (const row of rows) setShift(row, lag)\n return\n }\n port.scrollTop = Math.min(floor, Math.max(0, extent))\n port.setAttribute(FOLLOW_OWNED_ATTR, String(port.scrollTop))\n}\n\nfunction clearVisual(port: HTMLElement): void {\n port.removeAttribute(FOLLOW_OWNED_ATTR)\n port.style.overflowAnchor = ''\n port.style.scrollBehavior = ''\n const shiftRoot = shiftRootOf(port)\n if (shiftRoot !== null) {\n shiftRoot.style.transform = ''\n shiftRoot.style.willChange = ''\n } else {\n for (const row of shiftRowsOf(port)) {\n row.style.transform = ''\n row.style.willChange = ''\n }\n }\n const chrome = chromeShiftOf(port)\n if (chrome !== null) {\n chrome.style.transform = ''\n chrome.style.willChange = ''\n }\n}\n\n/** Live follow hosts per conversation port so one unmount does not clear another. */\nconst followOwners = new WeakMap<HTMLElement, number>()\n\nfunction acquireFollow(port: HTMLElement): void {\n followOwners.set(port, (followOwners.get(port) ?? 0) + 1)\n}\n\nfunction releaseFollow(port: HTMLElement): number {\n const next = (followOwners.get(port) ?? 1) - 1\n if (next <= 0) {\n followOwners.delete(port)\n return 0\n }\n followOwners.set(port, next)\n return next\n}\n\n/**\n * Own the conversation scrollport's bottom-follow while `active` is true.\n *\n * @param rootRef - An element inside the conversation scrollport.\n * @param active - True while the reply is still revealing.\n * @param speedCpsRef - Live reveal-rate EMA from the smoother.\n */\nexport function useConversationFollow(\n rootRef: RefObject<HTMLElement | null>,\n active: boolean,\n speedCpsRef: { current: number },\n): void {\n const activeRef = useRef(active)\n useEffect(() => {\n activeRef.current = active\n }, [active])\n\n useEffect(() => {\n if (!active) return\n let rafId = 0\n let last = performance.now()\n let following = true\n let primed = false\n let animatedH = 0\n let interacting = false\n let interactTimer: ReturnType<typeof setTimeout> | null = null\n let port: HTMLElement | null = null\n let resize: ResizeObserver | null = null\n let holding: HTMLElement | null = null\n let awayPx = 0\n\n const hold = (next: HTMLElement): void => {\n if (holding === next) return\n if (holding !== null) releaseFollow(holding)\n acquireFollow(next)\n holding = next\n }\n\n const drop = (next: HTMLElement): void => {\n if (holding === next) {\n releaseFollow(next)\n holding = null\n }\n clearVisual(next)\n }\n\n /**\n * Give the reader the visual position the glide was showing before the\n * transforms go away. While transforms carry the lag, the engine sits at\n * the floor and the effective visual top is `engine - lag`; writing that\n * keeps the handover frame-continuous, and the write shows up in\n * ChatView's ledger as reader movement, disarming its snap-follow.\n * Without a shift surface the engine already holds the interpolated top,\n * so there is nothing to compensate.\n */\n const handBackVisual = (next: HTMLElement): void => {\n if (!hasShiftSurface(next)) return\n const floor = Math.max(0, next.scrollHeight - next.clientHeight)\n if (floor <= 0) return\n const lag = Math.max(0, next.scrollHeight - animatedH)\n next.scrollTop = Math.min(floor, Math.max(0, next.scrollTop - lag))\n }\n\n const markGesture = (event: Event): void => {\n interacting = true\n if (event instanceof WheelEvent && event.deltaY < 0) awayPx += -event.deltaY\n else if (event.type === 'touchmove' || event.type === 'keydown') awayPx += FOLLOW_UNPIN_GESTURE_PX\n if (interactTimer !== null) clearTimeout(interactTimer)\n interactTimer = setTimeout(() => {\n interacting = false\n interactTimer = null\n awayPx = 0\n }, FOLLOW_GESTURE_MS)\n }\n\n const restoreBeforePaint = (): void => {\n if (!following || port === null) return\n applyVisual(port, animatedH)\n }\n\n const bindPort = (next: HTMLElement): void => {\n if (port === next) return\n if (port !== null) {\n for (const name of GESTURE_EVENTS) port.removeEventListener(name, markGesture)\n resize?.disconnect()\n }\n port = next\n for (const name of GESTURE_EVENTS) {\n port.addEventListener(name, markGesture, { passive: true })\n }\n if (typeof ResizeObserver !== 'undefined') {\n resize = new ResizeObserver(restoreBeforePaint)\n resize.observe(port)\n const proxy = resizeProxyOf(port)\n if (proxy !== null) resize.observe(proxy)\n }\n }\n\n const frame = (now: number) => {\n rafId = requestAnimationFrame(frame)\n const dt = Math.min(50, now - last)\n last = now\n const root = rootRef.current\n if (root === null) return\n const nextPort = root.closest<HTMLElement>('[data-conversation-scroll]')\n if (nextPort === null) return\n bindPort(nextPort)\n\n const floor = Math.max(0, nextPort.scrollHeight - nextPort.clientHeight)\n const reportedLag = floor - nextPort.scrollTop\n // Visual extent (content-height equivalent of the reader's scroll top):\n // content shorter than the viewport has no scrollTop to derive from, so\n // the extent is just the content height.\n const extent = Math.min(nextPort.scrollHeight, Math.max(0, nextPort.scrollHeight - reportedLag))\n\n if (!primed) {\n animatedH = extent\n following = reportedLag <= FOLLOW_SLACK_PX\n if (following) {\n hold(nextPort)\n applyVisual(nextPort, animatedH)\n }\n primed = true\n return\n }\n\n if (!following && !interacting && reportedLag <= FOLLOW_SLACK_PX) {\n following = true\n animatedH = extent\n hold(nextPort)\n } else if (following && interacting && awayPx >= FOLLOW_UNPIN_GESTURE_PX) {\n following = false\n awayPx = 0\n // Compensate before the transform clears, or the flow (turn-status\n // chrome included) jumps up by the whole lag in one frame.\n handBackVisual(nextPort)\n animatedH = nextPort.scrollHeight\n drop(nextPort)\n }\n\n if (!activeRef.current || !following) return\n hold(nextPort)\n\n const lag = nextPort.scrollHeight - animatedH\n const step = computeFollowStep(dt, {\n lag,\n speedEma: speedCpsRef.current,\n })\n if (lag <= 0.1) {\n animatedH = nextPort.scrollHeight\n } else {\n animatedH = Math.min(nextPort.scrollHeight, animatedH + step.advancePx)\n }\n applyVisual(nextPort, animatedH)\n }\n\n rafId = requestAnimationFrame(frame)\n return () => {\n cancelAnimationFrame(rafId)\n if (interactTimer !== null) clearTimeout(interactTimer)\n resize?.disconnect()\n if (port !== null) {\n for (const name of GESTURE_EVENTS) port.removeEventListener(name, markGesture)\n }\n const root = rootRef.current\n const host = root?.closest<HTMLElement>('[data-conversation-scroll]') ?? port\n if (host === null) return\n if (following) {\n // Same handback as an unpin: land on the effective visual top rather\n // than the floor, so the owner change (stream close, unmount) does\n // not snap the flow up by the remaining lag.\n handBackVisual(host)\n }\n const remaining = holding === host ? releaseFollow(host) : (followOwners.get(host) ?? 0)\n holding = null\n if (remaining === 0) clearVisual(host)\n }\n }, [active, rootRef, speedCpsRef])\n}\n","import { useRef, type ReactNode } from 'react'\nimport { useConversationFollow } from './teleprompterGlide.ts'\nimport css from './TypewriterAssistantNodeView.module.css'\n\n/**\n * Document-flow host that owns conversation-port follow while `active`.\n * Shared by assistant blocks and every other growing Chat row.\n */\nexport function FollowHost({\n active,\n speedCpsRef,\n children,\n}: {\n active: boolean\n speedCpsRef: { current: number }\n children: ReactNode\n}) {\n const rootRef = useRef<HTMLDivElement>(null)\n useConversationFollow(rootRef, active, speedCpsRef)\n return <div ref={rootRef} className={css.follow}>{children}</div>\n}\n","/**\n * Shared plugin configuration contract. The Host half defines the\n * Schemastery schema over this shape (defaults live here so both halves stay\n * symmetric); the client half falls back to the same defaults when the Host\n * boot-config bridge is absent (client-only composition).\n */\n\nimport type { StreamSmoothingPreset } from './client/useSmoothStreamContent.ts'\n\n/** Streaming render direction of the assistant node view. */\nexport type StreamMode = 'typewriter' | 'teleprompter'\n\n/** Plugin configuration validated by the Host schema and bridged to the browser half. */\nexport interface StreamConfig {\n /** Render direction: horizontal per-character reveal or uniform upward glide. */\n readonly mode: StreamMode\n /** Smoothing preset for the reveal cadence. */\n readonly preset: StreamSmoothingPreset\n /**\n * Unused at runtime; kept so existing overlays load. Live reveal tracks\n * observed arrival and ignores this seed.\n */\n readonly revealCharsPerSec: number\n /**\n * Unused at runtime; kept so existing overlays load. Follow is a\n * smooth-damp, not a cruise speed.\n */\n readonly scrollSpeedPxPerSec: number\n /**\n * Follow velocity ceiling in CSS pixels per second, so a huge first lag\n * does not teleport. Ordinary wraps stay well below this.\n */\n readonly maxScrollSpeedPxPerSec: number\n}\n\n/** Defaults shared by the Host schema and the client-side fallback. */\nexport const DEFAULT_STREAM_CONFIG: StreamConfig = {\n mode: 'typewriter',\n preset: 'balanced',\n revealCharsPerSec: 80,\n scrollSpeedPxPerSec: 48,\n maxScrollSpeedPxPerSec: 1000,\n}\n\n/**\n * Window global the Host writes into the served index HTML. The browser boot\n * graph carries no per-entry config, so this inline script is the only\n * Host-to-client configuration channel for a composed web plugin.\n */\nexport const STREAM_BOOT_GLOBAL = '__DSH_SMOOTH_STREAM_CONFIG__'\n","/**\n * User-owned settings for the smooth-stream plugin, exposed to the Host\n * settings service and edited from the Web Settings \"plugin configuration\"\n * page. This is the runtime-editable complement to {@link StreamConfig}: that\n * contract is composed at load and bridged once through the boot global, while\n * these preferences live in the durable user-settings document and take effect\n * live.\n */\n\n/** Settings namespace registered by the Host and served through the plugin RPC. */\nexport const STREAM_SETTINGS_NS = 'smooth-stream'\n\n/**\n * Preferences a user may set. Deliberately separate from {@link StreamConfig}\n * because the two change at different times: composition-time values go\n * through the boot global, a live UI edit goes through the protected plugin RPC.\n */\nexport interface StreamSettings {\n /**\n * Whether a reasoning (\"Think\") block auto-expands while it is the\n * streaming tail. Off keeps the block collapsed — the user can still open\n * it by hand — and stops the running state from re-owning the disclosure.\n */\n thinkAutoExpand: boolean\n}\n\n/** Defaults shared by the Host schema and the client-side fallback. */\nexport const DEFAULT_STREAM_SETTINGS: StreamSettings = {\n thinkAutoExpand: true,\n}\n","import { memo, useEffect, useMemo, useRef, useState, type ComponentProps, type ReactNode } from 'react'\nimport { IconThinkOutline14, JsonBlock, MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { ImageGallery, type ImageLoader, type MessageImageLabels } from '@deepseek-ai/dsh-client-ui-attachment'\nimport type { ChatNodeViewProps, TurnTailOwnerProps } from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport { AnimatedDisclosure } from './AnimatedDisclosure.tsx'\nimport { useSmoothStreamContent, type StreamSmoothingPreset } from './useSmoothStreamContent.ts'\nimport { useFpsGuard } from './useFpsGuard.ts'\nimport { FollowHost } from './FollowHost.tsx'\nimport { DEFAULT_STREAM_CONFIG, type StreamMode } from '../config.ts'\nimport { DEFAULT_STREAM_SETTINGS } from '../settings.ts'\nimport css from './TypewriterAssistantNodeView.module.css'\n\ntype AssistantProps = ChatNodeViewProps<'assistant-step'>\ntype MarkdownProps = Pick<ComponentProps<typeof MarkdownText>, 'codeLabels' | 'fileMentions' | 'text'>\n\nfunction usePrefersReducedMotion(): boolean {\n const [reduced, setReduced] = useState(\n () => typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches === true,\n )\n useEffect(() => {\n if (typeof window === 'undefined' || window.matchMedia === undefined) return\n const query = window.matchMedia('(prefers-reduced-motion: reduce)')\n const onChange = () => setReduced(query.matches)\n query.addEventListener('change', onChange)\n return () => query.removeEventListener('change', onChange)\n }, [])\n return reduced\n}\n\ninterface AnimatedMarkdownTextProps extends MarkdownProps {\n streaming: boolean\n announce: boolean\n /** True on the last text block: that block owns conversation follow. */\n ownFollow: boolean\n preset: StreamSmoothingPreset\n shouldHoldBack: () => boolean\n}\n\n/**\n * Smooth streaming text arm. While the reply runs, the accumulated source is\n * revealed through the smoother at a rate that tracks the model's arrival\n * and rendered by the Harness `MarkdownText`\n * streaming arm (incremental parse, frozen non-tail blocks), so there is no\n * raw-text tail and no text-to-markdown swap: the tree stays markdown\n * throughout. The last text block owns conversation-port follow so wraps\n * glide instead of snapping. Once the stream closes and the reveal queue\n * drains, the settled full parse (KaTeX math, fence highlighting, file\n * mentions) swaps in exactly once.\n */\nfunction AnimatedMarkdownText({\n text,\n codeLabels,\n fileMentions,\n streaming,\n announce,\n ownFollow,\n preset,\n shouldHoldBack,\n}: AnimatedMarkdownTextProps) {\n const reduced = usePrefersReducedMotion()\n const [typing, setTyping] = useState(streaming)\n const speedCpsRef = useRef(35)\n const displayed = useSmoothStreamContent(text, {\n enabled: typing && !reduced,\n preset,\n shouldHoldBack,\n speedCpsRef,\n })\n const shown = reduced ? text : displayed\n const live = typing && !reduced\n\n // The stream closed: keep revealing the remaining queue, then swap to the\n // settled parse exactly once. The markdown tree stays mounted until then.\n useEffect(() => {\n if (typing && !streaming && shown.length === text.length) setTyping(false)\n }, [shown, streaming, text, typing])\n\n if (live) {\n return (\n <>\n {announce && <span className={css.visuallyHidden} aria-live=\"polite\">{text}</span>}\n <FollowHost active={ownFollow} speedCpsRef={speedCpsRef}>\n <MarkdownText text={shown} streaming codeLabels={codeLabels} />\n </FollowHost>\n </>\n )\n }\n return <MarkdownText text={text} codeLabels={codeLabels} fileMentions={fileMentions} />\n}\n\nfunction imageLabels(t: AssistantProps['t']): MessageImageLabels {\n return {\n image: t('image.label'),\n open: t('image.openOriginal'),\n openNamed: label => t('image.openOriginalLabel', { label }),\n loading: t('image.loading'),\n loadFailed: t('image.loadFailed'),\n lightbox: {\n dialog: t('image.preview'),\n close: t('image.closePreview'),\n },\n }\n}\n\nfunction firstLine(text: string): string {\n const newline = text.indexOf('\\n')\n return newline === -1 ? text : text.slice(0, newline)\n}\n\nfunction latestLine(text: string): string {\n const visible = text.trimEnd()\n const newline = visible.lastIndexOf('\\n')\n return newline === -1 ? visible : visible.slice(newline + 1)\n}\n\n/**\n * Built-in Think disclosure with a smoothed `text` feed. Chevron and row\n * click stay on the disclosure chrome, which the plugin's AnimatedDisclosure\n * renders with a height-animated body (the harness primitive would mount and\n * unmount it, which cannot glide). The row opens only while this block is\n * the streaming tail and closes as soon as thinking ends — a later block,\n * or the assistant node settling — not when the rest of the reply is\n * still streaming.\n */\nfunction AnimatedReasoning({\n text,\n running,\n preset,\n thinkAutoExpand,\n shouldHoldBack,\n t,\n}: {\n text: string\n running: boolean\n preset: StreamSmoothingPreset\n thinkAutoExpand: boolean\n shouldHoldBack: () => boolean\n t: AssistantProps['t']\n}) {\n const reduced = usePrefersReducedMotion()\n const [expanded, setExpanded] = useState(running && thinkAutoExpand)\n const summaryRef = useRef<HTMLSpanElement>(null)\n const speedCpsRef = useRef(35)\n const displayed = useSmoothStreamContent(text, {\n enabled: running && !reduced,\n preset,\n shouldHoldBack,\n speedCpsRef,\n })\n const shown = running && !reduced ? displayed : text\n const summary = running ? latestLine(shown) : firstLine(text)\n\n useEffect(() => {\n // Only the running state owns disclosure while auto-expand is on; with it\n // off, a manual toggle is never wrestled back by the stream.\n if (thinkAutoExpand) setExpanded(running)\n }, [running, thinkAutoExpand])\n\n useEffect(() => {\n const element = summaryRef.current\n if (element === null) return\n element.scrollLeft = running ? element.scrollWidth - element.clientWidth : 0\n }, [running, summary])\n\n return (\n <FollowHost active={running} speedCpsRef={speedCpsRef}>\n <div className={css.think} data-variant=\"think\" data-state={running ? 'running' : 'ok'}>\n {running && <span className={css.visuallyHidden}>{t('row.running')}</span>}\n <AnimatedDisclosure\n rowClassName={css.thinkRow}\n leadingClassName={css.thinkLeading}\n titleClassName={css.thinkTitle}\n chevronClassName={css.thinkChevron}\n icon={<IconThinkOutline14 size={14} />}\n title=\"Think\"\n open={expanded}\n onToggle={() => { setExpanded(value => !value) }}\n collapsedContent={(\n <>\n <span className={css.thinkSeparator} aria-hidden />\n <span ref={summaryRef} className={css.thinkSummary} data-follow-end={running || undefined}>{summary}</span>\n </>\n )}\n >\n <div className={css.thinkBody}>{shown}</div>\n </AnimatedDisclosure>\n </div>\n </FollowHost>\n )\n}\n\n/**\n * Assistant node renderer for the typewriter overlay. Text observed while\n * streaming is revealed by the smoother through the Harness Markdown\n * renderer at a rate that tracks arrival. Reasoning blocks keep the\n * built-in Think disclosure and only receive a smoothed text feed; the\n * last text or reasoning block owns conversation-port follow so wraps\n * glide. The FPS guard holds offscreen\n * reveals when the frame rate is degraded. Settled text renders with the\n * full Markdown pipeline.\n */\nexport const TypewriterAssistantNodeView = memo(function TypewriterAssistantNodeView({\n mode: _mode = DEFAULT_STREAM_CONFIG.mode,\n preset = DEFAULT_STREAM_CONFIG.preset,\n revealCharsPerSec: _revealCharsPerSec = DEFAULT_STREAM_CONFIG.revealCharsPerSec,\n scrollSpeedPxPerSec: _scrollSpeedPxPerSec = DEFAULT_STREAM_CONFIG.scrollSpeedPxPerSec,\n maxScrollSpeedPxPerSec: _maxScrollSpeedPxPerSec = DEFAULT_STREAM_CONFIG.maxScrollSpeedPxPerSec,\n thinkAutoExpand = DEFAULT_STREAM_SETTINGS.thinkAutoExpand,\n node,\n useTurnData,\n openFile,\n loadImage,\n fileMentions,\n t,\n}: AssistantProps & {\n mode?: StreamMode\n preset?: StreamSmoothingPreset\n revealCharsPerSec?: number\n scrollSpeedPxPerSec?: number\n maxScrollSpeedPxPerSec?: number\n thinkAutoExpand?: boolean\n}) {\n const data = node.data\n const streaming = data.status === 'running'\n const { ref: guardRef, shouldHoldBack } = useFpsGuard(streaming)\n const rootSpeedRef = useRef(35)\n const turn = node.location.kind === 'turn' || node.location.kind === 'step'\n ? node.location.turn\n : undefined\n const tail = useTurnData('turn-tail')\n const owner = useMemo<TurnTailOwnerProps | undefined>(() => {\n if (turn?.status !== 'closed' || data.finalNode === undefined) return undefined\n if (tail?.closing?.finalNode.seq !== data.finalNode.seq) return undefined\n return { turn, seq: data.finalNode.seq, openFile }\n }, [data.finalNode, openFile, tail, turn])\n const mentions = useMemo(\n () => owner === undefined ? undefined : fileMentions(owner),\n [fileMentions, owner],\n )\n const codeLabels = useMemo(() => ({ copyLabel: t('copy'), copiedLabel: t('copied') }), [t])\n const imageLoader: ImageLoader = loadImage ?? (async () => {\n throw new Error(t('image.serviceUnavailable'))\n })\n const hasVisible = streaming\n || data.status === 'interrupted'\n || data.blocks.some(block => block.kind !== 'tool-call')\n if (!hasVisible) return null\n\n const rendered: ReactNode[] = []\n const last = data.blocks.length - 1\n let lastFollow = -1\n for (let index = 0; index < data.blocks.length; index += 1) {\n const kind = data.blocks[index]?.kind\n if (kind === 'text' || kind === 'reasoning') lastFollow = index\n }\n for (let index = 0; index < data.blocks.length; index += 1) {\n const block = data.blocks[index]\n if (block === undefined) continue\n switch (block.kind) {\n case 'text':\n rendered.push(\n <AnimatedMarkdownText\n key={index}\n text={block.text}\n codeLabels={codeLabels}\n fileMentions={mentions}\n streaming={streaming}\n announce={index === last}\n ownFollow={!streaming && index === lastFollow}\n preset={preset}\n shouldHoldBack={shouldHoldBack}\n />,\n )\n break\n case 'reasoning':\n rendered.push(\n <AnimatedReasoning\n key={index}\n text={block.text}\n running={streaming && index === last}\n preset={preset}\n thinkAutoExpand={thinkAutoExpand}\n shouldHoldBack={shouldHoldBack}\n t={t}\n />,\n )\n break\n case 'image': {\n const start = index\n const group = [block]\n while (index + 1 < data.blocks.length) {\n const next = data.blocks[index + 1]\n if (next === undefined || next.kind !== 'image') break\n group.push(next)\n index += 1\n }\n rendered.push(\n <ImageGallery key={start} images={group} load={imageLoader} align=\"start\" labels={imageLabels(t)} />,\n )\n break\n }\n case 'tool-call':\n break\n case 'other':\n rendered.push(\n <JsonBlock\n key={index}\n label={t('message.unknownBlock')}\n payload={block.block}\n truncatedLabel={total => t('json.truncated', { total })}\n />,\n )\n break\n }\n }\n\n return (\n <div ref={guardRef} className={css.root} data-streaming={streaming || undefined}>\n <FollowHost active={streaming} speedCpsRef={rootSpeedRef}>\n <div className={css.body}>\n {rendered}\n {data.status === 'interrupted' && <span className={css.stopped}>{t('message.stopped')}</span>}\n </div>\n </FollowHost>\n </div>\n )\n})\n","import { createElement, useRef, type ComponentType } from 'react'\nimport { FollowHost } from './FollowHost.tsx'\n\n/** Props forwarded through a follow wrap; extra kit seats pass through. */\nexport type FollowWrapProps = {\n node?: unknown\n renderSlot?: unknown\n} & Record<string, unknown>\n\n/**\n * True while a Chat node is still growing: an assistant/workflow `status:\n * 'running'` payload, a Tool root that has not settled (`kind` absent), or a\n * model-retry whose current attempt is still `scheduled`.\n * @param node - The Chat node's view `node` prop.\n * @returns whether this row should own conversation follow.\n */\nexport function isGrowingChatNode(node: unknown): boolean {\n if (node === null || typeof node !== 'object' || !('data' in node)) return false\n const data = (node as { data: unknown }).data\n if (data === null || typeof data !== 'object') return false\n if ('status' in data && (data as { status: unknown }).status === 'running') return true\n if ('root' in data) {\n const root = (data as { root: unknown }).root\n if (root !== null && typeof root === 'object' && !('kind' in root)) return true\n }\n if ('current' in data) {\n const current = (data as { current: unknown }).current\n if (\n current !== null\n && typeof current === 'object'\n && 'retryState' in current\n && (current as { retryState: unknown }).retryState === 'scheduled'\n ) return true\n }\n return false\n}\n\n/**\n * Wrap a prior Chat node renderer so a growing row shares conversation\n * follow. Presentation stays with the wrapped component; kit seats\n * (`renderSlot`, locale, inject) pass through unchanged.\n * @param Inner - The already-registered row component.\n * @returns A follow-hosted row.\n */\nexport function wrapFollowNodeView(Inner: ComponentType<FollowWrapProps>) {\n return function TypewriterFollowNodeView(props: FollowWrapProps) {\n const speedCpsRef = useRef(35)\n return (\n <FollowHost active={isGrowingChatNode(props.node)} speedCpsRef={speedCpsRef}>\n {createElement(Inner, props)}\n </FollowHost>\n )\n }\n}\n","/**\n * The smooth-stream plugin configuration card, rendered inside the Web\n * Settings \"plugin configuration\" page. One toggle, staged until the user\n * saves — the same shape as the Host-shipped cards, hand-drawn because the\n * Host cards' chrome is not exported for reuse.\n */\n\nimport { useState } from 'react'\nimport type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client'\nimport { IconChevronDownOutline14, IconRefreshOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { SmoothStreamCardFace } from './smooth-stream-card-controller.ts'\nimport css from './SmoothStreamCard.module.css'\n\n/** Props the renderer binds for the smooth-stream card. */\nexport type SmoothStreamCardProps =\n PropsRuntime<'settings.plugin.item'>\n & PropsLocale<'settings.smoothStream'>\n & InjectFace<SmoothStreamCardFace>\n\n/** Render the smooth-stream card independently of the core settings namespace allowlist. */\nexport function SmoothStreamCard(props: SmoothStreamCardProps) {\n const { t } = props\n const [open, setOpen] = useState(false)\n const state = props.useSmoothStreamCard(snapshot => snapshot)\n const blocked = !state.dirty || state.saving || state.status !== 'ready'\n const versionLabel = state.version === undefined\n ? null\n : t(state.installation === 'development' ? 'developmentVersion' : 'version')\n .replace('{version}', state.version)\n\n return (\n <li className={open ? `${css.card} ${css.cardOpen}` : css.card}>\n <button\n type=\"button\"\n className={css.header}\n aria-expanded={open}\n onClick={() => { setOpen(!open) }}\n >\n <span className={css.headText}>\n <span className={css.name}>{t('title')}</span>\n <span className={css.description}>{t('description')}</span>\n </span>\n {versionLabel === null ? null : <span className={css.version}>{versionLabel}</span>}\n {state.dirty ? <span className={css.pending}>{t('unsaved')}</span> : null}\n <IconChevronDownOutline14 className={open ? `${css.chevron} ${css.chevronOpen}` : css.chevron} />\n </button>\n {open\n ? (\n <div className={css.body}>\n {state.status === 'loading' ? <p className={css.readOnly} role=\"status\">{t('loading')}</p> : null}\n {state.status === 'unavailable' ? (\n <div className={css.failure}>\n <p className={css.readOnly} role=\"status\">{t('unavailable')}</p>\n <button type=\"button\" className={css.discard} onClick={props.reload}>{t('retry')}</button>\n </div>\n ) : null}\n {state.status === 'ready' ? (\n <>\n {!state.writable ? <p className={css.readOnly} role=\"status\">{t('readOnly')}</p> : null}\n <label className={css.field}>\n <span className={css.fieldHead}>\n <span className={css.label}>{t('thinkAutoExpand')}</span>\n <input\n type=\"checkbox\"\n className={css.toggle}\n checked={state.thinkAutoExpand}\n disabled={!state.writable}\n onChange={(event) => { props.edit(event.target.checked) }}\n />\n </span>\n <span className={css.hint}>{t('thinkAutoExpandHint')}</span>\n </label>\n <div className={css.updateRow}>\n <span className={css.updateCopy}>\n <span className={css.label}>{t('updates')}</span>\n <span className={css.hint}>\n {state.restartRequired\n ? t('restartRequired')\n : state.installation === 'npm' ? t('updateHint')\n : state.installation === 'development' ? t('developmentBuild') : t('updateUnavailable')}\n </span>\n </span>\n <button\n type=\"button\"\n className={css.update}\n disabled={!state.canUpgrade || state.upgrading || state.restartRequired}\n title={state.canUpgrade ? undefined : t('updateUnavailable')}\n onClick={props.upgrade}\n >\n <span aria-hidden=\"true\"><IconRefreshOutline14 /></span>\n {t(state.upgrading ? 'updating' : 'update')}\n </button>\n </div>\n {state.upgradeFailed ? <p className={css.failed} role=\"status\">{t('updateFailed')}</p> : null}\n <div className={css.footer}>\n {state.failed ? <p className={css.failed} role=\"status\">{t('saveFailed')}</p> : null}\n <button\n type=\"button\"\n className={css.discard}\n disabled={!state.dirty || state.saving}\n onClick={props.discard}\n >\n {t('discard')}\n </button>\n <button\n type=\"button\"\n className={css.save}\n disabled={blocked}\n onClick={props.save}\n >\n {t(state.saving ? 'saving' : 'save')}\n </button>\n </div>\n </>\n ) : null}\n </div>\n )\n : null}\n </li>\n )\n}\n","/** Staged form state for the plugin-owned smooth-stream settings RPC. */\n\nimport { createSnapshotStore, type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'\nimport { DEFAULT_STREAM_SETTINGS } from '../settings.ts'\nimport type { StreamInstallationKind, StreamSettingsView } from '../settings-api.ts'\nimport type { SmoothStreamSettingsApi } from './smooth-stream-settings-api.ts'\n\n/** What the smooth-stream card renders. It remains visible while its Host RPC loads. */\nexport interface SmoothStreamCardState {\n status: 'loading' | 'ready' | 'unavailable'\n writable: boolean\n dirty: boolean\n saving: boolean\n failed: boolean\n thinkAutoExpand: boolean\n version: string | undefined\n installation: StreamInstallationKind\n canUpgrade: boolean\n upgrading: boolean\n upgradeFailed: boolean\n restartRequired: boolean\n}\n\n/** The registration-side face injected into the settings slot renderer. */\nexport interface SmoothStreamCardFace {\n hooks: {\n smoothStreamCard: SnapshotStore<SmoothStreamCardState>\n }\n edit: (value: boolean) => void\n save: () => void\n discard: () => void\n reload: () => void\n upgrade: () => void\n}\n\n/** Bridges the plugin's protected Host interface onto a staged settings form. */\nexport class SmoothStreamCardController {\n private readonly store = createSnapshotStore<SmoothStreamCardState>(this.projection())\n private loaded: StreamSettingsView | undefined\n private staged: boolean | undefined\n private saving = false\n private failed = false\n private upgrading = false\n private upgradeFailed = false\n private restartRequired = false\n private loadGeneration = 0\n private loadStatus: 'loading' | 'ready' | 'unavailable' = 'loading'\n\n constructor(private readonly api: SmoothStreamSettingsApi) {}\n\n /** Begin the background read after the card has been registered. */\n start(): void {\n void this.load()\n }\n\n /** Ignore a late response after the surrounding optional services unload. */\n stop(): void {\n this.loadGeneration += 1\n }\n\n /** Current card snapshot, also consumed by the streaming preference cell. */\n getSnapshot(): SmoothStreamCardState {\n return this.store.getSnapshot()\n }\n\n /** Subscribe to state changes. */\n subscribe(listener: () => void): () => void {\n return this.store.subscribe(listener)\n }\n\n /** Build the face consumed by the settings slot renderer. */\n inject(): SmoothStreamCardFace {\n return {\n hooks: { smoothStreamCard: this.store },\n edit: (value) => {\n this.staged = value\n this.failed = false\n this.publish()\n },\n save: () => { void this.save() },\n discard: () => {\n if (this.staged === undefined && !this.failed) return\n this.staged = undefined\n this.failed = false\n this.publish()\n },\n reload: () => { void this.load() },\n upgrade: () => { void this.upgrade() },\n }\n }\n\n private projection(): SmoothStreamCardState {\n return {\n status: this.loadStatus,\n writable: this.loaded?.writable ?? false,\n dirty: this.staged !== undefined,\n saving: this.saving,\n failed: this.failed,\n thinkAutoExpand: this.staged ?? this.loaded?.thinkAutoExpand ?? DEFAULT_STREAM_SETTINGS.thinkAutoExpand,\n version: this.loaded?.version,\n installation: this.loaded?.installation ?? 'unmanaged',\n canUpgrade: this.loaded?.canUpgrade ?? false,\n upgrading: this.upgrading,\n upgradeFailed: this.upgradeFailed,\n restartRequired: this.restartRequired,\n }\n }\n\n private async load(): Promise<void> {\n const generation = ++this.loadGeneration\n this.loadStatus = 'loading'\n this.loaded = undefined\n this.publish()\n try {\n const view = await this.api.read()\n if (generation !== this.loadGeneration) return\n this.loaded = view\n this.loadStatus = 'ready'\n } catch {\n if (generation !== this.loadGeneration) return\n this.loaded = undefined\n this.loadStatus = 'unavailable'\n }\n this.publish()\n }\n\n private async save(): Promise<void> {\n if (this.staged === undefined || this.saving || this.loaded?.writable !== true) return\n const value = this.staged\n this.saving = true\n this.failed = false\n this.publish()\n try {\n this.loaded = await this.api.write(value)\n this.staged = undefined\n } catch {\n this.failed = true\n }\n this.saving = false\n this.publish()\n }\n\n private async upgrade(): Promise<void> {\n if (this.loaded?.canUpgrade !== true || this.upgrading) return\n this.upgrading = true\n this.upgradeFailed = false\n this.restartRequired = false\n this.publish()\n try {\n const result = await this.api.upgrade()\n this.restartRequired = result.restartRequired\n } catch {\n this.upgradeFailed = true\n }\n this.upgrading = false\n this.publish()\n }\n\n private publish(): void {\n this.store.set(this.projection())\n }\n}\n","/** Shared wire vocabulary for the plugin-owned settings RPC channel. */\n\n/** Dedicated, loopback-only RPC channel registered by the Host half. */\nexport const STREAM_SETTINGS_RPC_CHANNEL = '/smooth-stream'\n\n/** Endpoints accepted by {@link STREAM_SETTINGS_RPC_CHANNEL}. */\nexport const STREAM_SETTINGS_RPC = {\n read: 'settings.read',\n write: 'settings.write',\n upgrade: 'plugin.upgrade',\n} as const\n\n/** How the active profile supplied this plugin. */\nexport type StreamInstallationKind = 'npm' | 'development' | 'unmanaged'\n\n/** Redacted, plugin-owned configuration state returned to the browser. */\nexport interface StreamSettingsView {\n /** Version of the package currently running in the Host process. */\n version: string\n /** Source class of this package in the active profile. */\n installation: StreamInstallationKind\n /** Whether the Host settings provider permits a write. */\n writable: boolean\n /** Current resolved preference. */\n thinkAutoExpand: boolean\n /** Whether a fixed npm update command is safe to offer. */\n canUpgrade: boolean\n}\n\n/** Successful package update acknowledgement; loading the new code needs a restart. */\nexport interface StreamUpgradeView {\n restartRequired: true\n}\n","/** Browser adapter for the Host-owned smooth-stream settings RPC. */\n\nimport type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client'\nimport {\n STREAM_SETTINGS_RPC,\n STREAM_SETTINGS_RPC_CHANNEL,\n type StreamSettingsView,\n type StreamUpgradeView,\n} from '../settings-api.ts'\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : undefined\n}\n\nfunction settingsView(value: unknown): StreamSettingsView {\n const data = record(value)\n if (data === undefined\n || typeof data.version !== 'string'\n || !['npm', 'development', 'unmanaged'].includes(data.installation as string)\n || typeof data.writable !== 'boolean'\n || typeof data.thinkAutoExpand !== 'boolean'\n || typeof data.canUpgrade !== 'boolean') {\n throw new Error('dsh-smooth-stream: malformed settings response')\n }\n return data as unknown as StreamSettingsView\n}\n\nfunction upgradeView(value: unknown): StreamUpgradeView {\n const data = record(value)\n if (data?.restartRequired !== true) throw new Error('dsh-smooth-stream: malformed update response')\n return { restartRequired: true }\n}\n\nfunction accepted(result: Awaited<ReturnType<ConnectionHandle['rpc']['call']>>): unknown {\n if (!result.ok) throw new Error(result.error.message)\n return result.value\n}\n\n/** Narrow client contract consumed by the staged settings-card controller. */\nexport interface SmoothStreamSettingsApi {\n read(): Promise<StreamSettingsView>\n write(thinkAutoExpand: boolean): Promise<StreamSettingsView>\n upgrade(): Promise<StreamUpgradeView>\n}\n\n/** Build the typed facade over the generic Connection RPC service. */\nexport function createSmoothStreamSettingsApi(connection: ConnectionHandle): SmoothStreamSettingsApi {\n return {\n async read(): Promise<StreamSettingsView> {\n return settingsView(accepted(await connection.rpc.call(STREAM_SETTINGS_RPC_CHANNEL, STREAM_SETTINGS_RPC.read, {})))\n },\n async write(thinkAutoExpand: boolean): Promise<StreamSettingsView> {\n return settingsView(accepted(await connection.rpc.call(\n STREAM_SETTINGS_RPC_CHANNEL,\n STREAM_SETTINGS_RPC.write,\n { thinkAutoExpand },\n )))\n },\n async upgrade(): Promise<StreamUpgradeView> {\n return upgradeView(accepted(await connection.rpc.call(STREAM_SETTINGS_RPC_CHANNEL, STREAM_SETTINGS_RPC.upgrade, {})))\n },\n }\n}\n","/** Locale bundles for the smooth-stream plugin configuration card. */\n\n/** Dictionary namespace owned by this plugin's settings card. */\nexport const NS = 'settings.smoothStream'\n\n/** Locale keys the card renders. */\nexport type SmoothStreamLocaleKey =\n | 'title' | 'description'\n | 'thinkAutoExpand' | 'thinkAutoExpandHint'\n | 'readOnly' | 'loading' | 'unavailable' | 'retry'\n | 'version' | 'developmentVersion'\n | 'updates' | 'updateHint' | 'developmentBuild' | 'updateUnavailable'\n | 'update' | 'updating' | 'restartRequired' | 'updateFailed'\n | 'save' | 'saving' | 'discard' | 'unsaved' | 'saveFailed'\n\n/** English copy. */\nexport const en: Record<SmoothStreamLocaleKey, string> = {\n title: 'Smooth stream',\n description: 'How replies are revealed while they stream.',\n thinkAutoExpand: 'Auto-expand thinking',\n thinkAutoExpandHint: 'Open the thinking block while it streams. Turn off to keep it collapsed.',\n readOnly: 'This deployment stores settings read-only.',\n loading: 'Loading plugin settings…',\n unavailable: 'Plugin settings are unavailable in this connection.',\n retry: 'Retry',\n version: 'Version {version}',\n developmentVersion: 'Development version {version}',\n updates: 'Updates',\n updateHint: 'Install the newest npm version, then restart Harness.',\n developmentBuild: 'Linked source; updates are managed in the checkout.',\n updateUnavailable: 'Updates are available only for an npm profile installation.',\n update: 'Update',\n updating: 'Updating…',\n restartRequired: 'Updated. Restart Harness to load the new version.',\n updateFailed: 'The package update failed; your current version is unchanged.',\n save: 'Save',\n saving: 'Saving…',\n discard: 'Discard',\n unsaved: 'Unsaved',\n saveFailed: 'The deployment did not accept these values; they were left for you to correct.',\n}\n\n/** Simplified Chinese copy. */\nexport const zh: Record<SmoothStreamLocaleKey, string> = {\n title: '丝滑流式',\n description: '回复在流式输出时如何逐字展现。',\n thinkAutoExpand: '自动展开思考',\n thinkAutoExpandHint: '思考块在流式时自动展开;关闭后保持折叠,可手动展开。',\n readOnly: '本部署的设置为只读。',\n loading: '正在加载插件设置…',\n unavailable: '当前连接无法访问插件设置。',\n retry: '重试',\n version: '版本 {version}',\n developmentVersion: '开发版本 {version}',\n updates: '更新',\n updateHint: '安装最新 npm 版本后重启 Harness。',\n developmentBuild: '当前为本地链接版本,请在源码目录管理更新。',\n updateUnavailable: '只有 profile 使用 npm 包时才能更新。',\n update: '更新',\n updating: '更新中…',\n restartRequired: '已更新;重启 Harness 后加载新版本。',\n updateFailed: '包更新失败,当前版本未改变。',\n save: '保存',\n saving: '保存中…',\n discard: '放弃修改',\n unsaved: '未保存',\n saveFailed: '本部署没有接受这些值,已保留供你修改。',\n}\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n 'settings.smoothStream': SmoothStreamLocaleKey\n }\n}\n","import { createElement, useSyncExternalStore, type ComponentType } from 'react'\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: the connection Context merge and the plugins section's SlotMap\n// entry ('settings.plugin.item').\nimport type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client'\nimport type { ChatNodeViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport { TypewriterAssistantNodeView } from './TypewriterAssistantNodeView.tsx'\nimport { wrapFollowNodeView, type FollowWrapProps } from './TypewriterToolNodeView.tsx'\nimport { SmoothStreamCard } from './SmoothStreamCard.tsx'\nimport { SmoothStreamCardController } from './smooth-stream-card-controller.ts'\nimport { createSmoothStreamSettingsApi } from './smooth-stream-settings-api.ts'\nimport { NS as SETTINGS_NS, en, zh } from './locales.ts'\nimport { DEFAULT_STREAM_CONFIG, STREAM_BOOT_GLOBAL, type StreamConfig } from '../config.ts'\nimport { DEFAULT_STREAM_SETTINGS } from '../settings.ts'\n\n/**\n * Cordis services required by the browser half. Only `slots` is load-bearing\n * for the stream itself; locale and Connection power the configuration card\n * and are wired through `ctx.inject` below so a deployment without them still\n * streams with defaults.\n */\nexport const inject = ['slots']\n\ntype AssistantProps = ChatNodeViewProps<'assistant-step'>\n\nconst STREAM_MODES: readonly string[] = ['typewriter', 'teleprompter']\nconst STREAM_PRESETS: readonly string[] = ['realtime', 'balanced', 'silky']\n\n/** Human-authored rows stay on the built-in renderer; `assistant-step` is replaced. */\nconst SKIP_WRAP = new Set(['assistant-step', 'user', 'steering', 'command-input'])\n\n/**\n * Read the Host-bridged boot config. The inline script is produced by this\n * plugin's Host half from a schema-validated value, so only the structural\n * guarantees that could break between the two halves are re-checked: the\n * global is absent when the client runs without its Host entry (defaults\n * apply), and any present-but-malformed value fails loudly instead of\n * rendering a half-configured view.\n * @returns The resolved configuration for the assistant node view.\n */\nfunction readBootConfig(): StreamConfig {\n const raw = (globalThis as Record<string, unknown>)[STREAM_BOOT_GLOBAL]\n if (raw === undefined) {\n console.info('[dsh-smooth-stream] no host config bridge; using defaults')\n return DEFAULT_STREAM_CONFIG\n }\n if (\n typeof raw !== 'object' || raw === null\n || !STREAM_MODES.includes((raw as StreamConfig).mode)\n || !STREAM_PRESETS.includes((raw as StreamConfig).preset)\n || typeof (raw as StreamConfig).revealCharsPerSec !== 'number'\n || typeof (raw as StreamConfig).scrollSpeedPxPerSec !== 'number'\n || typeof (raw as StreamConfig).maxScrollSpeedPxPerSec !== 'number'\n ) {\n throw new Error(`[dsh-smooth-stream] malformed ${STREAM_BOOT_GLOBAL} boot global: ${JSON.stringify(raw)}`)\n }\n return raw as StreamConfig\n}\n\n/**\n * Wrap every keyed Chat row except `assistant-step` in place. A second\n * register with the same `children` table throws because the child slot is\n * already declared, and only the winning entry receives `renderSlot`;\n * swapping `entry.component` keeps the original children, locale, and inject\n * seats. `assistant-step` is replaced below so text and Think use the\n * typewriter reveal.\n * @param ctx - Browser context carrying the slot registry.\n * @returns Restorer that puts the original components back.\n */\nfunction wrapGrowingChatRows(ctx: ClientContext): () => void {\n const restores: Array<() => void> = []\n const wrapped = new WeakSet<object>()\n\n const wrapAll = (): void => {\n for (const entry of ctx.slots.entries('conversation.chat.node')) {\n const key = entry.options.key\n if (key === undefined || SKIP_WRAP.has(key)) continue\n const current = entry.component\n if (typeof current !== 'function' || wrapped.has(current)) continue\n const inner = current as ComponentType<FollowWrapProps>\n const next = wrapFollowNodeView(inner)\n wrapped.add(next)\n entry.component = next\n restores.push(() => {\n if (entry.component === next) entry.component = inner\n })\n }\n }\n\n wrapAll()\n const off = ctx.on('slots/changed', (key: string) => {\n if (key === 'conversation.chat.node') wrapAll()\n })\n return () => {\n off()\n for (const restore of restores) restore()\n }\n}\n\n/**\n * A live preference cell read by `useSyncExternalStore`. It starts on the\n * shared default and, once the plugin-owned settings controller is attached,\n * tracks the resolved `thinkAutoExpand` value. A composition (or test) that\n * ships no settings surface keeps the cell on the default.\n */\nclass PreferenceCell {\n private readonly listeners = new Set<() => void>()\n private card: SmoothStreamCardController | undefined\n private value = DEFAULT_STREAM_SETTINGS.thinkAutoExpand\n\n /** Re-point the cell at the plugin-owned settings controller. */\n attach(card: SmoothStreamCardController): () => void {\n this.card = card\n this.refresh()\n const unsubscribe = card.subscribe(() => { this.refresh() })\n return () => {\n unsubscribe()\n if (this.card !== card) return\n this.card = undefined\n this.refresh()\n }\n }\n\n private read(): boolean {\n return this.card?.getSnapshot().thinkAutoExpand ?? DEFAULT_STREAM_SETTINGS.thinkAutoExpand\n }\n\n private refresh(): void {\n const next = this.read()\n if (next === this.value) return\n this.value = next\n for (const listener of this.listeners) listener()\n }\n\n readonly getSnapshot = (): boolean => this.value\n\n readonly subscribe = (listener: () => void): () => void => {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n}\n\n/**\n * Register the typewriter renderer after the conversation package declares the\n * keyed Chat node seat. A lower priority shadows the built-in assistant row;\n * every other growing row is wrapped in place so Tool cards, retries, and\n * workflow runs share conversation follow. The Host-bridged configuration\n * selects the render direction, smoothing preset, and glide speed; the\n * plugin-owned settings RPC supplies the live auto-expand preference when the\n * settings surface is composed.\n * @param ctx - Browser context carrying the shared slot registry.\n */\nexport function apply(ctx: ClientContext): void {\n const config = readBootConfig()\n const preference = new PreferenceCell()\n\n // The card talks to the plugin-owned loopback RPC, so the core settings\n // namespace allowlist cannot make it disappear. The stream still applies\n // with defaults when the optional Settings UI or Connection is absent.\n ctx.inject(['slots', 'locale', 'connection'], (settingsCtx) => {\n const card = new SmoothStreamCardController(\n // The shared Context augmentation also carries the Host-side Connection\n // shape. This browser entry runs after the client provider installs its\n // handle, so narrow through unknown to its client contract here.\n createSmoothStreamSettingsApi(settingsCtx.get('connection') as unknown as ConnectionHandle),\n )\n const detachPreference = preference.attach(card)\n card.start()\n settingsCtx.effect(() => settingsCtx.locale.register(SETTINGS_NS, { zh, en }), 'dsh-smooth-stream: settings dictionaries')\n settingsCtx.slots.inject('settings.plugin.item', () => settingsCtx.slots.register({\n name: 'settings.plugin.item',\n id: 'smooth-stream',\n order: 30,\n locale: SETTINGS_NS,\n inject: () => card.inject(),\n }, SmoothStreamCard))\n return () => {\n card.stop()\n detachPreference()\n }\n })\n\n const configured = function StreamConfiguredView(props: AssistantProps) {\n const thinkAutoExpand = useSyncExternalStore(\n preference.subscribe,\n preference.getSnapshot,\n preference.getSnapshot,\n )\n return createElement(TypewriterAssistantNodeView, {\n ...props,\n mode: config.mode,\n preset: config.preset,\n revealCharsPerSec: config.revealCharsPerSec,\n scrollSpeedPxPerSec: config.scrollSpeedPxPerSec,\n maxScrollSpeedPxPerSec: config.maxScrollSpeedPxPerSec,\n thinkAutoExpand,\n })\n }\n ctx.slots.inject('conversation.chat.node', () => {\n const unwrap = wrapGrowingChatRows(ctx)\n const unshadow = ctx.slots.register({\n name: 'conversation.chat.node',\n key: 'assistant-step',\n priority: -100,\n locale: 'conversation',\n registrant: 'dsh-smooth-stream',\n }, configured)\n return () => {\n unshadow()\n unwrap()\n }\n })\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["css","IconChevronDownOutline14","clamp","useState","useRef","useCallback","useRef","useCallback","useRef","useRef","css","useState","useRef","css","MarkdownText","IconThinkOutline14","memo","useMemo","ImageGallery","JsonBlock","useRef","createElement","useState","css","IconChevronDownOutline14","IconRefreshOutline14","createSnapshotStore","SETTINGS_NS","useSyncExternalStore","createElement"],"sources":["../src/client/AnimatedDisclosure.tsx","../src/client/useSmoothStreamContent.ts","../src/client/useFpsGuard.ts","../src/client/teleprompterGlide.ts","../src/client/FollowHost.tsx","../src/config.ts","../src/settings.ts","../src/client/TypewriterAssistantNodeView.tsx","../src/client/TypewriterToolNodeView.tsx","../src/client/SmoothStreamCard.tsx","../src/client/smooth-stream-card-controller.ts","../src/settings-api.ts","../src/client/smooth-stream-settings-api.ts","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["// AnimatedDisclosure: the harness DisclosureRow chrome (24px row, hover\n// chevron preview, whole-row click/Enter/Space toggle) with one deliberate\n// difference - the expanded body stays mounted while collapsed and animates\n// between 0fr and 1fr grid tracks, so expand/collapse glides instead of\n// snapping. The harness primitive unmounts closed children (`{open &&\n// children}`) and a plugin cannot change that in place, so this fork mirrors\n// its DOM shape and `data-disclosure-row` contract: host styling keyed on the\n// row attribute and the Think chrome keep working unchanged.\n\nimport { type KeyboardEvent, type ReactNode } from 'react'\nimport { IconChevronDownOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'\nimport css from './TypewriterAssistantNodeView.module.css'\n\n/** Class-name join for optional overlay classes over the chrome defaults. */\nfunction cx(...parts: Array<string | undefined>): string {\n return parts.filter(part => part !== undefined && part !== '').join(' ')\n}\n\nexport interface AnimatedDisclosureProps {\n icon: ReactNode\n title: string\n open: boolean\n onToggle: () => void\n collapsedContent?: ReactNode\n children?: ReactNode\n rowClassName?: string | undefined\n leadingClassName?: string | undefined\n titleClassName?: string | undefined\n chevronClassName?: string | undefined\n}\n\n/**\n * Render one disclosure header whose expanded body is height-animated.\n * @param props - Visual content, controlled open state, and the toggle\n * callback fired by row click and Enter/Space.\n * @returns the animated disclosure row.\n */\nexport function AnimatedDisclosure({\n icon,\n title,\n open,\n onToggle,\n collapsedContent,\n children,\n rowClassName,\n leadingClassName,\n titleClassName,\n chevronClassName,\n}: AnimatedDisclosureProps) {\n const toggleFromKeyboard = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key !== 'Enter' && event.key !== ' ') return\n event.preventDefault()\n onToggle()\n }\n return (\n <div className={css.disclosureRoot} data-open={open || undefined}>\n <div\n className={cx(css.disclosureRow, rowClassName)}\n data-disclosure-row\n data-expandable=\"\"\n role=\"button\"\n tabIndex={0}\n aria-expanded={open}\n onClick={onToggle}\n onKeyDown={toggleFromKeyboard}\n >\n <span className={cx(css.disclosureLeading, leadingClassName)}>\n {open\n ? <IconChevronDownOutline14 className={chevronClassName} />\n : (\n <>\n <span className={css.disclosureIconIdle}>{icon}</span>\n <IconChevronDownOutline14 className={cx(chevronClassName, css.disclosureChevronHover)} />\n </>\n )}\n </span>\n <span className={cx(css.disclosureTitle, titleClassName)}>{title}</span>\n {!open && collapsedContent}\n </div>\n <div className={css.disclosureContent} data-disclosure-content data-collapsed={open ? undefined : ''}>\n {children}\n </div>\n </div>\n )\n}\n","/**\n * Stream-smoothing reveal hook.\n *\n * Buffers the model's chunked text and reveals it at a cadence that tracks\n * the observed arrival rate, so a long reply never dumps whole paragraphs at\n * once and a fast stream never stutters. Port of lobe-ui's smoother: EMA\n * arrival cps + chunk size, backlog pressure, commit-interval widening with\n * tail length, and a flush-speed settle drain once the input idles. The\n * reveal decision is the pure {@link computeRevealStep} for unit tests.\n *\n * `shouldHoldBack` is the performance guard's veto: while it returns true the\n * loop keeps measuring but skips the DOM commit, so an offscreen reply never\n * competes with visible frames when the frame rate is degraded.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nexport type StreamSmoothingPreset = 'realtime' | 'balanced' | 'silky'\n\nexport interface StreamSmoothingPresetConfig {\n readonly activeInputWindowMs: number\n readonly defaultCps: number\n readonly emaAlpha: number\n readonly flushCps: number\n readonly largeAppendChars: number\n readonly maxActiveCps: number\n readonly maxCps: number\n readonly maxFlushCps: number\n readonly minCommitIntervalMs: number\n readonly minCps: number\n readonly settleAfterMs: number\n readonly settleDrainMaxMs: number\n readonly settleDrainMinMs: number\n readonly targetBufferMs: number\n}\n\nexport const PRESET_CONFIG: Record<StreamSmoothingPreset, StreamSmoothingPresetConfig> = {\n balanced: {\n activeInputWindowMs: 220,\n defaultCps: 80,\n emaAlpha: 0.35,\n flushCps: 180,\n largeAppendChars: 120,\n maxActiveCps: 360,\n maxCps: 240,\n maxFlushCps: 480,\n minCommitIntervalMs: 16,\n minCps: 24,\n settleAfterMs: 280,\n settleDrainMaxMs: 420,\n settleDrainMinMs: 120,\n targetBufferMs: 40,\n },\n realtime: {\n activeInputWindowMs: 140,\n defaultCps: 120,\n emaAlpha: 0.45,\n flushCps: 240,\n largeAppendChars: 180,\n maxActiveCps: 480,\n maxCps: 320,\n maxFlushCps: 640,\n minCommitIntervalMs: 16,\n minCps: 32,\n settleAfterMs: 200,\n settleDrainMaxMs: 280,\n settleDrainMinMs: 100,\n targetBufferMs: 24,\n },\n silky: {\n activeInputWindowMs: 280,\n defaultCps: 64,\n emaAlpha: 0.28,\n flushCps: 140,\n largeAppendChars: 100,\n maxActiveCps: 280,\n maxCps: 180,\n maxFlushCps: 400,\n minCommitIntervalMs: 16,\n minCps: 20,\n settleAfterMs: 360,\n settleDrainMaxMs: 520,\n settleDrainMinMs: 160,\n targetBufferMs: 56,\n },\n}\n\nconst MAX_COMMIT_INTERVAL_MS = 16\n/** Demo queue divisor: each frame reveals about `backlog / 8` characters. */\nexport const QUEUE_REVEAL_DIVISOR = 8\nconst QUEUE_FRAME_MS = 16.67\n/** Hard cap on how far display may trail a live stream, in characters. */\nexport const LIVE_LAG_CHAR_CEILING = 32\nconst CATCHUP_SECONDS = 0.15\n\nexport const clamp = (value: number, min: number, max: number): number => {\n return Math.min(max, Math.max(min, value))\n}\n\n/**\n * Demo per-frame reveal: drain `backlog / 8` characters, at least 1, scaled\n * by frame time. A small queue types one glyph per frame; a burst raises the\n * step so the display does not fall behind.\n * @param backlog - Unrevealed characters.\n * @param dtMs - Frame delta in ms.\n * @returns Characters to reveal this frame.\n */\nexport function computeQueueReveal(backlog: number, dtMs: number): number {\n if (backlog <= 0 || dtMs <= 0) return 0\n return Math.min(backlog, Math.max(1, Math.ceil((backlog / QUEUE_REVEAL_DIVISOR) * (dtMs / QUEUE_FRAME_MS))))\n}\n\n/** Counts user-perceived characters (code points), not UTF-16 units. */\nexport const countChars = (text: string): number => {\n let count = 0\n for (const char of text) {\n void char\n count += 1\n }\n return count\n}\n\n/**\n * Drain rate for backlog beyond the tail-lag ceiling: the displayed text may\n * trail the stream by at most `backlogCharCeiling` characters for at most\n * `backlogSecondCeiling` seconds. The constants are a smoothness invariant\n * (bounded lag is the reason the reveal never stalls mid-reply), so they are\n * not config fields; the preset multiplier is how a deployment tunes them.\n */\nexport const BACKLOG_CHAR_CEILING = 300\nexport const BACKLOG_SECOND_CEILING = 2\n\nexport interface SettleDrainInput {\n readonly backlog: number\n readonly inputActive: boolean\n readonly settling: boolean\n}\n\n/** Pure settle-drain decision shared by the frame loop and its tests. */\nexport function computeSettleDrain(config: StreamSmoothingPresetConfig, input: SettleDrainInput): number {\n if (input.inputActive || !input.settling) return 0\n // A settled stream must drain fast enough to finish the reply promptly:\n // lag beyond the ceiling drains within the second ceiling.\n const overflow = Math.max(0, input.backlog - BACKLOG_CHAR_CEILING)\n const overflowCps = (overflow * 1000) / BACKLOG_SECOND_CEILING\n const drainTargetMs = clamp(input.backlog * 8, config.settleDrainMinMs, config.settleDrainMaxMs)\n const settleCps = (input.backlog * 1000) / drainTargetMs\n return clamp(Math.max(settleCps, overflowCps), config.flushCps, config.maxFlushCps)\n}\n\n/**\n * Drain rate multiplier once the input ends: leftover backlog reveals at\n * this multiple of the steady rate, so the end never drags.\n */\nexport const SETTLE_DRAIN_MULTIPLIER = 1.8\n\nexport interface RevealStepInput {\n readonly backlog: number\n readonly chunkSizeEma: number\n readonly arrivalCpsEma: number\n readonly emaCps: number\n readonly inputActive: boolean\n readonly settling: boolean\n /** Fixed reveal rate; overrides the arrival-tracking cadence entirely. */\n readonly steadyCps?: number | undefined\n}\n\nexport interface RevealStepResult {\n readonly revealChars: number\n readonly targetLagChars: number\n}\n\n/** Pure per-frame reveal decision shared by the loop and its tests. */\nexport function computeRevealStep(config: StreamSmoothingPresetConfig, input: RevealStepInput, dtSeconds: number): RevealStepResult {\n // Track the faster of the two EMAs and do not clamp to the old low maxCps\n // ceiling — that cap is why a fast model left hundreds of chars unrevealed.\n const trackedCps = Math.max(input.emaCps, input.arrivalCpsEma)\n const baseCps = clamp(trackedCps, config.minCps, config.maxFlushCps)\n const targetLagChars = input.inputActive\n ? Math.max(2, Math.round((baseCps * config.targetBufferMs) / 1000))\n : 0\n\n let currentCps: number\n if (input.steadyCps !== undefined) {\n currentCps = input.inputActive || input.settling\n ? clamp(\n input.steadyCps * (input.inputActive ? 1 : SETTLE_DRAIN_MULTIPLIER),\n config.minCps,\n config.maxFlushCps,\n )\n : 0\n } else if (input.inputActive) {\n const overflow = Math.max(0, input.backlog - LIVE_LAG_CHAR_CEILING)\n const catchup = overflow > 0 ? overflow / CATCHUP_SECONDS : 0\n currentCps = clamp(baseCps * 1.08 + catchup, config.minCps, config.maxFlushCps)\n } else if (input.settling) {\n currentCps = computeSettleDrain(config, input)\n } else {\n const idleFlushCps = Math.max(config.flushCps, baseCps * 1.8, input.arrivalCpsEma * 0.8)\n currentCps = clamp(idleFlushCps, config.flushCps, config.maxFlushCps)\n }\n\n const minRevealChars = input.inputActive ? 1 : 2\n return { revealChars: Math.max(minRevealChars, Math.round(currentCps * dtSeconds)), targetLagChars }\n}\n\nexport interface UseSmoothStreamContentOptions {\n enabled?: boolean\n preset?: StreamSmoothingPreset\n /** Performance guard veto: while true, reveal commits are held back. */\n shouldHoldBack?: (() => boolean) | undefined\n /**\n * Fixed reveal rate in chars/s. When set, the reveal runs at this steady\n * pace while the input streams (instead of tracking the arrival rate) and\n * drains the leftover backlog at {@link SETTLE_DRAIN_MULTIPLIER} once the\n * input ends.\n */\n steadyCps?: number | undefined\n /**\n * Seed for the arrival-rate EMA. When omitted, the preset's `defaultCps`\n * is used. The live rate then tracks observed arrival; this is not a cap.\n */\n defaultCps?: number | undefined\n /** Written each commit with the live arrival-rate EMA for the follow lerp. */\n speedCpsRef?: { current: number } | undefined\n}\n\n/**\n * Smooth a chunked content stream into a reveal-paced display string.\n *\n * @param content - The full accumulated input so far.\n * @param options - Preset, guard, and steady-rate wiring.\n * @returns The displayed content, revealed at the smoothed cadence.\n */\nexport function useSmoothStreamContent(\n content: string,\n { enabled = true, preset = 'balanced', shouldHoldBack, steadyCps, defaultCps, speedCpsRef }: UseSmoothStreamContentOptions = {},\n): string {\n const config = PRESET_CONFIG[preset]\n const seedCps = defaultCps ?? config.defaultCps\n const [displayedContent, setDisplayedContent] = useState(content)\n\n const displayedContentRef = useRef(content)\n const displayedCountRef = useRef(countChars(content))\n const targetContentRef = useRef(content)\n const targetCharsRef = useRef([...content])\n const targetCountRef = useRef(countChars(content))\n\n const emaCpsRef = useRef(seedCps)\n const lastInputTsRef = useRef(0)\n const lastInputCountRef = useRef(countChars(content))\n const chunkSizeEmaRef = useRef(1)\n const arrivalCpsEmaRef = useRef(seedCps)\n\n const rafRef = useRef<number | null>(null)\n const lastFrameTsRef = useRef<number | null>(null)\n const wakeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const holdBackRef = useRef(shouldHoldBack)\n const speedOutRef = useRef(speedCpsRef)\n speedOutRef.current = speedCpsRef\n\n useEffect(() => {\n holdBackRef.current = shouldHoldBack\n }, [shouldHoldBack])\n\n const clearWakeTimer = useCallback(() => {\n if (wakeTimerRef.current !== null) {\n clearTimeout(wakeTimerRef.current)\n wakeTimerRef.current = null\n }\n }, [])\n\n const stopFrameLoop = useCallback(() => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n lastFrameTsRef.current = null\n }, [])\n\n const stopScheduling = useCallback(() => {\n stopFrameLoop()\n clearWakeTimer()\n }, [clearWakeTimer, stopFrameLoop])\n\n const startFrameLoopRef = useRef<() => void>(() => {})\n\n const scheduleFrameWake = useCallback(\n (delayMs: number) => {\n clearWakeTimer()\n wakeTimerRef.current = setTimeout(\n () => {\n wakeTimerRef.current = null\n startFrameLoopRef.current()\n },\n Math.max(1, Math.ceil(delayMs)),\n )\n },\n [clearWakeTimer],\n )\n\n const syncImmediate = useCallback(\n (nextContent: string) => {\n stopScheduling()\n const chars = [...nextContent]\n const now = performance.now()\n targetContentRef.current = nextContent\n targetCharsRef.current = chars\n targetCountRef.current = chars.length\n displayedContentRef.current = nextContent\n displayedCountRef.current = chars.length\n setDisplayedContent(nextContent)\n emaCpsRef.current = seedCps\n chunkSizeEmaRef.current = 1\n arrivalCpsEmaRef.current = seedCps\n lastInputTsRef.current = now\n lastInputCountRef.current = chars.length\n },\n [seedCps, stopScheduling],\n )\n\n const startFrameLoop = useCallback(() => {\n clearWakeTimer()\n if (rafRef.current !== null) return\n\n const tick = () => {\n const targetCount = targetCountRef.current\n const displayedCount = displayedCountRef.current\n const backlog = targetCount - displayedCount\n\n if (backlog <= 0) {\n stopFrameLoop()\n return\n }\n\n const now = performance.now()\n if (lastFrameTsRef.current === null) {\n lastFrameTsRef.current = now\n rafRef.current = requestAnimationFrame(tick)\n return\n }\n\n const commitIntervalMs = Math.min(MAX_COMMIT_INTERVAL_MS, config.minCommitIntervalMs)\n const frameIntervalMs = Math.max(0, now - lastFrameTsRef.current)\n if (frameIntervalMs < commitIntervalMs) {\n rafRef.current = requestAnimationFrame(tick)\n return\n }\n\n const dtSeconds = Math.max(0.001, Math.min(frameIntervalMs / 1000, 0.12))\n lastFrameTsRef.current = now\n\n const idleMs = now - lastInputTsRef.current\n const inputActive = idleMs <= config.activeInputWindowMs\n const settling = !inputActive && idleMs >= config.settleAfterMs\n\n let revealChars: number\n if (steadyCps !== undefined) {\n const step = computeRevealStep(\n config,\n {\n backlog,\n chunkSizeEma: chunkSizeEmaRef.current,\n arrivalCpsEma: arrivalCpsEmaRef.current,\n emaCps: emaCpsRef.current,\n inputActive,\n settling,\n steadyCps,\n },\n dtSeconds,\n )\n revealChars = Math.min(step.revealChars, backlog)\n } else {\n // Same rAF queue drain as the silky markdown demo.\n revealChars = computeQueueReveal(backlog, frameIntervalMs)\n }\n\n // Performance guard: while degraded and the reply is offscreen, skip\n // the DOM commit — the backlog keeps accumulating and flushes when the\n // guard clears or the reply scrolls into view.\n if (holdBackRef.current?.() === true) {\n rafRef.current = requestAnimationFrame(tick)\n return\n }\n\n const speedOut = speedOutRef.current\n if (speedOut !== undefined && frameIntervalMs > 0) {\n const instantCps = (revealChars * 1000) / frameIntervalMs\n speedOut.current = speedOut.current * 0.92 + instantCps * 0.08\n }\n\n const nextCount = displayedCount + revealChars\n const segment = targetCharsRef.current.slice(displayedCount, nextCount).join('')\n if (segment) {\n const nextDisplayed = displayedContentRef.current + segment\n displayedContentRef.current = nextDisplayed\n displayedCountRef.current = nextCount\n setDisplayedContent(nextDisplayed)\n } else {\n displayedContentRef.current = targetContentRef.current\n displayedCountRef.current = targetCount\n setDisplayedContent(targetContentRef.current)\n }\n\n rafRef.current = requestAnimationFrame(tick)\n }\n\n rafRef.current = requestAnimationFrame(tick)\n }, [config, scheduleFrameWake, stopFrameLoop, clearWakeTimer, steadyCps])\n\n useEffect(() => {\n startFrameLoopRef.current = startFrameLoop\n }, [startFrameLoop])\n\n useEffect(() => {\n if (!enabled) {\n syncImmediate(content)\n return\n }\n\n const prevTargetContent = targetContentRef.current\n if (content === prevTargetContent) return\n\n const now = performance.now()\n const appendOnly = content.startsWith(prevTargetContent)\n\n if (!appendOnly) {\n syncImmediate(content)\n return\n }\n\n const appended = content.slice(prevTargetContent.length)\n const appendedChars = [...appended]\n const appendedCount = appendedChars.length\n\n targetContentRef.current = content\n targetCharsRef.current.push(...appendedChars)\n targetCountRef.current += appendedCount\n\n const hadSample = lastInputTsRef.current > 0\n const deltaChars = targetCountRef.current - lastInputCountRef.current\n const deltaMs = Math.max(1, now - lastInputTsRef.current)\n\n // Skip the first sample: lastInputTs starts at 0, so the interval would\n // be \"time since page load\" (or 1ms under fake timers) and poison the EMA.\n if (hadSample && deltaChars > 0) {\n const instantCps = (deltaChars * 1000) / deltaMs\n const normalizedInstantCps = clamp(instantCps, config.minCps, config.maxFlushCps * 3)\n const chunkEmaAlpha = 0.45\n chunkSizeEmaRef.current = chunkSizeEmaRef.current * (1 - chunkEmaAlpha) + appendedCount * chunkEmaAlpha\n arrivalCpsEmaRef.current = arrivalCpsEmaRef.current * (1 - chunkEmaAlpha) + normalizedInstantCps * chunkEmaAlpha\n emaCpsRef.current = emaCpsRef.current * (1 - config.emaAlpha) + normalizedInstantCps * config.emaAlpha\n }\n\n lastInputTsRef.current = now\n lastInputCountRef.current = targetCountRef.current\n\n startFrameLoop()\n }, [content, enabled, config, startFrameLoop, syncImmediate])\n\n useEffect(() => {\n return () => {\n stopScheduling()\n }\n }, [stopScheduling])\n\n return displayedContent\n}\n","/**\n * Performance guard for the streaming reveal.\n *\n * Feeds an EMA-smoothed frame-rate monitor from a rAF loop while streaming\n * and tracks whether the reply is on-screen. The returned `shouldHoldBack`\n * predicate is true only while the frame rate is below the threshold AND the\n * reply is offscreen — exactly the spec's \"skip offscreen DOM updates when\n * FPS < 30\" rule. The smoother consumes the predicate as its commit veto.\n */\n\nimport { useCallback, useEffect, useRef } from 'react'\n\nconst FPS_THRESHOLD = 30\nconst FPS_ALPHA = 0.12\nconst RECOVER_FRAMES = 6\nconst MAX_FRAME_MS = 100\n\ninterface MutableFps {\n emaMs: number\n lastMs: number\n healthyRun: number\n degraded: boolean\n}\n\nexport function useFpsGuard(active: boolean): {\n ref: (element: HTMLElement | null) => void\n shouldHoldBack: () => boolean\n} {\n const fpsRef = useRef<MutableFps>({ emaMs: 0, lastMs: 0, healthyRun: 0, degraded: false })\n const visibleRef = useRef(true)\n const elementRef = useRef<HTMLElement | null>(null)\n\n useEffect(() => {\n if (!active) return\n let rafId = 0\n const frame = (now: number) => {\n rafId = requestAnimationFrame(frame)\n const fps = fpsRef.current\n if (fps.lastMs === 0) {\n fps.lastMs = now\n return\n }\n const delta = Math.min(MAX_FRAME_MS, Math.max(1, now - fps.lastMs))\n fps.lastMs = now\n fps.emaMs = fps.emaMs === 0 ? delta : fps.emaMs + FPS_ALPHA * (delta - fps.emaMs)\n const currentFps = 1000 / fps.emaMs\n if (currentFps < FPS_THRESHOLD) {\n fps.healthyRun = 0\n fps.degraded = true\n } else if (fps.degraded) {\n fps.healthyRun += 1\n if (fps.healthyRun >= RECOVER_FRAMES) fps.degraded = false\n }\n }\n rafId = requestAnimationFrame(frame)\n return () => {\n cancelAnimationFrame(rafId)\n fpsRef.current = { emaMs: 0, lastMs: 0, healthyRun: 0, degraded: false }\n }\n }, [active])\n\n const ref = useCallback((element: HTMLElement | null) => {\n elementRef.current = element\n }, [])\n\n useEffect(() => {\n const element = elementRef.current\n if (element === null || typeof IntersectionObserver === 'undefined') return\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) visibleRef.current = entry.isIntersecting\n },\n { rootMargin: '120px 0px' },\n )\n observer.observe(element)\n return () => observer.disconnect()\n })\n\n const shouldHoldBack = useCallback(() => {\n return active && fpsRef.current.degraded && !visibleRef.current\n }, [active])\n\n return { ref, shouldHoldBack }\n}\n","/**\n * Conversation-port follow while an assistant reply streams.\n *\n * The demo's damped-spring lerp is driven from a float `animatedH` — the\n * smoothed content height — never from the rounded `scrollTop` the browser\n * reports back. A wrap raises the content height by a line; if the engine\n * were allowed to snap `scrollTop` to the new floor, the previous line would\n * hop up in one frame. This overlay:\n *\n * - owns follow via `data-follow-owned` so ChatView does not snap;\n * - sets `overflow-anchor: none` so CSS scroll-anchoring does not snap;\n * - restores `animatedH` in a ResizeObserver (before paint) so a layout\n * pass cannot flash a snapped frame;\n * - while the port has scroll room, writes the interpolated lag as\n * `translate3d` on `[data-chat-transcript]` (message rows only), so the\n * turn-status chrome stays pinned at the floor;\n * - clips only the part of the translated surface that crosses the\n * turn-status line, preserving the normal gap above that line;\n * - leaves `[data-chat-turn-status]` in normal flow at every height, so its\n * layout gap cannot be consumed by an interpolated transform.\n *\n * A real reader unpin first writes the effective visual top (`engine - lag`)\n * into `scrollTop` before clearing the transform, so the frame stays\n * continuous. Lifecycle completion is different: without a reader gesture,\n * the last owner settles at the floor and preserves bottom-follow.\n *\n * Unpin is a real gesture (wheel / touch / pointer / key) that leaves the\n * floor; a `scrollTop` delta from our own write must not release the pin.\n */\n\nimport { useEffect, useRef, type RefObject } from 'react'\n\n/**\n * Matches ChatView's `FOLLOW_OWNED_ATTR`. The overlay writes the last\n * programmatic `scrollTop` here so ChatView yields snap-follow and does not\n * treat the write as reader input.\n */\nconst FOLLOW_OWNED_ATTR = 'data-follow-owned'\n\n/** Demo `1 - exp(-dt / 18)` time constant, in ms. */\nexport const FOLLOW_LERP_DT_MS = 18\n\n/** Floor / ceiling of the per-frame lerp fraction before the dt term. */\nexport const FOLLOW_LERP_MIN = 0.05\nexport const FOLLOW_LERP_MAX = 0.25\n\n/** Lag (px) at which the lag term of the lerp saturates. */\nexport const FOLLOW_LERP_LAG_REF_PX = 160\n\n/** Reveal cps at which the speed factor is 1. */\nexport const FOLLOW_SPEED_REF_CPS = 35\n\nexport const FOLLOW_SPEED_FACTOR_MIN = 0.7\nexport const FOLLOW_SPEED_FACTOR_MAX = 2.2\n\n/** Reader-return / still-pinned boundary, matching ChatView + the demo. */\nexport const FOLLOW_SLACK_PX = 25\n\n/**\n * Upward wheel/touch distance that releases the pin. The engine `scrollTop`\n * is held on the floor while following, so a small trackpad tick never\n * appears as `reportedLag` and cannot be judged against {@link FOLLOW_SLACK_PX}.\n */\nexport const FOLLOW_UNPIN_GESTURE_PX = 8\n\n/** How long a gesture keeps `isUserInteracting` so the next scroll can unpin. */\nexport const FOLLOW_GESTURE_MS = 800\n\nconst GESTURE_EVENTS = ['wheel', 'touchmove', 'pointerdown', 'keydown'] as const\n\nexport interface FollowGlideInput {\n /** How far the interpolated top trails the floor, in px. */\n readonly lag: number\n /** Observed reveal rate in chars/s; 0 uses {@link FOLLOW_SPEED_REF_CPS}. */\n readonly speedEma: number\n}\n\nexport interface FollowGlideStep {\n /** Pixels to advance `animatedH` this frame (fractional). */\n readonly advancePx: number\n /** Applied lerp fraction, for tests. */\n readonly lerpStep: number\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value))\n}\n\n/**\n * One spring-lerp frame from the silky markdown demo.\n * @param dtMs - Frame delta in ms.\n * @param input - Current lag (from the float top, not the rounded engine top) and reveal-speed EMA.\n * @returns The fractional advance and the lerp fraction.\n */\nexport function computeFollowStep(dtMs: number, input: FollowGlideInput): FollowGlideStep {\n if (input.lag <= 0.1 || dtMs <= 0) return { advancePx: 0, lerpStep: 0 }\n const speed = input.speedEma > 0 ? input.speedEma : FOLLOW_SPEED_REF_CPS\n const speedFactor = clamp(speed / FOLLOW_SPEED_REF_CPS, FOLLOW_SPEED_FACTOR_MIN, FOLLOW_SPEED_FACTOR_MAX)\n const baseLerp = clamp((input.lag / FOLLOW_LERP_LAG_REF_PX) * speedFactor, FOLLOW_LERP_MIN, FOLLOW_LERP_MAX)\n const lerpStep = baseLerp * (1 - Math.exp(-dtMs / FOLLOW_LERP_DT_MS))\n return { advancePx: input.lag * lerpStep, lerpStep }\n}\n\n/** The message-rows box the lag transform rides on, when the host has one. */\nfunction shiftRootOf(port: HTMLElement): HTMLElement | null {\n return port.querySelector('[data-chat-transcript]')\n}\n\n/**\n * Row wrappers that carry only messages/tools. Hosts without a transcript\n * box keep the turn-status chrome as a sibling of the rows inside\n * `[data-chat-flow]`, so shifting that whole flow would drag the chrome\n * along; shifting the rows individually leaves every non-message sibling\n * (turn status, steering bubbles) pinned while the text glides.\n *\n * Only the outermost rows are shifted: a tool call nests its subcalls as\n * descendant `[data-chat-anchor-key]` rows, and writing the lag on each of\n * them would double (or further multiply) the shift, tearing the subcalls\n * away from their parent every frame. Descendants ride the parent's\n * transform instead.\n */\nfunction shiftRowsOf(port: HTMLElement): HTMLElement[] {\n return [...port.querySelectorAll<HTMLElement>('[data-chat-anchor-key]')]\n .filter(row => row.parentElement?.closest('[data-chat-anchor-key]') === null)\n}\n\n/** Element whose resize signals flow growth for the before-paint restore. */\nfunction resizeProxyOf(port: HTMLElement): HTMLElement | null {\n return port.querySelector('[data-chat-transcript]') ?? port.querySelector('[data-chat-flow]')\n}\n\n/** True when the glide expresses its lag as transforms instead of engine top. */\nfunction hasShiftSurface(port: HTMLElement): boolean {\n return shiftRootOf(port) !== null || shiftRowsOf(port).length > 0\n}\n\n/** Cached natural gap from a shifted surface's bottom to the status line. */\nconst statusGapCache = new WeakMap<HTMLElement, { chrome: HTMLElement; px: number }>()\n\nfunction currentShiftOf(element: HTMLElement): number {\n return Number(/translate3d\\(0, ([\\d.]+)px, 0\\)/.exec(element.style.transform)?.[1] ?? 0)\n}\n\nfunction statusGapBelow(surface: HTMLElement, chrome: HTMLElement): number {\n const cached = statusGapCache.get(surface)\n if (cached?.chrome === chrome) return cached.px\n // getBoundingClientRect includes our current transform. Remove it to recover\n // the layout bottom, then keep the existing gap available to the reveal.\n const naturalBottom = surface.getBoundingClientRect().bottom - currentShiftOf(surface)\n const px = Math.max(0, chrome.getBoundingClientRect().top - naturalBottom)\n statusGapCache.set(surface, { chrome, px })\n return px\n}\n\nfunction setShift(element: HTMLElement, px: number, paintAllowance?: number): void {\n if (Math.abs(px) > 0.01) {\n element.style.transform = `translate3d(0, ${px}px, 0)`\n element.style.willChange = 'transform'\n const bottomClip = paintAllowance === undefined ? 0 : Math.max(0, px - paintAllowance)\n element.style.clipPath = bottomClip > 0.01 ? `inset(0 0 ${bottomClip}px 0)` : ''\n } else {\n element.style.transform = ''\n element.style.willChange = ''\n element.style.clipPath = ''\n }\n}\n\n/**\n * The running-turn label. It stays in normal flow so the host column's gap\n * always separates it from the transcript.\n */\nfunction statusChromeOf(port: HTMLElement): HTMLElement | null {\n return port.querySelector<HTMLElement>(\n '[data-chat-turn-status], [data-chat-flow] > [role=\"status\"]',\n )\n}\n\n/**\n * Render the single smoothed extent `animatedH`. Once the port has scroll\n * room the engine is pinned at the floor and the lag rides\n * `[data-chat-transcript]` (or each message row when the host has no\n * transcript box). Before that, message rows and status chrome remain in\n * normal flow. Without any shift surface the engine carries the interpolated\n * top itself.\n */\nfunction applyVisual(port: HTMLElement, animatedH: number): void {\n const contentHeight = Math.max(0, port.scrollHeight)\n const floor = Math.max(0, contentHeight - port.clientHeight)\n const extent = Math.min(contentHeight, Math.max(0, animatedH))\n const lag = contentHeight - extent\n port.style.overflowAnchor = 'none'\n port.style.scrollBehavior = 'auto'\n const chrome = statusChromeOf(port)\n if (chrome !== null) setShift(chrome, 0)\n const shiftRoot = shiftRootOf(port)\n if (shiftRoot !== null) {\n if (floor <= 0) {\n port.scrollTop = 0\n port.setAttribute(FOLLOW_OWNED_ATTR, String(port.scrollTop))\n setShift(shiftRoot, 0)\n return\n }\n port.scrollTop = floor\n port.setAttribute(FOLLOW_OWNED_ATTR, String(port.scrollTop))\n setShift(shiftRoot, lag, chrome === null ? undefined : statusGapBelow(shiftRoot, chrome))\n return\n }\n const rows = shiftRowsOf(port)\n if (rows.length > 0) {\n if (floor <= 0) {\n port.scrollTop = 0\n port.setAttribute(FOLLOW_OWNED_ATTR, String(port.scrollTop))\n for (const row of rows) setShift(row, 0)\n return\n }\n port.scrollTop = floor\n port.setAttribute(FOLLOW_OWNED_ATTR, String(port.scrollTop))\n const last = rows.length - 1\n for (const [index, row] of rows.entries()) {\n const allowance = index === last && chrome !== null ? statusGapBelow(row, chrome) : undefined\n setShift(row, lag, allowance)\n }\n return\n }\n port.scrollTop = Math.min(floor, Math.max(0, extent))\n port.setAttribute(FOLLOW_OWNED_ATTR, String(port.scrollTop))\n}\n\nfunction clearVisual(port: HTMLElement): void {\n port.removeAttribute(FOLLOW_OWNED_ATTR)\n port.style.overflowAnchor = ''\n port.style.scrollBehavior = ''\n const shiftRoot = shiftRootOf(port)\n if (shiftRoot !== null) {\n statusGapCache.delete(shiftRoot)\n shiftRoot.style.transform = ''\n shiftRoot.style.willChange = ''\n shiftRoot.style.clipPath = ''\n } else {\n for (const row of shiftRowsOf(port)) {\n statusGapCache.delete(row)\n row.style.transform = ''\n row.style.willChange = ''\n row.style.clipPath = ''\n }\n }\n const chrome = statusChromeOf(port)\n if (chrome !== null) {\n chrome.style.transform = ''\n chrome.style.willChange = ''\n chrome.style.clipPath = ''\n }\n}\n\nfunction settleAtFloor(port: HTMLElement): void {\n const floor = Math.max(0, port.scrollHeight - port.clientHeight)\n port.scrollTop = floor\n port.setAttribute(FOLLOW_OWNED_ATTR, String(port.scrollTop))\n}\n\n/** Live follow hosts per conversation port so one unmount does not clear another. */\nconst followOwners = new WeakMap<HTMLElement, number>()\n\nfunction acquireFollow(port: HTMLElement): void {\n followOwners.set(port, (followOwners.get(port) ?? 0) + 1)\n}\n\nfunction releaseFollow(port: HTMLElement): number {\n const next = (followOwners.get(port) ?? 1) - 1\n if (next <= 0) {\n followOwners.delete(port)\n return 0\n }\n followOwners.set(port, next)\n return next\n}\n\n/**\n * Own the conversation scrollport's bottom-follow while `active` is true.\n *\n * @param rootRef - An element inside the conversation scrollport.\n * @param active - True while the reply is still revealing.\n * @param speedCpsRef - Live reveal-rate EMA from the smoother.\n */\nexport function useConversationFollow(\n rootRef: RefObject<HTMLElement | null>,\n active: boolean,\n speedCpsRef: { current: number },\n): void {\n const activeRef = useRef(active)\n useEffect(() => {\n activeRef.current = active\n }, [active])\n\n useEffect(() => {\n if (!active) return\n let rafId = 0\n let last = performance.now()\n let following = true\n let primed = false\n let animatedH = 0\n let interacting = false\n let interactTimer: ReturnType<typeof setTimeout> | null = null\n let port: HTMLElement | null = null\n let resize: ResizeObserver | null = null\n let holding: HTMLElement | null = null\n let awayPx = 0\n\n const hold = (next: HTMLElement): void => {\n if (holding === next) return\n if (holding !== null) releaseFollow(holding)\n acquireFollow(next)\n holding = next\n }\n\n const drop = (next: HTMLElement): void => {\n if (holding === next) {\n releaseFollow(next)\n holding = null\n }\n clearVisual(next)\n }\n\n /**\n * Give the reader the visual position the glide was showing before the\n * transforms go away. While transforms carry the lag, the engine sits at\n * the floor and the effective visual top is `engine - lag`; writing that\n * keeps the handover frame-continuous, and the write shows up in\n * ChatView's ledger as reader movement, disarming its snap-follow.\n * Without a shift surface the engine already holds the interpolated top,\n * so there is nothing to compensate.\n */\n const handBackVisual = (next: HTMLElement): void => {\n if (!hasShiftSurface(next)) return\n const floor = Math.max(0, next.scrollHeight - next.clientHeight)\n if (floor <= 0) return\n const lag = Math.max(0, next.scrollHeight - animatedH)\n next.scrollTop = Math.min(floor, Math.max(0, next.scrollTop - lag))\n }\n\n const markGesture = (event: Event): void => {\n interacting = true\n if (event instanceof WheelEvent && event.deltaY < 0) awayPx += -event.deltaY\n else if (event.type === 'touchmove' || event.type === 'keydown') awayPx += FOLLOW_UNPIN_GESTURE_PX\n if (interactTimer !== null) clearTimeout(interactTimer)\n interactTimer = setTimeout(() => {\n interacting = false\n interactTimer = null\n awayPx = 0\n }, FOLLOW_GESTURE_MS)\n }\n\n const restoreBeforePaint = (): void => {\n if (!following || port === null) return\n applyVisual(port, animatedH)\n }\n\n const bindPort = (next: HTMLElement): void => {\n if (port === next) return\n if (port !== null) {\n for (const name of GESTURE_EVENTS) port.removeEventListener(name, markGesture)\n resize?.disconnect()\n }\n port = next\n for (const name of GESTURE_EVENTS) {\n port.addEventListener(name, markGesture, { passive: true })\n }\n if (typeof ResizeObserver !== 'undefined') {\n resize = new ResizeObserver(restoreBeforePaint)\n resize.observe(port)\n const proxy = resizeProxyOf(port)\n if (proxy !== null) resize.observe(proxy)\n }\n }\n\n const frame = (now: number) => {\n rafId = requestAnimationFrame(frame)\n const dt = Math.min(50, now - last)\n last = now\n const root = rootRef.current\n if (root === null) return\n const nextPort = root.closest<HTMLElement>('[data-conversation-scroll]')\n if (nextPort === null) return\n bindPort(nextPort)\n\n const floor = Math.max(0, nextPort.scrollHeight - nextPort.clientHeight)\n const reportedLag = floor - nextPort.scrollTop\n // Visual extent (content-height equivalent of the reader's scroll top):\n // content shorter than the viewport has no scrollTop to derive from, so\n // the extent is just the content height.\n const extent = Math.min(nextPort.scrollHeight, Math.max(0, nextPort.scrollHeight - reportedLag))\n\n if (!primed) {\n animatedH = extent\n following = reportedLag <= FOLLOW_SLACK_PX\n if (following) {\n hold(nextPort)\n applyVisual(nextPort, animatedH)\n }\n primed = true\n return\n }\n\n if (!following && !interacting && reportedLag <= FOLLOW_SLACK_PX) {\n following = true\n animatedH = extent\n hold(nextPort)\n } else if (following && interacting && awayPx >= FOLLOW_UNPIN_GESTURE_PX) {\n following = false\n awayPx = 0\n // Compensate before the transform clears, or the flow (turn-status\n // chrome included) jumps up by the whole lag in one frame.\n handBackVisual(nextPort)\n animatedH = nextPort.scrollHeight\n drop(nextPort)\n }\n\n if (!activeRef.current || !following) return\n hold(nextPort)\n\n const lag = nextPort.scrollHeight - animatedH\n const step = computeFollowStep(dt, {\n lag,\n speedEma: speedCpsRef.current,\n })\n if (lag <= 0.1) {\n animatedH = nextPort.scrollHeight\n } else {\n animatedH = Math.min(nextPort.scrollHeight, animatedH + step.advancePx)\n }\n applyVisual(nextPort, animatedH)\n }\n\n rafId = requestAnimationFrame(frame)\n return () => {\n cancelAnimationFrame(rafId)\n if (interactTimer !== null) clearTimeout(interactTimer)\n resize?.disconnect()\n if (port !== null) {\n for (const name of GESTURE_EVENTS) port.removeEventListener(name, markGesture)\n }\n const root = rootRef.current\n const host = root?.closest<HTMLElement>('[data-conversation-scroll]') ?? port\n if (host === null) return\n const remaining = holding === host ? releaseFollow(host) : (followOwners.get(host) ?? 0)\n holding = null\n if (remaining === 0) {\n if (following) {\n if (interacting && awayPx >= FOLLOW_UNPIN_GESTURE_PX) handBackVisual(host)\n else settleAtFloor(host)\n }\n clearVisual(host)\n }\n }\n }, [active, rootRef, speedCpsRef])\n}\n","import { useRef, type ReactNode } from 'react'\nimport { useConversationFollow } from './teleprompterGlide.ts'\nimport css from './TypewriterAssistantNodeView.module.css'\n\n/**\n * Document-flow host that owns conversation-port follow while `active`.\n * Shared by assistant blocks and every other growing Chat row.\n */\nexport function FollowHost({\n active,\n speedCpsRef,\n children,\n}: {\n active: boolean\n speedCpsRef: { current: number }\n children: ReactNode\n}) {\n const rootRef = useRef<HTMLDivElement>(null)\n useConversationFollow(rootRef, active, speedCpsRef)\n return <div ref={rootRef} className={css.follow}>{children}</div>\n}\n","/**\n * Shared plugin configuration contract. The Host half defines the\n * Schemastery schema over this shape (defaults live here so both halves stay\n * symmetric); the client half falls back to the same defaults when the Host\n * boot-config bridge is absent (client-only composition).\n */\n\nimport type { StreamSmoothingPreset } from './client/useSmoothStreamContent.ts'\n\n/** Streaming render direction of the assistant node view. */\nexport type StreamMode = 'typewriter' | 'teleprompter'\n\n/** Plugin configuration validated by the Host schema and bridged to the browser half. */\nexport interface StreamConfig {\n /** Render direction: horizontal per-character reveal or uniform upward glide. */\n readonly mode: StreamMode\n /** Smoothing preset for the reveal cadence. */\n readonly preset: StreamSmoothingPreset\n /**\n * Unused at runtime; kept so existing overlays load. Live reveal tracks\n * observed arrival and ignores this seed.\n */\n readonly revealCharsPerSec: number\n /**\n * Unused at runtime; kept so existing overlays load. Follow is a\n * smooth-damp, not a cruise speed.\n */\n readonly scrollSpeedPxPerSec: number\n /**\n * Follow velocity ceiling in CSS pixels per second, so a huge first lag\n * does not teleport. Ordinary wraps stay well below this.\n */\n readonly maxScrollSpeedPxPerSec: number\n}\n\n/** Defaults shared by the Host schema and the client-side fallback. */\nexport const DEFAULT_STREAM_CONFIG: StreamConfig = {\n mode: 'typewriter',\n preset: 'balanced',\n revealCharsPerSec: 80,\n scrollSpeedPxPerSec: 48,\n maxScrollSpeedPxPerSec: 1000,\n}\n\n/**\n * Window global the Host writes into the served index HTML. The browser boot\n * graph carries no per-entry config, so this inline script is the only\n * Host-to-client configuration channel for a composed web plugin.\n */\nexport const STREAM_BOOT_GLOBAL = '__DSH_SMOOTH_STREAM_CONFIG__'\n","/**\n * User-owned settings for the smooth-stream plugin, exposed to the Host\n * settings service and edited from the Web Settings \"plugin configuration\"\n * page. This is the runtime-editable complement to {@link StreamConfig}: that\n * contract is composed at load and bridged once through the boot global, while\n * these preferences live in the durable user-settings document and take effect\n * live.\n */\n\n/** Settings namespace registered by the Host and served through the plugin RPC. */\nexport const STREAM_SETTINGS_NS = 'smooth-stream'\n\n/**\n * Preferences a user may set. Deliberately separate from {@link StreamConfig}\n * because the two change at different times: composition-time values go\n * through the boot global, a live UI edit goes through the protected plugin RPC.\n */\nexport interface StreamSettings {\n /**\n * Whether a reasoning (\"Think\") block auto-expands while it is the\n * streaming tail. Off keeps the block collapsed — the user can still open\n * it by hand — and stops the running state from re-owning the disclosure.\n */\n thinkAutoExpand: boolean\n}\n\n/** Defaults shared by the Host schema and the client-side fallback. */\nexport const DEFAULT_STREAM_SETTINGS: StreamSettings = {\n thinkAutoExpand: true,\n}\n","import { memo, useEffect, useMemo, useRef, useState, type ComponentProps, type ReactNode } from 'react'\nimport { IconThinkOutline14, JsonBlock, MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { ImageGallery, type ImageLoader, type MessageImageLabels } from '@deepseek-ai/dsh-client-ui-attachment'\nimport type { ChatNodeViewProps, TurnTailOwnerProps } from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport { AnimatedDisclosure } from './AnimatedDisclosure.tsx'\nimport { useSmoothStreamContent, type StreamSmoothingPreset } from './useSmoothStreamContent.ts'\nimport { useFpsGuard } from './useFpsGuard.ts'\nimport { FollowHost } from './FollowHost.tsx'\nimport { DEFAULT_STREAM_CONFIG, type StreamMode } from '../config.ts'\nimport { DEFAULT_STREAM_SETTINGS } from '../settings.ts'\nimport css from './TypewriterAssistantNodeView.module.css'\n\ntype AssistantProps = ChatNodeViewProps<'assistant-step'>\ntype MarkdownProps = Pick<ComponentProps<typeof MarkdownText>, 'codeLabels' | 'fileMentions' | 'text'>\n\nfunction usePrefersReducedMotion(): boolean {\n const [reduced, setReduced] = useState(\n () => typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches === true,\n )\n useEffect(() => {\n if (typeof window === 'undefined' || window.matchMedia === undefined) return\n const query = window.matchMedia('(prefers-reduced-motion: reduce)')\n const onChange = () => setReduced(query.matches)\n query.addEventListener('change', onChange)\n return () => query.removeEventListener('change', onChange)\n }, [])\n return reduced\n}\n\ninterface AnimatedMarkdownTextProps extends MarkdownProps {\n streaming: boolean\n announce: boolean\n /** True on the last text block: that block owns conversation follow. */\n ownFollow: boolean\n preset: StreamSmoothingPreset\n shouldHoldBack: () => boolean\n}\n\n/**\n * Smooth streaming text arm. While the reply runs, the accumulated source is\n * revealed through the smoother at a rate that tracks the model's arrival\n * and rendered by the Harness `MarkdownText`\n * streaming arm (incremental parse, frozen non-tail blocks), so there is no\n * raw-text tail and no text-to-markdown swap: the tree stays markdown\n * throughout. The last text block owns conversation-port follow so wraps\n * glide instead of snapping. Once the stream closes and the reveal queue\n * drains, the settled full parse (KaTeX math, fence highlighting, file\n * mentions) swaps in exactly once.\n */\nfunction AnimatedMarkdownText({\n text,\n codeLabels,\n fileMentions,\n streaming,\n announce,\n ownFollow,\n preset,\n shouldHoldBack,\n}: AnimatedMarkdownTextProps) {\n const reduced = usePrefersReducedMotion()\n const [typing, setTyping] = useState(streaming)\n const speedCpsRef = useRef(35)\n const displayed = useSmoothStreamContent(text, {\n enabled: typing && !reduced,\n preset,\n shouldHoldBack,\n speedCpsRef,\n })\n const shown = reduced ? text : displayed\n const live = typing && !reduced\n\n // The stream closed: keep revealing the remaining queue, then swap to the\n // settled parse exactly once. The markdown tree stays mounted until then.\n useEffect(() => {\n if (typing && !streaming && shown.length === text.length) setTyping(false)\n }, [shown, streaming, text, typing])\n\n if (live) {\n return (\n <>\n {announce && <span className={css.visuallyHidden} aria-live=\"polite\">{text}</span>}\n <FollowHost active={ownFollow} speedCpsRef={speedCpsRef}>\n <MarkdownText text={shown} streaming codeLabels={codeLabels} />\n </FollowHost>\n </>\n )\n }\n return <MarkdownText text={text} codeLabels={codeLabels} fileMentions={fileMentions} />\n}\n\nfunction imageLabels(t: AssistantProps['t']): MessageImageLabels {\n return {\n image: t('image.label'),\n open: t('image.openOriginal'),\n openNamed: label => t('image.openOriginalLabel', { label }),\n loading: t('image.loading'),\n loadFailed: t('image.loadFailed'),\n lightbox: {\n dialog: t('image.preview'),\n close: t('image.closePreview'),\n },\n }\n}\n\nfunction firstLine(text: string): string {\n const newline = text.indexOf('\\n')\n return newline === -1 ? text : text.slice(0, newline)\n}\n\nfunction latestLine(text: string): string {\n const visible = text.trimEnd()\n const newline = visible.lastIndexOf('\\n')\n return newline === -1 ? visible : visible.slice(newline + 1)\n}\n\n/**\n * Built-in Think disclosure with a smoothed `text` feed. Chevron and row\n * click stay on the disclosure chrome, which the plugin's AnimatedDisclosure\n * renders with a height-animated body (the harness primitive would mount and\n * unmount it, which cannot glide). The row opens only while this block is\n * the streaming tail and closes as soon as thinking ends — a later block,\n * or the assistant node settling — not when the rest of the reply is\n * still streaming.\n */\nfunction AnimatedReasoning({\n text,\n running,\n preset,\n thinkAutoExpand,\n shouldHoldBack,\n followSpeedCpsRef,\n t,\n}: {\n text: string\n running: boolean\n preset: StreamSmoothingPreset\n thinkAutoExpand: boolean\n shouldHoldBack: () => boolean\n followSpeedCpsRef?: { current: number } | undefined\n t: AssistantProps['t']\n}) {\n const reduced = usePrefersReducedMotion()\n const [expanded, setExpanded] = useState(running && thinkAutoExpand)\n const summaryRef = useRef<HTMLSpanElement>(null)\n const displayed = useSmoothStreamContent(text, {\n enabled: running && !reduced,\n preset,\n shouldHoldBack,\n speedCpsRef: followSpeedCpsRef,\n })\n const shown = running && !reduced ? displayed : text\n const summary = running ? latestLine(shown) : firstLine(text)\n\n useEffect(() => {\n // Only the running state owns disclosure while auto-expand is on; with it\n // off, a manual toggle is never wrestled back by the stream.\n if (thinkAutoExpand) setExpanded(running)\n }, [running, thinkAutoExpand])\n\n useEffect(() => {\n const element = summaryRef.current\n if (element === null) return\n element.scrollLeft = running ? element.scrollWidth - element.clientWidth : 0\n }, [running, summary])\n\n // Preserve FollowHost's layout wrapper without mounting a second scroll owner.\n return (\n <div className={css.follow}>\n <div className={css.think} data-variant=\"think\" data-state={running ? 'running' : 'ok'}>\n {running && <span className={css.visuallyHidden}>{t('row.running')}</span>}\n <AnimatedDisclosure\n rowClassName={css.thinkRow}\n leadingClassName={css.thinkLeading}\n titleClassName={css.thinkTitle}\n chevronClassName={css.thinkChevron}\n icon={<IconThinkOutline14 size={14} />}\n title=\"Think\"\n open={expanded}\n onToggle={() => { setExpanded(value => !value) }}\n collapsedContent={(\n <>\n <span className={css.thinkSeparator} aria-hidden />\n <span ref={summaryRef} className={css.thinkSummary} data-follow-end={running || undefined}>{summary}</span>\n </>\n )}\n >\n <div className={css.thinkBody}>{shown}</div>\n </AnimatedDisclosure>\n </div>\n </div>\n )\n}\n\n/**\n * Assistant node renderer for the typewriter overlay. Text observed while\n * streaming is revealed by the smoother through the Harness Markdown\n * renderer at a rate that tracks arrival. Reasoning blocks keep the\n * built-in Think disclosure and only receive a smoothed text feed; the\n * outer node owns conversation-port follow while streaming; the final text\n * block keeps ownership while its settled reveal queue drains. The FPS guard\n * holds offscreen reveals when the frame rate is degraded. Settled text\n * renders with the full Markdown pipeline.\n */\nexport const TypewriterAssistantNodeView = memo(function TypewriterAssistantNodeView({\n mode: _mode = DEFAULT_STREAM_CONFIG.mode,\n preset = DEFAULT_STREAM_CONFIG.preset,\n revealCharsPerSec: _revealCharsPerSec = DEFAULT_STREAM_CONFIG.revealCharsPerSec,\n scrollSpeedPxPerSec: _scrollSpeedPxPerSec = DEFAULT_STREAM_CONFIG.scrollSpeedPxPerSec,\n maxScrollSpeedPxPerSec: _maxScrollSpeedPxPerSec = DEFAULT_STREAM_CONFIG.maxScrollSpeedPxPerSec,\n thinkAutoExpand = DEFAULT_STREAM_SETTINGS.thinkAutoExpand,\n node,\n useTurnData,\n openFile,\n loadImage,\n fileMentions,\n t,\n}: AssistantProps & {\n mode?: StreamMode\n preset?: StreamSmoothingPreset\n revealCharsPerSec?: number\n scrollSpeedPxPerSec?: number\n maxScrollSpeedPxPerSec?: number\n thinkAutoExpand?: boolean\n}) {\n const data = node.data\n const streaming = data.status === 'running'\n const { ref: guardRef, shouldHoldBack } = useFpsGuard(streaming)\n const rootSpeedRef = useRef(35)\n const reasoningOwnsSpeed = streaming && data.blocks[data.blocks.length - 1]?.kind === 'reasoning'\n useEffect(() => {\n if (!reasoningOwnsSpeed) rootSpeedRef.current = 35\n }, [reasoningOwnsSpeed])\n const turn = node.location.kind === 'turn' || node.location.kind === 'step'\n ? node.location.turn\n : undefined\n const tail = useTurnData('turn-tail')\n const owner = useMemo<TurnTailOwnerProps | undefined>(() => {\n if (turn?.status !== 'closed' || data.finalNode === undefined) return undefined\n if (tail?.closing?.finalNode.seq !== data.finalNode.seq) return undefined\n return { turn, seq: data.finalNode.seq, openFile }\n }, [data.finalNode, openFile, tail, turn])\n const mentions = useMemo(\n () => owner === undefined ? undefined : fileMentions(owner),\n [fileMentions, owner],\n )\n const codeLabels = useMemo(() => ({ copyLabel: t('copy'), copiedLabel: t('copied') }), [t])\n const imageLoader: ImageLoader = loadImage ?? (async () => {\n throw new Error(t('image.serviceUnavailable'))\n })\n const hasVisible = streaming\n || data.status === 'interrupted'\n || data.blocks.some(block => block.kind !== 'tool-call')\n if (!hasVisible) return null\n\n const rendered: ReactNode[] = []\n const last = data.blocks.length - 1\n let lastFollow = -1\n for (let index = 0; index < data.blocks.length; index += 1) {\n const kind = data.blocks[index]?.kind\n if (kind === 'text' || kind === 'reasoning') lastFollow = index\n }\n for (let index = 0; index < data.blocks.length; index += 1) {\n const block = data.blocks[index]\n if (block === undefined) continue\n switch (block.kind) {\n case 'text':\n rendered.push(\n <AnimatedMarkdownText\n key={index}\n text={block.text}\n codeLabels={codeLabels}\n fileMentions={mentions}\n streaming={streaming}\n announce={index === last}\n ownFollow={!streaming && index === lastFollow}\n preset={preset}\n shouldHoldBack={shouldHoldBack}\n />,\n )\n break\n case 'reasoning':\n rendered.push(\n <AnimatedReasoning\n key={index}\n text={block.text}\n running={streaming && index === last}\n preset={preset}\n thinkAutoExpand={thinkAutoExpand}\n shouldHoldBack={shouldHoldBack}\n followSpeedCpsRef={reasoningOwnsSpeed && index === last ? rootSpeedRef : undefined}\n t={t}\n />,\n )\n break\n case 'image': {\n const start = index\n const group = [block]\n while (index + 1 < data.blocks.length) {\n const next = data.blocks[index + 1]\n if (next === undefined || next.kind !== 'image') break\n group.push(next)\n index += 1\n }\n rendered.push(\n <ImageGallery key={start} images={group} load={imageLoader} align=\"start\" labels={imageLabels(t)} />,\n )\n break\n }\n case 'tool-call':\n break\n case 'other':\n rendered.push(\n <JsonBlock\n key={index}\n label={t('message.unknownBlock')}\n payload={block.block}\n truncatedLabel={total => t('json.truncated', { total })}\n />,\n )\n break\n }\n }\n\n return (\n <div ref={guardRef} className={css.root} data-streaming={streaming || undefined}>\n <FollowHost active={streaming} speedCpsRef={rootSpeedRef}>\n <div className={css.body}>\n {rendered}\n {data.status === 'interrupted' && <span className={css.stopped}>{t('message.stopped')}</span>}\n </div>\n </FollowHost>\n </div>\n )\n})\n","import { createElement, useRef, type ComponentType } from 'react'\nimport { FollowHost } from './FollowHost.tsx'\n\n/** Props forwarded through a follow wrap; extra kit seats pass through. */\nexport type FollowWrapProps = {\n node?: unknown\n renderSlot?: unknown\n} & Record<string, unknown>\n\n/**\n * True while a Chat node is still growing: an assistant/workflow `status:\n * 'running'` payload, a Tool root that has not settled (`kind` absent), or a\n * model-retry whose current attempt is still `scheduled`.\n * @param node - The Chat node's view `node` prop.\n * @returns whether this row should own conversation follow.\n */\nexport function isGrowingChatNode(node: unknown): boolean {\n if (node === null || typeof node !== 'object' || !('data' in node)) return false\n const data = (node as { data: unknown }).data\n if (data === null || typeof data !== 'object') return false\n if ('status' in data && (data as { status: unknown }).status === 'running') return true\n if ('root' in data) {\n const root = (data as { root: unknown }).root\n if (root !== null && typeof root === 'object' && !('kind' in root)) return true\n }\n if ('current' in data) {\n const current = (data as { current: unknown }).current\n if (\n current !== null\n && typeof current === 'object'\n && 'retryState' in current\n && (current as { retryState: unknown }).retryState === 'scheduled'\n ) return true\n }\n return false\n}\n\n/**\n * Wrap a prior Chat node renderer so a growing row shares conversation\n * follow. Presentation stays with the wrapped component; kit seats\n * (`renderSlot`, locale, inject) pass through unchanged.\n * @param Inner - The already-registered row component.\n * @returns A follow-hosted row.\n */\nexport function wrapFollowNodeView(Inner: ComponentType<FollowWrapProps>) {\n return function TypewriterFollowNodeView(props: FollowWrapProps) {\n const speedCpsRef = useRef(35)\n return (\n <FollowHost active={isGrowingChatNode(props.node)} speedCpsRef={speedCpsRef}>\n {createElement(Inner, props)}\n </FollowHost>\n )\n }\n}\n","/**\n * The smooth-stream plugin configuration card, rendered inside the Web\n * Settings \"plugin configuration\" page. One toggle, staged until the user\n * saves — the same shape as the Host-shipped cards, hand-drawn because the\n * Host cards' chrome is not exported for reuse.\n */\n\nimport { useState } from 'react'\nimport type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client'\nimport { IconChevronDownOutline14, IconRefreshOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { SmoothStreamCardFace } from './smooth-stream-card-controller.ts'\nimport css from './SmoothStreamCard.module.css'\n\n/** Props the renderer binds for the smooth-stream card. */\nexport type SmoothStreamCardProps =\n PropsRuntime<'settings.plugin.item'>\n & PropsLocale<'settings.smoothStream'>\n & InjectFace<SmoothStreamCardFace>\n\n/** Render the smooth-stream card independently of the core settings namespace allowlist. */\nexport function SmoothStreamCard(props: SmoothStreamCardProps) {\n const { t } = props\n const [open, setOpen] = useState(false)\n const state = props.useSmoothStreamCard(snapshot => snapshot)\n const blocked = !state.dirty || state.saving || state.status !== 'ready'\n const versionLabel = state.version === undefined\n ? null\n : t(state.installation === 'development' ? 'developmentVersion' : 'version')\n .replace('{version}', state.version)\n\n return (\n <li className={open ? `${css.card} ${css.cardOpen}` : css.card}>\n <button\n type=\"button\"\n className={css.header}\n aria-expanded={open}\n onClick={() => { setOpen(!open) }}\n >\n <span className={css.headText}>\n <span className={css.name}>{t('title')}</span>\n <span className={css.description}>{t('description')}</span>\n </span>\n {versionLabel === null ? null : <span className={css.version}>{versionLabel}</span>}\n {state.dirty ? <span className={css.pending}>{t('unsaved')}</span> : null}\n <IconChevronDownOutline14 className={open ? `${css.chevron} ${css.chevronOpen}` : css.chevron} />\n </button>\n {open\n ? (\n <div className={css.body}>\n {state.status === 'loading' ? <p className={css.readOnly} role=\"status\">{t('loading')}</p> : null}\n {state.status === 'unavailable' ? (\n <div className={css.failure}>\n <p className={css.readOnly} role=\"status\">{t('unavailable')}</p>\n <button type=\"button\" className={css.discard} onClick={props.reload}>{t('retry')}</button>\n </div>\n ) : null}\n {state.status === 'ready' ? (\n <>\n {!state.writable ? <p className={css.readOnly} role=\"status\">{t('readOnly')}</p> : null}\n <label className={css.field}>\n <span className={css.fieldHead}>\n <span className={css.label}>{t('thinkAutoExpand')}</span>\n <input\n type=\"checkbox\"\n className={css.toggle}\n checked={state.thinkAutoExpand}\n disabled={!state.writable}\n onChange={(event) => { props.edit(event.target.checked) }}\n />\n </span>\n <span className={css.hint}>{t('thinkAutoExpandHint')}</span>\n </label>\n <div className={css.updateRow}>\n <span className={css.updateCopy}>\n <span className={css.label}>{t('updates')}</span>\n <span className={css.hint}>\n {state.restartRequired\n ? t('restartRequired')\n : state.installation === 'npm' ? t('updateHint')\n : state.installation === 'development' ? t('developmentBuild') : t('updateUnavailable')}\n </span>\n </span>\n <button\n type=\"button\"\n className={css.update}\n disabled={!state.canUpgrade || state.upgrading || state.restartRequired}\n title={state.canUpgrade ? undefined : t('updateUnavailable')}\n onClick={props.upgrade}\n >\n <span aria-hidden=\"true\"><IconRefreshOutline14 /></span>\n {t(state.upgrading ? 'updating' : 'update')}\n </button>\n </div>\n {state.upgradeFailed ? <p className={css.failed} role=\"status\">{t('updateFailed')}</p> : null}\n <div className={css.footer}>\n {state.failed ? <p className={css.failed} role=\"status\">{t('saveFailed')}</p> : null}\n <button\n type=\"button\"\n className={css.discard}\n disabled={!state.dirty || state.saving}\n onClick={props.discard}\n >\n {t('discard')}\n </button>\n <button\n type=\"button\"\n className={css.save}\n disabled={blocked}\n onClick={props.save}\n >\n {t(state.saving ? 'saving' : 'save')}\n </button>\n </div>\n </>\n ) : null}\n </div>\n )\n : null}\n </li>\n )\n}\n","/** Staged form state for the plugin-owned smooth-stream settings RPC. */\n\nimport { createSnapshotStore, type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'\nimport { DEFAULT_STREAM_SETTINGS } from '../settings.ts'\nimport type { StreamInstallationKind, StreamSettingsView } from '../settings-api.ts'\nimport type { SmoothStreamSettingsApi } from './smooth-stream-settings-api.ts'\n\n/** What the smooth-stream card renders. It remains visible while its Host RPC loads. */\nexport interface SmoothStreamCardState {\n status: 'loading' | 'ready' | 'unavailable'\n writable: boolean\n dirty: boolean\n saving: boolean\n failed: boolean\n thinkAutoExpand: boolean\n version: string | undefined\n installation: StreamInstallationKind\n canUpgrade: boolean\n upgrading: boolean\n upgradeFailed: boolean\n restartRequired: boolean\n}\n\n/** The registration-side face injected into the settings slot renderer. */\nexport interface SmoothStreamCardFace {\n hooks: {\n smoothStreamCard: SnapshotStore<SmoothStreamCardState>\n }\n edit: (value: boolean) => void\n save: () => void\n discard: () => void\n reload: () => void\n upgrade: () => void\n}\n\n/** Bridges the plugin's protected Host interface onto a staged settings form. */\nexport class SmoothStreamCardController {\n private readonly store = createSnapshotStore<SmoothStreamCardState>(this.projection())\n private loaded: StreamSettingsView | undefined\n private staged: boolean | undefined\n private saving = false\n private failed = false\n private upgrading = false\n private upgradeFailed = false\n private restartRequired = false\n private loadGeneration = 0\n private loadStatus: 'loading' | 'ready' | 'unavailable' = 'loading'\n\n constructor(private readonly api: SmoothStreamSettingsApi) {}\n\n /** Begin the background read after the card has been registered. */\n start(): void {\n void this.load()\n }\n\n /** Ignore a late response after the surrounding optional services unload. */\n stop(): void {\n this.loadGeneration += 1\n }\n\n /** Current card snapshot, also consumed by the streaming preference cell. */\n getSnapshot(): SmoothStreamCardState {\n return this.store.getSnapshot()\n }\n\n /** Subscribe to state changes. */\n subscribe(listener: () => void): () => void {\n return this.store.subscribe(listener)\n }\n\n /** Build the face consumed by the settings slot renderer. */\n inject(): SmoothStreamCardFace {\n return {\n hooks: { smoothStreamCard: this.store },\n edit: (value) => {\n this.staged = value\n this.failed = false\n this.publish()\n },\n save: () => { void this.save() },\n discard: () => {\n if (this.staged === undefined && !this.failed) return\n this.staged = undefined\n this.failed = false\n this.publish()\n },\n reload: () => { void this.load() },\n upgrade: () => { void this.upgrade() },\n }\n }\n\n private projection(): SmoothStreamCardState {\n return {\n status: this.loadStatus,\n writable: this.loaded?.writable ?? false,\n dirty: this.staged !== undefined,\n saving: this.saving,\n failed: this.failed,\n thinkAutoExpand: this.staged ?? this.loaded?.thinkAutoExpand ?? DEFAULT_STREAM_SETTINGS.thinkAutoExpand,\n version: this.loaded?.version,\n installation: this.loaded?.installation ?? 'unmanaged',\n canUpgrade: this.loaded?.canUpgrade ?? false,\n upgrading: this.upgrading,\n upgradeFailed: this.upgradeFailed,\n restartRequired: this.restartRequired,\n }\n }\n\n private async load(): Promise<void> {\n const generation = ++this.loadGeneration\n this.loadStatus = 'loading'\n this.loaded = undefined\n this.publish()\n try {\n const view = await this.api.read()\n if (generation !== this.loadGeneration) return\n this.loaded = view\n this.loadStatus = 'ready'\n } catch {\n if (generation !== this.loadGeneration) return\n this.loaded = undefined\n this.loadStatus = 'unavailable'\n }\n this.publish()\n }\n\n private async save(): Promise<void> {\n if (this.staged === undefined || this.saving || this.loaded?.writable !== true) return\n const value = this.staged\n this.saving = true\n this.failed = false\n this.publish()\n try {\n this.loaded = await this.api.write(value)\n this.staged = undefined\n } catch {\n this.failed = true\n }\n this.saving = false\n this.publish()\n }\n\n private async upgrade(): Promise<void> {\n if (this.loaded?.canUpgrade !== true || this.upgrading) return\n this.upgrading = true\n this.upgradeFailed = false\n this.restartRequired = false\n this.publish()\n try {\n const result = await this.api.upgrade()\n this.restartRequired = result.restartRequired\n } catch {\n this.upgradeFailed = true\n }\n this.upgrading = false\n this.publish()\n }\n\n private publish(): void {\n this.store.set(this.projection())\n }\n}\n","/** Shared wire vocabulary for the plugin-owned settings RPC channel. */\n\n/** Dedicated, loopback-only RPC channel registered by the Host half. */\nexport const STREAM_SETTINGS_RPC_CHANNEL = '/smooth-stream'\n\n/** Endpoints accepted by {@link STREAM_SETTINGS_RPC_CHANNEL}. */\nexport const STREAM_SETTINGS_RPC = {\n read: 'settings.read',\n write: 'settings.write',\n upgrade: 'plugin.upgrade',\n} as const\n\n/** How the active profile supplied this plugin. */\nexport type StreamInstallationKind = 'npm' | 'development' | 'unmanaged'\n\n/** Redacted, plugin-owned configuration state returned to the browser. */\nexport interface StreamSettingsView {\n /** Version of the package currently running in the Host process. */\n version: string\n /** Source class of this package in the active profile. */\n installation: StreamInstallationKind\n /** Whether the Host settings provider permits a write. */\n writable: boolean\n /** Current resolved preference. */\n thinkAutoExpand: boolean\n /** Whether a fixed npm update command is safe to offer. */\n canUpgrade: boolean\n}\n\n/** Successful package update acknowledgement; loading the new code needs a restart. */\nexport interface StreamUpgradeView {\n restartRequired: true\n}\n","/** Browser adapter for the Host-owned smooth-stream settings RPC. */\n\nimport type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client'\nimport {\n STREAM_SETTINGS_RPC,\n STREAM_SETTINGS_RPC_CHANNEL,\n type StreamSettingsView,\n type StreamUpgradeView,\n} from '../settings-api.ts'\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : undefined\n}\n\nfunction settingsView(value: unknown): StreamSettingsView {\n const data = record(value)\n if (data === undefined\n || typeof data.version !== 'string'\n || !['npm', 'development', 'unmanaged'].includes(data.installation as string)\n || typeof data.writable !== 'boolean'\n || typeof data.thinkAutoExpand !== 'boolean'\n || typeof data.canUpgrade !== 'boolean') {\n throw new Error('dsh-smooth-stream: malformed settings response')\n }\n return data as unknown as StreamSettingsView\n}\n\nfunction upgradeView(value: unknown): StreamUpgradeView {\n const data = record(value)\n if (data?.restartRequired !== true) throw new Error('dsh-smooth-stream: malformed update response')\n return { restartRequired: true }\n}\n\nfunction accepted(result: Awaited<ReturnType<ConnectionHandle['rpc']['call']>>): unknown {\n if (!result.ok) throw new Error(result.error.message)\n return result.value\n}\n\n/** Narrow client contract consumed by the staged settings-card controller. */\nexport interface SmoothStreamSettingsApi {\n read(): Promise<StreamSettingsView>\n write(thinkAutoExpand: boolean): Promise<StreamSettingsView>\n upgrade(): Promise<StreamUpgradeView>\n}\n\n/** Build the typed facade over the generic Connection RPC service. */\nexport function createSmoothStreamSettingsApi(connection: ConnectionHandle): SmoothStreamSettingsApi {\n return {\n async read(): Promise<StreamSettingsView> {\n return settingsView(accepted(await connection.rpc.call(STREAM_SETTINGS_RPC_CHANNEL, STREAM_SETTINGS_RPC.read, {})))\n },\n async write(thinkAutoExpand: boolean): Promise<StreamSettingsView> {\n return settingsView(accepted(await connection.rpc.call(\n STREAM_SETTINGS_RPC_CHANNEL,\n STREAM_SETTINGS_RPC.write,\n { thinkAutoExpand },\n )))\n },\n async upgrade(): Promise<StreamUpgradeView> {\n return upgradeView(accepted(await connection.rpc.call(STREAM_SETTINGS_RPC_CHANNEL, STREAM_SETTINGS_RPC.upgrade, {})))\n },\n }\n}\n","/** Locale bundles for the smooth-stream plugin configuration card. */\n\n/** Dictionary namespace owned by this plugin's settings card. */\nexport const NS = 'settings.smoothStream'\n\n/** Locale keys the card renders. */\nexport type SmoothStreamLocaleKey =\n | 'title' | 'description'\n | 'thinkAutoExpand' | 'thinkAutoExpandHint'\n | 'readOnly' | 'loading' | 'unavailable' | 'retry'\n | 'version' | 'developmentVersion'\n | 'updates' | 'updateHint' | 'developmentBuild' | 'updateUnavailable'\n | 'update' | 'updating' | 'restartRequired' | 'updateFailed'\n | 'save' | 'saving' | 'discard' | 'unsaved' | 'saveFailed'\n\n/** English copy. */\nexport const en: Record<SmoothStreamLocaleKey, string> = {\n title: 'Smooth stream',\n description: 'How replies are revealed while they stream.',\n thinkAutoExpand: 'Auto-expand thinking',\n thinkAutoExpandHint: 'Open the thinking block while it streams. Turn off to keep it collapsed.',\n readOnly: 'This deployment stores settings read-only.',\n loading: 'Loading plugin settings…',\n unavailable: 'Plugin settings are unavailable in this connection.',\n retry: 'Retry',\n version: 'Version {version}',\n developmentVersion: 'Development version {version}',\n updates: 'Updates',\n updateHint: 'Install the newest npm version, then restart Harness.',\n developmentBuild: 'Linked source; updates are managed in the checkout.',\n updateUnavailable: 'Updates are available only for an npm profile installation.',\n update: 'Update',\n updating: 'Updating…',\n restartRequired: 'Updated. Restart Harness to load the new version.',\n updateFailed: 'The package update failed; your current version is unchanged.',\n save: 'Save',\n saving: 'Saving…',\n discard: 'Discard',\n unsaved: 'Unsaved',\n saveFailed: 'The deployment did not accept these values; they were left for you to correct.',\n}\n\n/** Simplified Chinese copy. */\nexport const zh: Record<SmoothStreamLocaleKey, string> = {\n title: '丝滑流式',\n description: '回复在流式输出时如何逐字展现。',\n thinkAutoExpand: '自动展开思考',\n thinkAutoExpandHint: '思考块在流式时自动展开;关闭后保持折叠,可手动展开。',\n readOnly: '本部署的设置为只读。',\n loading: '正在加载插件设置…',\n unavailable: '当前连接无法访问插件设置。',\n retry: '重试',\n version: '版本 {version}',\n developmentVersion: '开发版本 {version}',\n updates: '更新',\n updateHint: '安装最新 npm 版本后重启 Harness。',\n developmentBuild: '当前为本地链接版本,请在源码目录管理更新。',\n updateUnavailable: '只有 profile 使用 npm 包时才能更新。',\n update: '更新',\n updating: '更新中…',\n restartRequired: '已更新;重启 Harness 后加载新版本。',\n updateFailed: '包更新失败,当前版本未改变。',\n save: '保存',\n saving: '保存中…',\n discard: '放弃修改',\n unsaved: '未保存',\n saveFailed: '本部署没有接受这些值,已保留供你修改。',\n}\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n 'settings.smoothStream': SmoothStreamLocaleKey\n }\n}\n","import { createElement, useSyncExternalStore, type ComponentType } from 'react'\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: the connection Context merge and the plugins section's SlotMap\n// entry ('settings.plugin.item').\nimport type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client'\nimport type { ChatNodeViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport { TypewriterAssistantNodeView } from './TypewriterAssistantNodeView.tsx'\nimport { wrapFollowNodeView, type FollowWrapProps } from './TypewriterToolNodeView.tsx'\nimport { SmoothStreamCard } from './SmoothStreamCard.tsx'\nimport { SmoothStreamCardController } from './smooth-stream-card-controller.ts'\nimport { createSmoothStreamSettingsApi } from './smooth-stream-settings-api.ts'\nimport { NS as SETTINGS_NS, en, zh } from './locales.ts'\nimport { DEFAULT_STREAM_CONFIG, STREAM_BOOT_GLOBAL, type StreamConfig } from '../config.ts'\nimport { DEFAULT_STREAM_SETTINGS } from '../settings.ts'\n\n/**\n * Cordis services required by the browser half. Only `slots` is load-bearing\n * for the stream itself; locale and Connection power the configuration card\n * and are wired through `ctx.inject` below so a deployment without them still\n * streams with defaults.\n */\nexport const inject = ['slots']\n\ntype AssistantProps = ChatNodeViewProps<'assistant-step'>\n\nconst STREAM_MODES: readonly string[] = ['typewriter', 'teleprompter']\nconst STREAM_PRESETS: readonly string[] = ['realtime', 'balanced', 'silky']\n\n/** Human-authored rows stay on the built-in renderer; `assistant-step` is replaced. */\nconst SKIP_WRAP = new Set(['assistant-step', 'user', 'steering', 'command-input'])\n\n/**\n * Read the Host-bridged boot config. The inline script is produced by this\n * plugin's Host half from a schema-validated value, so only the structural\n * guarantees that could break between the two halves are re-checked: the\n * global is absent when the client runs without its Host entry (defaults\n * apply), and any present-but-malformed value fails loudly instead of\n * rendering a half-configured view.\n * @returns The resolved configuration for the assistant node view.\n */\nfunction readBootConfig(): StreamConfig {\n const raw = (globalThis as Record<string, unknown>)[STREAM_BOOT_GLOBAL]\n if (raw === undefined) {\n console.info('[dsh-smooth-stream] no host config bridge; using defaults')\n return DEFAULT_STREAM_CONFIG\n }\n if (\n typeof raw !== 'object' || raw === null\n || !STREAM_MODES.includes((raw as StreamConfig).mode)\n || !STREAM_PRESETS.includes((raw as StreamConfig).preset)\n || typeof (raw as StreamConfig).revealCharsPerSec !== 'number'\n || typeof (raw as StreamConfig).scrollSpeedPxPerSec !== 'number'\n || typeof (raw as StreamConfig).maxScrollSpeedPxPerSec !== 'number'\n ) {\n throw new Error(`[dsh-smooth-stream] malformed ${STREAM_BOOT_GLOBAL} boot global: ${JSON.stringify(raw)}`)\n }\n return raw as StreamConfig\n}\n\n/**\n * Wrap every keyed Chat row except `assistant-step` in place. A second\n * register with the same `children` table throws because the child slot is\n * already declared, and only the winning entry receives `renderSlot`;\n * swapping `entry.component` keeps the original children, locale, and inject\n * seats. `assistant-step` is replaced below so text and Think use the\n * typewriter reveal.\n * @param ctx - Browser context carrying the slot registry.\n * @returns Restorer that puts the original components back.\n */\nfunction wrapGrowingChatRows(ctx: ClientContext): () => void {\n const restores: Array<() => void> = []\n const wrapped = new WeakSet<object>()\n\n const wrapAll = (): void => {\n for (const entry of ctx.slots.entries('conversation.chat.node')) {\n const key = entry.options.key\n if (key === undefined || SKIP_WRAP.has(key)) continue\n const current = entry.component\n if (typeof current !== 'function' || wrapped.has(current)) continue\n const inner = current as ComponentType<FollowWrapProps>\n const next = wrapFollowNodeView(inner)\n wrapped.add(next)\n entry.component = next\n restores.push(() => {\n if (entry.component === next) entry.component = inner\n })\n }\n }\n\n wrapAll()\n const off = ctx.on('slots/changed', (key: string) => {\n if (key === 'conversation.chat.node') wrapAll()\n })\n return () => {\n off()\n for (const restore of restores) restore()\n }\n}\n\n/**\n * A live preference cell read by `useSyncExternalStore`. It starts on the\n * shared default and, once the plugin-owned settings controller is attached,\n * tracks the resolved `thinkAutoExpand` value. A composition (or test) that\n * ships no settings surface keeps the cell on the default.\n */\nclass PreferenceCell {\n private readonly listeners = new Set<() => void>()\n private card: SmoothStreamCardController | undefined\n private value = DEFAULT_STREAM_SETTINGS.thinkAutoExpand\n\n /** Re-point the cell at the plugin-owned settings controller. */\n attach(card: SmoothStreamCardController): () => void {\n this.card = card\n this.refresh()\n const unsubscribe = card.subscribe(() => { this.refresh() })\n return () => {\n unsubscribe()\n if (this.card !== card) return\n this.card = undefined\n this.refresh()\n }\n }\n\n private read(): boolean {\n return this.card?.getSnapshot().thinkAutoExpand ?? DEFAULT_STREAM_SETTINGS.thinkAutoExpand\n }\n\n private refresh(): void {\n const next = this.read()\n if (next === this.value) return\n this.value = next\n for (const listener of this.listeners) listener()\n }\n\n readonly getSnapshot = (): boolean => this.value\n\n readonly subscribe = (listener: () => void): () => void => {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n}\n\n/**\n * Register the typewriter renderer after the conversation package declares the\n * keyed Chat node seat. A lower priority shadows the built-in assistant row;\n * every other growing row is wrapped in place so Tool cards, retries, and\n * workflow runs share conversation follow. The Host-bridged configuration\n * selects the render direction, smoothing preset, and glide speed; the\n * plugin-owned settings RPC supplies the live auto-expand preference when the\n * settings surface is composed.\n * @param ctx - Browser context carrying the shared slot registry.\n */\nexport function apply(ctx: ClientContext): void {\n const config = readBootConfig()\n const preference = new PreferenceCell()\n\n // The card talks to the plugin-owned loopback RPC, so the core settings\n // namespace allowlist cannot make it disappear. The stream still applies\n // with defaults when the optional Settings UI or Connection is absent.\n ctx.inject(['slots', 'locale', 'connection'], (settingsCtx) => {\n const card = new SmoothStreamCardController(\n // The shared Context augmentation also carries the Host-side Connection\n // shape. This browser entry runs after the client provider installs its\n // handle, so narrow through unknown to its client contract here.\n createSmoothStreamSettingsApi(settingsCtx.get('connection') as unknown as ConnectionHandle),\n )\n const detachPreference = preference.attach(card)\n card.start()\n settingsCtx.effect(() => settingsCtx.locale.register(SETTINGS_NS, { zh, en }), 'dsh-smooth-stream: settings dictionaries')\n settingsCtx.slots.inject('settings.plugin.item', () => settingsCtx.slots.register({\n name: 'settings.plugin.item',\n id: 'smooth-stream',\n order: 30,\n locale: SETTINGS_NS,\n inject: () => card.inject(),\n }, SmoothStreamCard))\n return () => {\n card.stop()\n detachPreference()\n }\n })\n\n const configured = function StreamConfiguredView(props: AssistantProps) {\n const thinkAutoExpand = useSyncExternalStore(\n preference.subscribe,\n preference.getSnapshot,\n preference.getSnapshot,\n )\n return createElement(TypewriterAssistantNodeView, {\n ...props,\n mode: config.mode,\n preset: config.preset,\n revealCharsPerSec: config.revealCharsPerSec,\n scrollSpeedPxPerSec: config.scrollSpeedPxPerSec,\n maxScrollSpeedPxPerSec: config.maxScrollSpeedPxPerSec,\n thinkAutoExpand,\n })\n }\n ctx.slots.inject('conversation.chat.node', () => {\n const unwrap = wrapGrowingChatRows(ctx)\n const unshadow = ctx.slots.register({\n name: 'conversation.chat.node',\n key: 'assistant-step',\n priority: -100,\n locale: 'conversation',\n registrant: 'dsh-smooth-stream',\n }, configured)\n return () => {\n unshadow()\n unwrap()\n }\n })\n}\n"],"mappings":"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"}
|