@agents24/chat-react 0.5.21 → 0.5.23

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "contractHash": "37437aff006eec5ea404f4259bf2e8cb0ba442ecc5aa72b4d39964530899d58a",
2
+ "contractHash": "0394b689ce7604b444b11c8792050fae0c1da4233d6b318d22832c3b89516a4a",
3
3
  "contractVersion": "0.3.0",
4
4
  "corpus": "conformance/v1/corpus.json",
5
5
  "generatedBy": "@agents24/sdk-contract",
@@ -15,11 +15,11 @@
15
15
  "reactDom": ">=19 <20"
16
16
  },
17
17
  "@agents24/client": {
18
- "contract": "37437aff006eec5ea404f4259bf2e8cb0ba442ecc5aa72b4d39964530899d58a",
18
+ "contract": "0394b689ce7604b444b11c8792050fae0c1da4233d6b318d22832c3b89516a4a",
19
19
  "runtime": "run-stream.v3"
20
20
  },
21
21
  "@agents24/node": {
22
- "contract": "37437aff006eec5ea404f4259bf2e8cb0ba442ecc5aa72b4d39964530899d58a",
22
+ "contract": "0394b689ce7604b444b11c8792050fae0c1da4233d6b318d22832c3b89516a4a",
23
23
  "node": "^22.0.0 || ^24.0.0"
24
24
  },
25
25
  "@agents24/react": {
@@ -27,11 +27,11 @@
27
27
  "react": ">=19 <20"
28
28
  },
29
29
  "@talmudpedia/runtime-sdk": {
30
- "contract": "37437aff006eec5ea404f4259bf2e8cb0ba442ecc5aa72b4d39964530899d58a",
30
+ "contract": "0394b689ce7604b444b11c8792050fae0c1da4233d6b318d22832c3b89516a4a",
31
31
  "protocolOwner": "@agents24/client"
32
32
  },
33
33
  "agents24": {
34
- "contract": "37437aff006eec5ea404f4259bf2e8cb0ba442ecc5aa72b4d39964530899d58a",
34
+ "contract": "0394b689ce7604b444b11c8792050fae0c1da4233d6b318d22832c3b89516a4a",
35
35
  "python": ">=3.10"
36
36
  }
37
37
  },
@@ -15,7 +15,7 @@ var defaultStreamingTextCache = {
15
15
  }
16
16
  };
17
17
  var getActiveStreamingTextPartId = (message, streamingMessageId) => {
18
- if (message.role !== "assistant" || streamingMessageId !== message.id) return null;
18
+ if (message.role !== "assistant" || message.responseCompletion || streamingMessageId !== message.id) return null;
19
19
  const trailingPart = message.parts[message.parts.length - 1];
20
20
  return trailingPart?.kind === "text" ? trailingPart.id : null;
21
21
  };
@@ -186,4 +186,4 @@ export {
186
186
  isActiveStreamingTextPart,
187
187
  useStreamingText
188
188
  };
189
- //# sourceMappingURL=chunk-SSUO4EPD.js.map
189
+ //# sourceMappingURL=chunk-5PWUQTLK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/streaming-text.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\n\nimport type { ChatMessage, ChatPart } from \"./types\";\n\nexport type StreamingTextMode = \"streaming\" | \"static\";\n\nexport type StreamingTextCache = {\n get: (id: string) => string | undefined;\n set: (id: string, text: string) => void;\n};\n\nexport type UseStreamingTextOptions = {\n id: string;\n isStreaming: boolean;\n text: string;\n cache?: StreamingTextCache | false;\n charsPerSecond?: number;\n catchupThreshold?: number;\n maxCatchupChars?: number;\n};\n\nexport type UseStreamingTextResult = {\n displayedText: string;\n isAnimating: boolean;\n mode: StreamingTextMode;\n parseIncompleteMarkdown: boolean;\n};\n\nconst DEFAULT_COMPLETED_TEXT_CACHE_SIZE = 200;\nconst STREAM_RUNWAY_MS = 80;\nconst STREAM_IDLE_RELEASE_MS = 120;\nconst defaultCompletedTextCache = new Map<string, string>();\n\nconst defaultStreamingTextCache: StreamingTextCache = {\n get: (id) => defaultCompletedTextCache.get(id),\n set: (id, text) => {\n defaultCompletedTextCache.set(id, text);\n if (defaultCompletedTextCache.size > DEFAULT_COMPLETED_TEXT_CACHE_SIZE) {\n const firstKey = defaultCompletedTextCache.keys().next().value;\n if (firstKey) defaultCompletedTextCache.delete(firstKey);\n }\n },\n};\n\nexport const getActiveStreamingTextPartId = (\n message: ChatMessage,\n streamingMessageId: string | null\n) => {\n if (message.role !== \"assistant\" || message.responseCompletion || streamingMessageId !== message.id) return null;\n const trailingPart = message.parts[message.parts.length - 1];\n return trailingPart?.kind === \"text\" ? trailingPart.id : null;\n};\n\nexport const isActiveStreamingTextPart = (\n message: ChatMessage,\n part: ChatPart,\n streamingMessageId: string | null\n) => part.kind === \"text\" && part.id === getActiveStreamingTextPartId(message, streamingMessageId);\n\nconst graphemeEndOffsets = (value: string): number[] => {\n if (!value) return [];\n\n if (typeof Intl !== \"undefined\" && \"Segmenter\" in Intl) {\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n return Array.from(segmenter.segment(value), ({ index, segment }) => index + segment.length);\n }\n\n const characters = Array.from(value);\n const offsets: number[] = [];\n let offset = 0;\n let regionalIndicators = 0;\n characters.forEach((character, index) => {\n const previous = characters[index - 1];\n const codePoint = character.codePointAt(0) ?? 0;\n const isRegionalIndicator = codePoint >= 0x1f1e6 && codePoint <= 0x1f1ff;\n const continuesCluster =\n index > 0 &&\n (/^\\p{Mark}$/u.test(character) ||\n (codePoint >= 0xfe00 && codePoint <= 0xfe0f) ||\n (codePoint >= 0x1f3fb && codePoint <= 0x1f3ff) ||\n character === \"\\u200d\" ||\n previous === \"\\u200d\" ||\n (isRegionalIndicator && regionalIndicators % 2 === 1));\n if (!continuesCluster) {\n if (offset > 0) offsets.push(offset);\n regionalIndicators = 0;\n }\n offset += character.length;\n regionalIndicators = isRegionalIndicator ? regionalIndicators + 1 : 0;\n });\n offsets.push(offset);\n return offsets;\n};\n\nexport function useStreamingText({\n id,\n isStreaming,\n text,\n cache = defaultStreamingTextCache,\n charsPerSecond = 72,\n catchupThreshold = 40,\n maxCatchupChars = 20,\n}: UseStreamingTextOptions): UseStreamingTextResult {\n const cacheAdapter = cache === false ? null : cache;\n const [displayedText, setDisplayedText] = useState(() => {\n const cachedText = cacheAdapter?.get(id);\n return cachedText && text.startsWith(cachedText) ? cachedText : text;\n });\n const targetRef = useRef(text);\n const displayedRef = useRef(displayedText);\n const rafRef = useRef<number | null>(null);\n const lastFrameAtRef = useRef<number | null>(null);\n const targetUpdatedAtRef = useRef<number | null>(null);\n const progressRemainderRef = useRef(0);\n const idRef = useRef(id);\n const streamingRef = useRef(isStreaming);\n const reduceMotionRef = useRef(false);\n\n useEffect(() => {\n if (isStreaming || !text) return;\n cacheAdapter?.set(id, text);\n }, [cacheAdapter, id, isStreaming, text]);\n\n useEffect(() => {\n targetRef.current = text;\n targetUpdatedAtRef.current =\n typeof performance === \"undefined\" ? null : performance.now();\n\n if (\n !isStreaming ||\n reduceMotionRef.current ||\n !text.startsWith(displayedRef.current)\n ) {\n displayedRef.current = text;\n setDisplayedText(text);\n progressRemainderRef.current = 0;\n }\n }, [isStreaming, text]);\n\n useEffect(() => {\n if (idRef.current === id) return;\n\n idRef.current = id;\n const cachedText = cacheAdapter?.get(id);\n const initial = cachedText && text.startsWith(cachedText) ? cachedText : text;\n displayedRef.current = initial;\n setDisplayedText(initial);\n lastFrameAtRef.current = null;\n targetUpdatedAtRef.current =\n typeof performance === \"undefined\" ? null : performance.now();\n progressRemainderRef.current = 0;\n }, [cacheAdapter, id, isStreaming, text]);\n\n useEffect(() => {\n streamingRef.current = isStreaming;\n\n if (typeof window === \"undefined\") {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n const reduceMotion =\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n reduceMotionRef.current = reduceMotion;\n\n if (reduceMotion || !isStreaming) {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n const cachedText = cacheAdapter?.get(id);\n if (cachedText === text) {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n if (!text.startsWith(displayedRef.current)) {\n displayedRef.current = text;\n setDisplayedText(text);\n }\n\n const tick = (timestamp: number) => {\n const previousTimestamp = lastFrameAtRef.current ?? timestamp;\n lastFrameAtRef.current = timestamp;\n\n const target = targetRef.current;\n const current = displayedRef.current;\n\n if (!streamingRef.current || reduceMotionRef.current) {\n displayedRef.current = target;\n setDisplayedText(target);\n rafRef.current = null;\n return;\n }\n\n if (!target.startsWith(current)) {\n displayedRef.current = target;\n setDisplayedText(target);\n progressRemainderRef.current = 0;\n rafRef.current = window.requestAnimationFrame(tick);\n return;\n }\n\n const pending = target.slice(current.length);\n const pendingOffsets = graphemeEndOffsets(pending);\n if (pendingOffsets.length === 0) {\n rafRef.current = window.requestAnimationFrame(tick);\n return;\n }\n\n const elapsedMs = Math.max(0, timestamp - previousTimestamp);\n const targetIdleMs =\n targetUpdatedAtRef.current === null\n ? STREAM_IDLE_RELEASE_MS\n : Math.max(0, timestamp - targetUpdatedAtRef.current);\n const runway =\n targetIdleMs >= STREAM_IDLE_RELEASE_MS\n ? 0\n : Math.min(\n pendingOffsets.length - 1,\n Math.max(1, Math.ceil((charsPerSecond * STREAM_RUNWAY_MS) / 1000))\n );\n const eligibleGraphemes = pendingOffsets.length - runway;\n\n progressRemainderRef.current += (elapsedMs / 1000) * charsPerSecond;\n let step = Math.floor(progressRemainderRef.current);\n if (current.length === 0 && eligibleGraphemes > 0) step = Math.max(1, step);\n\n const catchupStep =\n pendingOffsets.length > catchupThreshold\n ? Math.min(maxCatchupChars, Math.ceil(pendingOffsets.length / 10))\n : 0;\n step = Math.min(eligibleGraphemes, Math.max(step, catchupStep));\n\n if (step > 0) {\n progressRemainderRef.current = Math.max(0, progressRemainderRef.current - step);\n const next = current + pending.slice(0, pendingOffsets[step - 1]);\n displayedRef.current = next;\n setDisplayedText(next);\n }\n rafRef.current = window.requestAnimationFrame(tick);\n };\n\n if (rafRef.current === null) {\n rafRef.current = window.requestAnimationFrame(tick);\n }\n\n return () => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n lastFrameAtRef.current = null;\n progressRemainderRef.current = 0;\n };\n }, [cacheAdapter, catchupThreshold, charsPerSecond, id, isStreaming, maxCatchupChars]);\n\n const reduceMotion =\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n return {\n displayedText: !isStreaming || reduceMotion ? text : displayedText,\n isAnimating: isStreaming,\n mode: isStreaming ? \"streaming\" : \"static\",\n parseIncompleteMarkdown: isStreaming,\n };\n}\n"],"mappings":"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","names":["reduceMotion"]}
package/dist/index.cjs CHANGED
@@ -542,7 +542,7 @@ var defaultStreamingTextCache = {
542
542
  }
543
543
  };
544
544
  var getActiveStreamingTextPartId = (message, streamingMessageId) => {
545
- if (message.role !== "assistant" || streamingMessageId !== message.id) return null;
545
+ if (message.role !== "assistant" || message.responseCompletion || streamingMessageId !== message.id) return null;
546
546
  const trailingPart = message.parts[message.parts.length - 1];
547
547
  return trailingPart?.kind === "text" ? trailingPart.id : null;
548
548
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/latest-thread-scroller.tsx","../src/mcp-oauth.ts","../src/streaming-text.ts","../src/viewport.ts"],"sourcesContent":["export * from \"./latest-thread-scroller\";\nexport * from \"./mcp-oauth\";\nexport * from \"./streaming-text\";\nexport * from \"./types\";\nexport * from \"./viewport\";\n","import * as React from \"react\";\nimport {\n MessageScroller,\n useMessageScroller,\n useMessageScrollerVisibility,\n} from \"@shadcn/react/message-scroller\";\n\nconst cx = (...values: Array<string | false | null | undefined>) =>\n values.filter(Boolean).join(\" \");\n\n/** Anchor the current turn only; older user anchors can trigger a late jump. */\nexport function latestThreadAnchorId(messages: readonly { id: string; role: string }[]): string | null {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n if (messages[index].role === \"user\") return messages[index].id;\n }\n return null;\n}\n\ntype MessageScrollerProviderProps = React.ComponentProps<\n typeof MessageScroller.Provider\n>;\ntype MessageScrollerRootProps = React.ComponentProps<typeof MessageScroller.Root>;\ntype MessageScrollerViewportProps = React.ComponentProps<\n typeof MessageScroller.Viewport\n>;\ntype MessageScrollerContentProps = React.ComponentProps<\n typeof MessageScroller.Content\n>;\ntype MessageScrollerItemProps = React.ComponentProps<typeof MessageScroller.Item>;\ntype MessageScrollerButtonProps = React.ComponentProps<typeof MessageScroller.Button>;\n\ntype LatestThreadScrollerLayoutContextValue = {\n contentElement: HTMLElement | null;\n rootElement: HTMLElement | null;\n setContentElement: (node: HTMLElement | null) => void;\n setRootElement: (node: HTMLElement | null) => void;\n};\n\nconst LatestThreadScrollerLayoutContext =\n React.createContext<LatestThreadScrollerLayoutContextValue | null>(null);\n\nconst useLatestThreadScrollerLayout = () =>\n React.useContext(LatestThreadScrollerLayoutContext);\n\nfunction RestoreThreadPosition({ restoreKey }: { restoreKey?: string | null }) {\n const { scrollToEnd } = useMessageScroller();\n React.useLayoutEffect(() => {\n if (restoreKey) scrollToEnd({ behavior: \"auto\" });\n }, [restoreKey, scrollToEnd]);\n return null;\n}\n\nexport type LatestThreadScrollerProviderProps = MessageScrollerProviderProps & {\n /** Scroll to the latest turn when a different transcript is opened. */\n restoreKey?: string | null;\n};\n\nexport function LatestThreadScrollerProvider({\n autoScroll = true,\n children,\n defaultScrollPosition = \"last-anchor\",\n restoreKey,\n scrollPreviousItemPeek = 64,\n ...props\n}: LatestThreadScrollerProviderProps) {\n return (\n <MessageScroller.Provider\n autoScroll={autoScroll}\n defaultScrollPosition={defaultScrollPosition}\n scrollPreviousItemPeek={scrollPreviousItemPeek}\n {...props}\n >\n {children}\n <RestoreThreadPosition restoreKey={restoreKey} />\n </MessageScroller.Provider>\n );\n}\n\nexport type LatestThreadScrollerRootProps = MessageScrollerRootProps;\n\nexport function LatestThreadScrollerRoot({\n className,\n ref,\n ...props\n}: LatestThreadScrollerRootProps) {\n const [rootElement, setRootElement] = React.useState<HTMLElement | null>(null);\n const [contentElement, setContentElement] =\n React.useState<HTMLElement | null>(null);\n const layoutContext = React.useMemo<LatestThreadScrollerLayoutContextValue>(\n () => ({\n contentElement,\n rootElement,\n setContentElement,\n setRootElement,\n }),\n [contentElement, rootElement]\n );\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n setRootElement(node);\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref]\n );\n\n return (\n <LatestThreadScrollerLayoutContext.Provider value={layoutContext}>\n <MessageScroller.Root\n ref={setRef}\n className={cx(\n \"a24-scroller relative flex size-full min-h-0 flex-1 flex-col overflow-hidden\",\n className\n )}\n {...props}\n />\n </LatestThreadScrollerLayoutContext.Provider>\n );\n}\n\nexport type LatestThreadScrollerViewportProps =\n MessageScrollerViewportProps & {\n onViewportChange?: (node: HTMLElement | null) => void;\n };\n\nexport function LatestThreadScrollerViewport({\n className,\n onViewportChange,\n preserveScrollOnPrepend = true,\n ref,\n ...props\n}: LatestThreadScrollerViewportProps) {\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n onViewportChange?.(node);\n },\n [onViewportChange, ref]\n );\n\n return (\n <MessageScroller.Viewport\n ref={setRef}\n className={cx(\n \"a24-scroller__viewport size-full min-h-0 min-w-0 flex-1 overflow-y-auto overscroll-contain\",\n className\n )}\n preserveScrollOnPrepend={preserveScrollOnPrepend}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerContentProps = MessageScrollerContentProps;\n\nexport function LatestThreadScrollerContent({\n className,\n ref,\n ...props\n}: LatestThreadScrollerContentProps) {\n const layout = useLatestThreadScrollerLayout();\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n layout?.setContentElement(node);\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [layout, ref]\n );\n\n return (\n <MessageScroller.Content\n ref={setRef}\n data-agents24-latest-thread-content=\"\"\n className={cx(\"a24-scroller__content flex h-max min-h-full flex-col gap-3 p-4\", className)}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerItemProps = Omit<\n MessageScrollerItemProps,\n \"messageId\"\n> & {\n messageId: string;\n};\n\nexport function LatestThreadScrollerItem({\n className,\n messageId,\n ...props\n}: LatestThreadScrollerItemProps) {\n return (\n <MessageScroller.Item\n className={cx(\n \"a24-scroller__item min-w-0 shrink-0 overflow-visible\",\n className\n )}\n messageId={messageId}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerButtonProps = Omit<\n MessageScrollerButtonProps,\n \"render\"\n> & {\n className?: string;\n render?: MessageScrollerButtonProps[\"render\"];\n};\n\nexport function LatestThreadScrollerButton({\n children,\n className,\n direction = \"end\",\n render,\n ...props\n}: LatestThreadScrollerButtonProps) {\n if (render) {\n return (\n <MessageScroller.Button\n direction={direction}\n render={render}\n {...props}\n />\n );\n }\n\n return (\n <MessageScroller.Button\n direction={direction}\n render={(buttonProps) => (\n <button\n {...(buttonProps as Record<string, unknown>)}\n aria-label={\n direction === \"end\"\n ? \"Scroll to latest message\"\n : \"Scroll to first message\"\n }\n className={cx(\n \"a24-scroller__button absolute bottom-4 left-1/2 z-50 flex size-9 -translate-x-1/2 items-center justify-center rounded-full border border-border bg-background text-foreground shadow-md transition-[background-color,border-color,color,opacity,transform] duration-200 data-[active=false]:pointer-events-none data-[active=false]:translate-y-2 data-[active=false]:opacity-0 data-[active=true]:translate-y-0 data-[active=true]:opacity-100\",\n className\n )}\n type=\"button\"\n >\n {children ?? (direction === \"end\" ? \"↓\" : \"↑\")}\n </button>\n )}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerOutlineItem = {\n id: string;\n label: string;\n messageIds?: string[];\n responsePreview?: string;\n};\n\nexport type LatestThreadScrollerOutlineProps = {\n cardClassName?: string;\n className?: string;\n contentMaxWidth?: number;\n dir?: \"ltr\" | \"rtl\";\n items: LatestThreadScrollerOutlineItem[];\n minContainerWidthForRail?: number;\n minSideGutterForRail?: number;\n side?: \"left\" | \"right\";\n verticalOffset?: string;\n};\n\nexport function LatestThreadScrollerOutline({\n cardClassName,\n className,\n contentMaxWidth = 768,\n dir = \"ltr\",\n items,\n minContainerWidthForRail = 0,\n minSideGutterForRail = 48,\n side,\n verticalOffset = \"3.5rem\",\n}: LatestThreadScrollerOutlineProps) {\n const navRef = React.useRef<HTMLElement | null>(null);\n const layout = useLatestThreadScrollerLayout();\n const [hasSideRoom, setHasSideRoom] = React.useState(false);\n const [hoveredIndex, setHoveredIndex] = React.useState<number | null>(null);\n const { scrollToMessage } = useMessageScroller();\n const { currentAnchorId, visibleMessageIds } = useMessageScrollerVisibility();\n const visibleMessageIdSet = React.useMemo(\n () => new Set(visibleMessageIds),\n [visibleMessageIds]\n );\n const focusIndex = hoveredIndex ?? -1;\n const railSide = side ?? (dir === \"rtl\" ? \"right\" : \"left\");\n\n React.useEffect(() => {\n const root = layout?.rootElement ?? navRef.current?.parentElement;\n if (!root) return;\n\n const updateSideRoom = () => {\n const rootRect = root.getBoundingClientRect();\n const rootWidth = rootRect.width;\n const content = layout?.contentElement;\n const sideGutter = content\n ? Math.max(\n 0,\n railSide === \"left\"\n ? content.getBoundingClientRect().left - rootRect.left\n : rootRect.right - content.getBoundingClientRect().right\n )\n : Math.max(0, (rootWidth - contentMaxWidth) / 2);\n const nextHasSideRoom =\n rootWidth >= minContainerWidthForRail &&\n sideGutter >= minSideGutterForRail;\n setHasSideRoom((current) =>\n current === nextHasSideRoom ? current : nextHasSideRoom\n );\n };\n\n updateSideRoom();\n if (typeof ResizeObserver === \"undefined\") return;\n const resizeObserver = new ResizeObserver(updateSideRoom);\n resizeObserver.observe(root);\n const content = layout?.contentElement;\n if (content) {\n resizeObserver.observe(content);\n }\n return () => resizeObserver.disconnect();\n }, [\n contentMaxWidth,\n layout?.contentElement,\n layout?.rootElement,\n minContainerWidthForRail,\n minSideGutterForRail,\n railSide,\n ]);\n\n if (items.length < 2) {\n return null;\n }\n\n return (\n <nav\n ref={navRef}\n aria-label=\"Transcript outline\"\n data-side={railSide}\n data-visible={hasSideRoom ? \"\" : undefined}\n className={cx(\n \"a24-outline pointer-events-none absolute z-10 max-h-[min(18rem,calc(100%-10rem))] w-16 overflow-visible\",\n hasSideRoom ? \"hidden md:block\" : \"hidden\",\n railSide === \"left\" ? \"left-1\" : \"right-1\",\n className\n )}\n dir={dir}\n style={{\n top: \"50%\",\n transform: `translateY(calc(-50% - ${verticalOffset}))`,\n }}\n >\n <div className=\"a24-outline__rail pointer-events-auto flex flex-col gap-0 py-1\">\n {items.map((item, index) => {\n const itemMessageIds =\n item.messageIds && item.messageIds.length > 0\n ? item.messageIds\n : [item.id];\n const active = itemMessageIds.some(\n (messageId) =>\n visibleMessageIdSet.has(messageId) || messageId === currentAnchorId\n );\n const distance =\n focusIndex >= 0 ? Math.abs(index - focusIndex) : Number.POSITIVE_INFINITY;\n const isFocused = distance === 0;\n const isNear = distance === 1;\n const isNextNear = distance === 2;\n const barWidth = isFocused\n ? 50\n : isNear\n ? 36\n : isNextNear\n ? 23\n : 10;\n const barTone = focusIndex < 0\n ? active ? 80 : 18\n : isFocused ? 80 : isNear ? 32 : isNextNear ? 24 : 16;\n const fallbackLabel = `Turn ${index + 1}`;\n const previewLabel =\n item.label && item.label !== fallbackLabel ? item.label : \"\";\n const responsePreview = (item.responsePreview || \"\").trim();\n\n return (\n <button\n key={item.id}\n type=\"button\"\n data-active={active}\n data-side={railSide}\n dir=\"ltr\"\n className={cx(\n \"a24-outline__button group relative flex h-2 w-16 items-center rounded-sm outline-none\",\n railSide === \"left\" ? \"justify-start\" : \"justify-end\"\n )}\n aria-label={`Jump to ${item.label || fallbackLabel}`}\n onBlur={() => setHoveredIndex(null)}\n onFocus={() => setHoveredIndex(index)}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(null)}\n onClick={() =>\n scrollToMessage(item.id, {\n align: \"start\",\n behavior: \"smooth\",\n })\n }\n >\n <span\n className=\"a24-outline__bar h-0.5 rounded-full transition-[width,background-color] duration-150 ease-out\"\n style={{\n backgroundColor: `color-mix(in oklch, var(--a24-text) ${barTone}%, transparent)`,\n width: barWidth,\n }}\n />\n {previewLabel ? (\n <span\n dir={dir}\n className={cx(\n \"a24-outline__preview pointer-events-none absolute top-1/2 z-20 max-h-32 w-64 -translate-y-1/2 overflow-hidden rounded-lg border border-border/80 bg-background p-3 text-start opacity-0 shadow-lg transition-[opacity,transform] duration-200 group-hover:pointer-events-auto group-hover:opacity-100 group-focus-visible:pointer-events-auto group-focus-visible:opacity-100\",\n railSide === \"left\"\n ? \"left-full ml-2 -translate-x-1 group-hover:translate-x-0 group-focus-visible:translate-x-0\"\n : \"right-full mr-2 translate-x-1 group-hover:translate-x-0 group-focus-visible:translate-x-0\",\n cardClassName\n )}\n >\n <span\n className=\"block overflow-hidden text-sm leading-5 text-foreground\"\n style={{\n display: \"-webkit-box\",\n WebkitBoxOrient: \"vertical\",\n WebkitLineClamp: responsePreview ? 2 : 4,\n }}\n >\n {previewLabel}\n </span>\n {responsePreview ? (\n <span\n className=\"mt-1 block overflow-hidden text-sm leading-5 text-muted-foreground\"\n style={{\n display: \"-webkit-box\",\n WebkitBoxOrient: \"vertical\",\n WebkitLineClamp: 2,\n }}\n >\n {responsePreview}\n </span>\n ) : null}\n </span>\n ) : null}\n </button>\n );\n })}\n </div>\n </nav>\n );\n}\n\nexport const LatestThreadScroller = {\n Provider: LatestThreadScrollerProvider,\n Root: LatestThreadScrollerRoot,\n Viewport: LatestThreadScrollerViewport,\n Content: LatestThreadScrollerContent,\n Item: LatestThreadScrollerItem,\n Button: LatestThreadScrollerButton,\n Outline: LatestThreadScrollerOutline,\n};\n","import type { McpCallbackResult } from \"@agents24/client\";\nimport type { ChatMcpOauthCompletion, WaitForMcpOauthCompleteInput } from \"./types\";\n\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\ntype CryptoLike = {\n getRandomValues<T extends Uint8Array>(array: T): T;\n randomUUID(): string;\n subtle: { digest(algorithm: string, data: Uint8Array): Promise<ArrayBuffer> };\n};\n\nexport function browserChatCrypto(): CryptoLike {\n const value = (globalThis as unknown as { crypto?: CryptoLike }).crypto;\n if (!value?.subtle || !value.randomUUID) {\n throw new Error(\"Secure browser crypto is required for MCP authorization.\");\n }\n return value;\n}\n\nfunction base64Url(bytes: Uint8Array): string {\n let binary = \"\";\n bytes.forEach((byte) => { binary += String.fromCharCode(byte); });\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/g, \"\");\n}\n\nexport async function createMcpPkceProof(): Promise<{ challenge: string; verifier: string }> {\n const crypto = browserChatCrypto();\n const verifier = base64Url(crypto.getRandomValues(new Uint8Array(32)));\n const digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(verifier));\n return { challenge: base64Url(new Uint8Array(digest)), verifier };\n}\n\nfunction isLoopback(hostname: string): boolean {\n return hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"[::1]\";\n}\n\nfunction normalizedOrigin(value: string): string {\n try {\n const url = new URL(value);\n if (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && isLoopback(url.hostname))) {\n throw new Error(\"unsafe callback origin\");\n }\n if (url.origin === \"null\") throw new Error(\"opaque callback origin\");\n return url.origin;\n } catch {\n throw new Error(\"MCP authorization returned an invalid callback origin.\");\n }\n}\n\nexport function validateMcpCallbackResult(\n result: McpCallbackResult,\n expectedServerId: string,\n): McpCallbackResult {\n const serverId = String(result.server_id || \"\").trim();\n const connectionId = String(result.connection_id || \"\").trim();\n if (!serverId || serverId !== expectedServerId) {\n throw new Error(\"MCP authorization completed for an unexpected server.\");\n }\n if (!UUID_PATTERN.test(connectionId)) {\n throw new Error(\"MCP authorization returned an invalid connection identity.\");\n }\n return result;\n}\n\nexport function waitForMcpOauthComplete({\n popup,\n callbackOrigin,\n popupNonce,\n requireConnectionId = false,\n serverId,\n timeoutMs = 120_000,\n}: WaitForMcpOauthCompleteInput): Promise<ChatMcpOauthCompletion> {\n if (!popup) return Promise.reject(new Error(\"Could not open the MCP authorization popup.\"));\n const expectedOrigin = normalizedOrigin(callbackOrigin);\n const expectedServerId = String(serverId || \"\").trim();\n const expectedPopupNonce = String(popupNonce || \"\").trim();\n if (!expectedServerId) return Promise.reject(new Error(\"MCP authorization is missing its server identity.\"));\n if (!expectedPopupNonce) return Promise.reject(new Error(\"MCP authorization is missing its popup binding.\"));\n const returnFocusTo = typeof document !== \"undefined\"\n ? document.activeElement as { focus?: () => void } | null\n : null;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const finish = (result: ChatMcpOauthCompletion | Error) => {\n if (settled) return;\n settled = true;\n window.clearTimeout(timeout);\n window.clearInterval(closeTimer);\n window.removeEventListener(\"message\", onMessage);\n returnFocusTo?.focus?.();\n if (result instanceof Error) reject(result);\n else resolve(result);\n };\n const onMessage = (event: MessageEvent) => {\n if (event.source !== popup || event.origin !== expectedOrigin) return;\n const data = event.data as {\n type?: string;\n code?: string;\n connection_id?: string;\n popup_nonce?: string;\n server_id?: string;\n } | null;\n if (\n data?.type !== \"agents24.mcp.callback\" ||\n data.server_id !== expectedServerId ||\n data.popup_nonce !== expectedPopupNonce\n ) return;\n const code = String(data.code || \"\").trim();\n if (!code || code.length > 2048) return;\n const connectionId = String(data.connection_id || \"\").trim();\n if ((requireConnectionId || connectionId) && !UUID_PATTERN.test(connectionId)) return;\n finish({\n code,\n ...(connectionId ? { connectionId } : {}),\n popupNonce: expectedPopupNonce,\n serverId: expectedServerId,\n });\n };\n const timeout = window.setTimeout(\n () => finish(new Error(\"MCP authorization timed out.\")),\n Math.max(1, timeoutMs),\n );\n const closeTimer = window.setInterval(() => {\n if (popup.closed) finish(new Error(\"MCP authorization window was closed before connecting.\"));\n }, 500);\n window.addEventListener(\"message\", onMessage);\n });\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nimport type { ChatMessage, ChatPart } from \"./types\";\n\nexport type StreamingTextMode = \"streaming\" | \"static\";\n\nexport type StreamingTextCache = {\n get: (id: string) => string | undefined;\n set: (id: string, text: string) => void;\n};\n\nexport type UseStreamingTextOptions = {\n id: string;\n isStreaming: boolean;\n text: string;\n cache?: StreamingTextCache | false;\n charsPerSecond?: number;\n catchupThreshold?: number;\n maxCatchupChars?: number;\n};\n\nexport type UseStreamingTextResult = {\n displayedText: string;\n isAnimating: boolean;\n mode: StreamingTextMode;\n parseIncompleteMarkdown: boolean;\n};\n\nconst DEFAULT_COMPLETED_TEXT_CACHE_SIZE = 200;\nconst STREAM_RUNWAY_MS = 80;\nconst STREAM_IDLE_RELEASE_MS = 120;\nconst defaultCompletedTextCache = new Map<string, string>();\n\nconst defaultStreamingTextCache: StreamingTextCache = {\n get: (id) => defaultCompletedTextCache.get(id),\n set: (id, text) => {\n defaultCompletedTextCache.set(id, text);\n if (defaultCompletedTextCache.size > DEFAULT_COMPLETED_TEXT_CACHE_SIZE) {\n const firstKey = defaultCompletedTextCache.keys().next().value;\n if (firstKey) defaultCompletedTextCache.delete(firstKey);\n }\n },\n};\n\nexport const getActiveStreamingTextPartId = (\n message: ChatMessage,\n streamingMessageId: string | null\n) => {\n if (message.role !== \"assistant\" || streamingMessageId !== message.id) return null;\n const trailingPart = message.parts[message.parts.length - 1];\n return trailingPart?.kind === \"text\" ? trailingPart.id : null;\n};\n\nexport const isActiveStreamingTextPart = (\n message: ChatMessage,\n part: ChatPart,\n streamingMessageId: string | null\n) => part.kind === \"text\" && part.id === getActiveStreamingTextPartId(message, streamingMessageId);\n\nconst graphemeEndOffsets = (value: string): number[] => {\n if (!value) return [];\n\n if (typeof Intl !== \"undefined\" && \"Segmenter\" in Intl) {\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n return Array.from(segmenter.segment(value), ({ index, segment }) => index + segment.length);\n }\n\n const characters = Array.from(value);\n const offsets: number[] = [];\n let offset = 0;\n let regionalIndicators = 0;\n characters.forEach((character, index) => {\n const previous = characters[index - 1];\n const codePoint = character.codePointAt(0) ?? 0;\n const isRegionalIndicator = codePoint >= 0x1f1e6 && codePoint <= 0x1f1ff;\n const continuesCluster =\n index > 0 &&\n (/^\\p{Mark}$/u.test(character) ||\n (codePoint >= 0xfe00 && codePoint <= 0xfe0f) ||\n (codePoint >= 0x1f3fb && codePoint <= 0x1f3ff) ||\n character === \"\\u200d\" ||\n previous === \"\\u200d\" ||\n (isRegionalIndicator && regionalIndicators % 2 === 1));\n if (!continuesCluster) {\n if (offset > 0) offsets.push(offset);\n regionalIndicators = 0;\n }\n offset += character.length;\n regionalIndicators = isRegionalIndicator ? regionalIndicators + 1 : 0;\n });\n offsets.push(offset);\n return offsets;\n};\n\nexport function useStreamingText({\n id,\n isStreaming,\n text,\n cache = defaultStreamingTextCache,\n charsPerSecond = 72,\n catchupThreshold = 40,\n maxCatchupChars = 20,\n}: UseStreamingTextOptions): UseStreamingTextResult {\n const cacheAdapter = cache === false ? null : cache;\n const [displayedText, setDisplayedText] = useState(() => {\n const cachedText = cacheAdapter?.get(id);\n return cachedText && text.startsWith(cachedText) ? cachedText : text;\n });\n const targetRef = useRef(text);\n const displayedRef = useRef(displayedText);\n const rafRef = useRef<number | null>(null);\n const lastFrameAtRef = useRef<number | null>(null);\n const targetUpdatedAtRef = useRef<number | null>(null);\n const progressRemainderRef = useRef(0);\n const idRef = useRef(id);\n const streamingRef = useRef(isStreaming);\n const reduceMotionRef = useRef(false);\n\n useEffect(() => {\n if (isStreaming || !text) return;\n cacheAdapter?.set(id, text);\n }, [cacheAdapter, id, isStreaming, text]);\n\n useEffect(() => {\n targetRef.current = text;\n targetUpdatedAtRef.current =\n typeof performance === \"undefined\" ? null : performance.now();\n\n if (\n !isStreaming ||\n reduceMotionRef.current ||\n !text.startsWith(displayedRef.current)\n ) {\n displayedRef.current = text;\n setDisplayedText(text);\n progressRemainderRef.current = 0;\n }\n }, [isStreaming, text]);\n\n useEffect(() => {\n if (idRef.current === id) return;\n\n idRef.current = id;\n const cachedText = cacheAdapter?.get(id);\n const initial = cachedText && text.startsWith(cachedText) ? cachedText : text;\n displayedRef.current = initial;\n setDisplayedText(initial);\n lastFrameAtRef.current = null;\n targetUpdatedAtRef.current =\n typeof performance === \"undefined\" ? null : performance.now();\n progressRemainderRef.current = 0;\n }, [cacheAdapter, id, isStreaming, text]);\n\n useEffect(() => {\n streamingRef.current = isStreaming;\n\n if (typeof window === \"undefined\") {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n const reduceMotion =\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n reduceMotionRef.current = reduceMotion;\n\n if (reduceMotion || !isStreaming) {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n const cachedText = cacheAdapter?.get(id);\n if (cachedText === text) {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n if (!text.startsWith(displayedRef.current)) {\n displayedRef.current = text;\n setDisplayedText(text);\n }\n\n const tick = (timestamp: number) => {\n const previousTimestamp = lastFrameAtRef.current ?? timestamp;\n lastFrameAtRef.current = timestamp;\n\n const target = targetRef.current;\n const current = displayedRef.current;\n\n if (!streamingRef.current || reduceMotionRef.current) {\n displayedRef.current = target;\n setDisplayedText(target);\n rafRef.current = null;\n return;\n }\n\n if (!target.startsWith(current)) {\n displayedRef.current = target;\n setDisplayedText(target);\n progressRemainderRef.current = 0;\n rafRef.current = window.requestAnimationFrame(tick);\n return;\n }\n\n const pending = target.slice(current.length);\n const pendingOffsets = graphemeEndOffsets(pending);\n if (pendingOffsets.length === 0) {\n rafRef.current = window.requestAnimationFrame(tick);\n return;\n }\n\n const elapsedMs = Math.max(0, timestamp - previousTimestamp);\n const targetIdleMs =\n targetUpdatedAtRef.current === null\n ? STREAM_IDLE_RELEASE_MS\n : Math.max(0, timestamp - targetUpdatedAtRef.current);\n const runway =\n targetIdleMs >= STREAM_IDLE_RELEASE_MS\n ? 0\n : Math.min(\n pendingOffsets.length - 1,\n Math.max(1, Math.ceil((charsPerSecond * STREAM_RUNWAY_MS) / 1000))\n );\n const eligibleGraphemes = pendingOffsets.length - runway;\n\n progressRemainderRef.current += (elapsedMs / 1000) * charsPerSecond;\n let step = Math.floor(progressRemainderRef.current);\n if (current.length === 0 && eligibleGraphemes > 0) step = Math.max(1, step);\n\n const catchupStep =\n pendingOffsets.length > catchupThreshold\n ? Math.min(maxCatchupChars, Math.ceil(pendingOffsets.length / 10))\n : 0;\n step = Math.min(eligibleGraphemes, Math.max(step, catchupStep));\n\n if (step > 0) {\n progressRemainderRef.current = Math.max(0, progressRemainderRef.current - step);\n const next = current + pending.slice(0, pendingOffsets[step - 1]);\n displayedRef.current = next;\n setDisplayedText(next);\n }\n rafRef.current = window.requestAnimationFrame(tick);\n };\n\n if (rafRef.current === null) {\n rafRef.current = window.requestAnimationFrame(tick);\n }\n\n return () => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n lastFrameAtRef.current = null;\n progressRemainderRef.current = 0;\n };\n }, [cacheAdapter, catchupThreshold, charsPerSecond, id, isStreaming, maxCatchupChars]);\n\n const reduceMotion =\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n return {\n displayedText: !isStreaming || reduceMotion ? text : displayedText,\n isAnimating: isStreaming,\n mode: isStreaming ? \"streaming\" : \"static\",\n parseIncompleteMarkdown: isStreaming,\n };\n}\n","export {\n MessageScroller,\n useMessageScroller,\n useMessageScrollerScrollable,\n useMessageScrollerVisibility,\n} from \"@shadcn/react/message-scroller\";\nexport type {\n MessageScrollerDefaultScrollPosition,\n MessageScrollerScrollAlign,\n MessageScrollerScrollable,\n MessageScrollerScrollOptions,\n MessageScrollerVisibilityState,\n} from \"@shadcn/react/message-scroller\";\n"],"mappings":"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","names":["content","reduceMotion","import_message_scroller"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/latest-thread-scroller.tsx","../src/mcp-oauth.ts","../src/streaming-text.ts","../src/viewport.ts"],"sourcesContent":["export * from \"./latest-thread-scroller\";\nexport * from \"./mcp-oauth\";\nexport * from \"./streaming-text\";\nexport * from \"./types\";\nexport * from \"./viewport\";\n","import * as React from \"react\";\nimport {\n MessageScroller,\n useMessageScroller,\n useMessageScrollerVisibility,\n} from \"@shadcn/react/message-scroller\";\n\nconst cx = (...values: Array<string | false | null | undefined>) =>\n values.filter(Boolean).join(\" \");\n\n/** Anchor the current turn only; older user anchors can trigger a late jump. */\nexport function latestThreadAnchorId(messages: readonly { id: string; role: string }[]): string | null {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n if (messages[index].role === \"user\") return messages[index].id;\n }\n return null;\n}\n\ntype MessageScrollerProviderProps = React.ComponentProps<\n typeof MessageScroller.Provider\n>;\ntype MessageScrollerRootProps = React.ComponentProps<typeof MessageScroller.Root>;\ntype MessageScrollerViewportProps = React.ComponentProps<\n typeof MessageScroller.Viewport\n>;\ntype MessageScrollerContentProps = React.ComponentProps<\n typeof MessageScroller.Content\n>;\ntype MessageScrollerItemProps = React.ComponentProps<typeof MessageScroller.Item>;\ntype MessageScrollerButtonProps = React.ComponentProps<typeof MessageScroller.Button>;\n\ntype LatestThreadScrollerLayoutContextValue = {\n contentElement: HTMLElement | null;\n rootElement: HTMLElement | null;\n setContentElement: (node: HTMLElement | null) => void;\n setRootElement: (node: HTMLElement | null) => void;\n};\n\nconst LatestThreadScrollerLayoutContext =\n React.createContext<LatestThreadScrollerLayoutContextValue | null>(null);\n\nconst useLatestThreadScrollerLayout = () =>\n React.useContext(LatestThreadScrollerLayoutContext);\n\nfunction RestoreThreadPosition({ restoreKey }: { restoreKey?: string | null }) {\n const { scrollToEnd } = useMessageScroller();\n React.useLayoutEffect(() => {\n if (restoreKey) scrollToEnd({ behavior: \"auto\" });\n }, [restoreKey, scrollToEnd]);\n return null;\n}\n\nexport type LatestThreadScrollerProviderProps = MessageScrollerProviderProps & {\n /** Scroll to the latest turn when a different transcript is opened. */\n restoreKey?: string | null;\n};\n\nexport function LatestThreadScrollerProvider({\n autoScroll = true,\n children,\n defaultScrollPosition = \"last-anchor\",\n restoreKey,\n scrollPreviousItemPeek = 64,\n ...props\n}: LatestThreadScrollerProviderProps) {\n return (\n <MessageScroller.Provider\n autoScroll={autoScroll}\n defaultScrollPosition={defaultScrollPosition}\n scrollPreviousItemPeek={scrollPreviousItemPeek}\n {...props}\n >\n {children}\n <RestoreThreadPosition restoreKey={restoreKey} />\n </MessageScroller.Provider>\n );\n}\n\nexport type LatestThreadScrollerRootProps = MessageScrollerRootProps;\n\nexport function LatestThreadScrollerRoot({\n className,\n ref,\n ...props\n}: LatestThreadScrollerRootProps) {\n const [rootElement, setRootElement] = React.useState<HTMLElement | null>(null);\n const [contentElement, setContentElement] =\n React.useState<HTMLElement | null>(null);\n const layoutContext = React.useMemo<LatestThreadScrollerLayoutContextValue>(\n () => ({\n contentElement,\n rootElement,\n setContentElement,\n setRootElement,\n }),\n [contentElement, rootElement]\n );\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n setRootElement(node);\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref]\n );\n\n return (\n <LatestThreadScrollerLayoutContext.Provider value={layoutContext}>\n <MessageScroller.Root\n ref={setRef}\n className={cx(\n \"a24-scroller relative flex size-full min-h-0 flex-1 flex-col overflow-hidden\",\n className\n )}\n {...props}\n />\n </LatestThreadScrollerLayoutContext.Provider>\n );\n}\n\nexport type LatestThreadScrollerViewportProps =\n MessageScrollerViewportProps & {\n onViewportChange?: (node: HTMLElement | null) => void;\n };\n\nexport function LatestThreadScrollerViewport({\n className,\n onViewportChange,\n preserveScrollOnPrepend = true,\n ref,\n ...props\n}: LatestThreadScrollerViewportProps) {\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n onViewportChange?.(node);\n },\n [onViewportChange, ref]\n );\n\n return (\n <MessageScroller.Viewport\n ref={setRef}\n className={cx(\n \"a24-scroller__viewport size-full min-h-0 min-w-0 flex-1 overflow-y-auto overscroll-contain\",\n className\n )}\n preserveScrollOnPrepend={preserveScrollOnPrepend}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerContentProps = MessageScrollerContentProps;\n\nexport function LatestThreadScrollerContent({\n className,\n ref,\n ...props\n}: LatestThreadScrollerContentProps) {\n const layout = useLatestThreadScrollerLayout();\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n layout?.setContentElement(node);\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [layout, ref]\n );\n\n return (\n <MessageScroller.Content\n ref={setRef}\n data-agents24-latest-thread-content=\"\"\n className={cx(\"a24-scroller__content flex h-max min-h-full flex-col gap-3 p-4\", className)}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerItemProps = Omit<\n MessageScrollerItemProps,\n \"messageId\"\n> & {\n messageId: string;\n};\n\nexport function LatestThreadScrollerItem({\n className,\n messageId,\n ...props\n}: LatestThreadScrollerItemProps) {\n return (\n <MessageScroller.Item\n className={cx(\n \"a24-scroller__item min-w-0 shrink-0 overflow-visible\",\n className\n )}\n messageId={messageId}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerButtonProps = Omit<\n MessageScrollerButtonProps,\n \"render\"\n> & {\n className?: string;\n render?: MessageScrollerButtonProps[\"render\"];\n};\n\nexport function LatestThreadScrollerButton({\n children,\n className,\n direction = \"end\",\n render,\n ...props\n}: LatestThreadScrollerButtonProps) {\n if (render) {\n return (\n <MessageScroller.Button\n direction={direction}\n render={render}\n {...props}\n />\n );\n }\n\n return (\n <MessageScroller.Button\n direction={direction}\n render={(buttonProps) => (\n <button\n {...(buttonProps as Record<string, unknown>)}\n aria-label={\n direction === \"end\"\n ? \"Scroll to latest message\"\n : \"Scroll to first message\"\n }\n className={cx(\n \"a24-scroller__button absolute bottom-4 left-1/2 z-50 flex size-9 -translate-x-1/2 items-center justify-center rounded-full border border-border bg-background text-foreground shadow-md transition-[background-color,border-color,color,opacity,transform] duration-200 data-[active=false]:pointer-events-none data-[active=false]:translate-y-2 data-[active=false]:opacity-0 data-[active=true]:translate-y-0 data-[active=true]:opacity-100\",\n className\n )}\n type=\"button\"\n >\n {children ?? (direction === \"end\" ? \"↓\" : \"↑\")}\n </button>\n )}\n {...props}\n />\n );\n}\n\nexport type LatestThreadScrollerOutlineItem = {\n id: string;\n label: string;\n messageIds?: string[];\n responsePreview?: string;\n};\n\nexport type LatestThreadScrollerOutlineProps = {\n cardClassName?: string;\n className?: string;\n contentMaxWidth?: number;\n dir?: \"ltr\" | \"rtl\";\n items: LatestThreadScrollerOutlineItem[];\n minContainerWidthForRail?: number;\n minSideGutterForRail?: number;\n side?: \"left\" | \"right\";\n verticalOffset?: string;\n};\n\nexport function LatestThreadScrollerOutline({\n cardClassName,\n className,\n contentMaxWidth = 768,\n dir = \"ltr\",\n items,\n minContainerWidthForRail = 0,\n minSideGutterForRail = 48,\n side,\n verticalOffset = \"3.5rem\",\n}: LatestThreadScrollerOutlineProps) {\n const navRef = React.useRef<HTMLElement | null>(null);\n const layout = useLatestThreadScrollerLayout();\n const [hasSideRoom, setHasSideRoom] = React.useState(false);\n const [hoveredIndex, setHoveredIndex] = React.useState<number | null>(null);\n const { scrollToMessage } = useMessageScroller();\n const { currentAnchorId, visibleMessageIds } = useMessageScrollerVisibility();\n const visibleMessageIdSet = React.useMemo(\n () => new Set(visibleMessageIds),\n [visibleMessageIds]\n );\n const focusIndex = hoveredIndex ?? -1;\n const railSide = side ?? (dir === \"rtl\" ? \"right\" : \"left\");\n\n React.useEffect(() => {\n const root = layout?.rootElement ?? navRef.current?.parentElement;\n if (!root) return;\n\n const updateSideRoom = () => {\n const rootRect = root.getBoundingClientRect();\n const rootWidth = rootRect.width;\n const content = layout?.contentElement;\n const sideGutter = content\n ? Math.max(\n 0,\n railSide === \"left\"\n ? content.getBoundingClientRect().left - rootRect.left\n : rootRect.right - content.getBoundingClientRect().right\n )\n : Math.max(0, (rootWidth - contentMaxWidth) / 2);\n const nextHasSideRoom =\n rootWidth >= minContainerWidthForRail &&\n sideGutter >= minSideGutterForRail;\n setHasSideRoom((current) =>\n current === nextHasSideRoom ? current : nextHasSideRoom\n );\n };\n\n updateSideRoom();\n if (typeof ResizeObserver === \"undefined\") return;\n const resizeObserver = new ResizeObserver(updateSideRoom);\n resizeObserver.observe(root);\n const content = layout?.contentElement;\n if (content) {\n resizeObserver.observe(content);\n }\n return () => resizeObserver.disconnect();\n }, [\n contentMaxWidth,\n layout?.contentElement,\n layout?.rootElement,\n minContainerWidthForRail,\n minSideGutterForRail,\n railSide,\n ]);\n\n if (items.length < 2) {\n return null;\n }\n\n return (\n <nav\n ref={navRef}\n aria-label=\"Transcript outline\"\n data-side={railSide}\n data-visible={hasSideRoom ? \"\" : undefined}\n className={cx(\n \"a24-outline pointer-events-none absolute z-10 max-h-[min(18rem,calc(100%-10rem))] w-16 overflow-visible\",\n hasSideRoom ? \"hidden md:block\" : \"hidden\",\n railSide === \"left\" ? \"left-1\" : \"right-1\",\n className\n )}\n dir={dir}\n style={{\n top: \"50%\",\n transform: `translateY(calc(-50% - ${verticalOffset}))`,\n }}\n >\n <div className=\"a24-outline__rail pointer-events-auto flex flex-col gap-0 py-1\">\n {items.map((item, index) => {\n const itemMessageIds =\n item.messageIds && item.messageIds.length > 0\n ? item.messageIds\n : [item.id];\n const active = itemMessageIds.some(\n (messageId) =>\n visibleMessageIdSet.has(messageId) || messageId === currentAnchorId\n );\n const distance =\n focusIndex >= 0 ? Math.abs(index - focusIndex) : Number.POSITIVE_INFINITY;\n const isFocused = distance === 0;\n const isNear = distance === 1;\n const isNextNear = distance === 2;\n const barWidth = isFocused\n ? 50\n : isNear\n ? 36\n : isNextNear\n ? 23\n : 10;\n const barTone = focusIndex < 0\n ? active ? 80 : 18\n : isFocused ? 80 : isNear ? 32 : isNextNear ? 24 : 16;\n const fallbackLabel = `Turn ${index + 1}`;\n const previewLabel =\n item.label && item.label !== fallbackLabel ? item.label : \"\";\n const responsePreview = (item.responsePreview || \"\").trim();\n\n return (\n <button\n key={item.id}\n type=\"button\"\n data-active={active}\n data-side={railSide}\n dir=\"ltr\"\n className={cx(\n \"a24-outline__button group relative flex h-2 w-16 items-center rounded-sm outline-none\",\n railSide === \"left\" ? \"justify-start\" : \"justify-end\"\n )}\n aria-label={`Jump to ${item.label || fallbackLabel}`}\n onBlur={() => setHoveredIndex(null)}\n onFocus={() => setHoveredIndex(index)}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(null)}\n onClick={() =>\n scrollToMessage(item.id, {\n align: \"start\",\n behavior: \"smooth\",\n })\n }\n >\n <span\n className=\"a24-outline__bar h-0.5 rounded-full transition-[width,background-color] duration-150 ease-out\"\n style={{\n backgroundColor: `color-mix(in oklch, var(--a24-text) ${barTone}%, transparent)`,\n width: barWidth,\n }}\n />\n {previewLabel ? (\n <span\n dir={dir}\n className={cx(\n \"a24-outline__preview pointer-events-none absolute top-1/2 z-20 max-h-32 w-64 -translate-y-1/2 overflow-hidden rounded-lg border border-border/80 bg-background p-3 text-start opacity-0 shadow-lg transition-[opacity,transform] duration-200 group-hover:pointer-events-auto group-hover:opacity-100 group-focus-visible:pointer-events-auto group-focus-visible:opacity-100\",\n railSide === \"left\"\n ? \"left-full ml-2 -translate-x-1 group-hover:translate-x-0 group-focus-visible:translate-x-0\"\n : \"right-full mr-2 translate-x-1 group-hover:translate-x-0 group-focus-visible:translate-x-0\",\n cardClassName\n )}\n >\n <span\n className=\"block overflow-hidden text-sm leading-5 text-foreground\"\n style={{\n display: \"-webkit-box\",\n WebkitBoxOrient: \"vertical\",\n WebkitLineClamp: responsePreview ? 2 : 4,\n }}\n >\n {previewLabel}\n </span>\n {responsePreview ? (\n <span\n className=\"mt-1 block overflow-hidden text-sm leading-5 text-muted-foreground\"\n style={{\n display: \"-webkit-box\",\n WebkitBoxOrient: \"vertical\",\n WebkitLineClamp: 2,\n }}\n >\n {responsePreview}\n </span>\n ) : null}\n </span>\n ) : null}\n </button>\n );\n })}\n </div>\n </nav>\n );\n}\n\nexport const LatestThreadScroller = {\n Provider: LatestThreadScrollerProvider,\n Root: LatestThreadScrollerRoot,\n Viewport: LatestThreadScrollerViewport,\n Content: LatestThreadScrollerContent,\n Item: LatestThreadScrollerItem,\n Button: LatestThreadScrollerButton,\n Outline: LatestThreadScrollerOutline,\n};\n","import type { McpCallbackResult } from \"@agents24/client\";\nimport type { ChatMcpOauthCompletion, WaitForMcpOauthCompleteInput } from \"./types\";\n\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\ntype CryptoLike = {\n getRandomValues<T extends Uint8Array>(array: T): T;\n randomUUID(): string;\n subtle: { digest(algorithm: string, data: Uint8Array): Promise<ArrayBuffer> };\n};\n\nexport function browserChatCrypto(): CryptoLike {\n const value = (globalThis as unknown as { crypto?: CryptoLike }).crypto;\n if (!value?.subtle || !value.randomUUID) {\n throw new Error(\"Secure browser crypto is required for MCP authorization.\");\n }\n return value;\n}\n\nfunction base64Url(bytes: Uint8Array): string {\n let binary = \"\";\n bytes.forEach((byte) => { binary += String.fromCharCode(byte); });\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/g, \"\");\n}\n\nexport async function createMcpPkceProof(): Promise<{ challenge: string; verifier: string }> {\n const crypto = browserChatCrypto();\n const verifier = base64Url(crypto.getRandomValues(new Uint8Array(32)));\n const digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(verifier));\n return { challenge: base64Url(new Uint8Array(digest)), verifier };\n}\n\nfunction isLoopback(hostname: string): boolean {\n return hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"[::1]\";\n}\n\nfunction normalizedOrigin(value: string): string {\n try {\n const url = new URL(value);\n if (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && isLoopback(url.hostname))) {\n throw new Error(\"unsafe callback origin\");\n }\n if (url.origin === \"null\") throw new Error(\"opaque callback origin\");\n return url.origin;\n } catch {\n throw new Error(\"MCP authorization returned an invalid callback origin.\");\n }\n}\n\nexport function validateMcpCallbackResult(\n result: McpCallbackResult,\n expectedServerId: string,\n): McpCallbackResult {\n const serverId = String(result.server_id || \"\").trim();\n const connectionId = String(result.connection_id || \"\").trim();\n if (!serverId || serverId !== expectedServerId) {\n throw new Error(\"MCP authorization completed for an unexpected server.\");\n }\n if (!UUID_PATTERN.test(connectionId)) {\n throw new Error(\"MCP authorization returned an invalid connection identity.\");\n }\n return result;\n}\n\nexport function waitForMcpOauthComplete({\n popup,\n callbackOrigin,\n popupNonce,\n requireConnectionId = false,\n serverId,\n timeoutMs = 120_000,\n}: WaitForMcpOauthCompleteInput): Promise<ChatMcpOauthCompletion> {\n if (!popup) return Promise.reject(new Error(\"Could not open the MCP authorization popup.\"));\n const expectedOrigin = normalizedOrigin(callbackOrigin);\n const expectedServerId = String(serverId || \"\").trim();\n const expectedPopupNonce = String(popupNonce || \"\").trim();\n if (!expectedServerId) return Promise.reject(new Error(\"MCP authorization is missing its server identity.\"));\n if (!expectedPopupNonce) return Promise.reject(new Error(\"MCP authorization is missing its popup binding.\"));\n const returnFocusTo = typeof document !== \"undefined\"\n ? document.activeElement as { focus?: () => void } | null\n : null;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const finish = (result: ChatMcpOauthCompletion | Error) => {\n if (settled) return;\n settled = true;\n window.clearTimeout(timeout);\n window.clearInterval(closeTimer);\n window.removeEventListener(\"message\", onMessage);\n returnFocusTo?.focus?.();\n if (result instanceof Error) reject(result);\n else resolve(result);\n };\n const onMessage = (event: MessageEvent) => {\n if (event.source !== popup || event.origin !== expectedOrigin) return;\n const data = event.data as {\n type?: string;\n code?: string;\n connection_id?: string;\n popup_nonce?: string;\n server_id?: string;\n } | null;\n if (\n data?.type !== \"agents24.mcp.callback\" ||\n data.server_id !== expectedServerId ||\n data.popup_nonce !== expectedPopupNonce\n ) return;\n const code = String(data.code || \"\").trim();\n if (!code || code.length > 2048) return;\n const connectionId = String(data.connection_id || \"\").trim();\n if ((requireConnectionId || connectionId) && !UUID_PATTERN.test(connectionId)) return;\n finish({\n code,\n ...(connectionId ? { connectionId } : {}),\n popupNonce: expectedPopupNonce,\n serverId: expectedServerId,\n });\n };\n const timeout = window.setTimeout(\n () => finish(new Error(\"MCP authorization timed out.\")),\n Math.max(1, timeoutMs),\n );\n const closeTimer = window.setInterval(() => {\n if (popup.closed) finish(new Error(\"MCP authorization window was closed before connecting.\"));\n }, 500);\n window.addEventListener(\"message\", onMessage);\n });\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nimport type { ChatMessage, ChatPart } from \"./types\";\n\nexport type StreamingTextMode = \"streaming\" | \"static\";\n\nexport type StreamingTextCache = {\n get: (id: string) => string | undefined;\n set: (id: string, text: string) => void;\n};\n\nexport type UseStreamingTextOptions = {\n id: string;\n isStreaming: boolean;\n text: string;\n cache?: StreamingTextCache | false;\n charsPerSecond?: number;\n catchupThreshold?: number;\n maxCatchupChars?: number;\n};\n\nexport type UseStreamingTextResult = {\n displayedText: string;\n isAnimating: boolean;\n mode: StreamingTextMode;\n parseIncompleteMarkdown: boolean;\n};\n\nconst DEFAULT_COMPLETED_TEXT_CACHE_SIZE = 200;\nconst STREAM_RUNWAY_MS = 80;\nconst STREAM_IDLE_RELEASE_MS = 120;\nconst defaultCompletedTextCache = new Map<string, string>();\n\nconst defaultStreamingTextCache: StreamingTextCache = {\n get: (id) => defaultCompletedTextCache.get(id),\n set: (id, text) => {\n defaultCompletedTextCache.set(id, text);\n if (defaultCompletedTextCache.size > DEFAULT_COMPLETED_TEXT_CACHE_SIZE) {\n const firstKey = defaultCompletedTextCache.keys().next().value;\n if (firstKey) defaultCompletedTextCache.delete(firstKey);\n }\n },\n};\n\nexport const getActiveStreamingTextPartId = (\n message: ChatMessage,\n streamingMessageId: string | null\n) => {\n if (message.role !== \"assistant\" || message.responseCompletion || streamingMessageId !== message.id) return null;\n const trailingPart = message.parts[message.parts.length - 1];\n return trailingPart?.kind === \"text\" ? trailingPart.id : null;\n};\n\nexport const isActiveStreamingTextPart = (\n message: ChatMessage,\n part: ChatPart,\n streamingMessageId: string | null\n) => part.kind === \"text\" && part.id === getActiveStreamingTextPartId(message, streamingMessageId);\n\nconst graphemeEndOffsets = (value: string): number[] => {\n if (!value) return [];\n\n if (typeof Intl !== \"undefined\" && \"Segmenter\" in Intl) {\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n return Array.from(segmenter.segment(value), ({ index, segment }) => index + segment.length);\n }\n\n const characters = Array.from(value);\n const offsets: number[] = [];\n let offset = 0;\n let regionalIndicators = 0;\n characters.forEach((character, index) => {\n const previous = characters[index - 1];\n const codePoint = character.codePointAt(0) ?? 0;\n const isRegionalIndicator = codePoint >= 0x1f1e6 && codePoint <= 0x1f1ff;\n const continuesCluster =\n index > 0 &&\n (/^\\p{Mark}$/u.test(character) ||\n (codePoint >= 0xfe00 && codePoint <= 0xfe0f) ||\n (codePoint >= 0x1f3fb && codePoint <= 0x1f3ff) ||\n character === \"\\u200d\" ||\n previous === \"\\u200d\" ||\n (isRegionalIndicator && regionalIndicators % 2 === 1));\n if (!continuesCluster) {\n if (offset > 0) offsets.push(offset);\n regionalIndicators = 0;\n }\n offset += character.length;\n regionalIndicators = isRegionalIndicator ? regionalIndicators + 1 : 0;\n });\n offsets.push(offset);\n return offsets;\n};\n\nexport function useStreamingText({\n id,\n isStreaming,\n text,\n cache = defaultStreamingTextCache,\n charsPerSecond = 72,\n catchupThreshold = 40,\n maxCatchupChars = 20,\n}: UseStreamingTextOptions): UseStreamingTextResult {\n const cacheAdapter = cache === false ? null : cache;\n const [displayedText, setDisplayedText] = useState(() => {\n const cachedText = cacheAdapter?.get(id);\n return cachedText && text.startsWith(cachedText) ? cachedText : text;\n });\n const targetRef = useRef(text);\n const displayedRef = useRef(displayedText);\n const rafRef = useRef<number | null>(null);\n const lastFrameAtRef = useRef<number | null>(null);\n const targetUpdatedAtRef = useRef<number | null>(null);\n const progressRemainderRef = useRef(0);\n const idRef = useRef(id);\n const streamingRef = useRef(isStreaming);\n const reduceMotionRef = useRef(false);\n\n useEffect(() => {\n if (isStreaming || !text) return;\n cacheAdapter?.set(id, text);\n }, [cacheAdapter, id, isStreaming, text]);\n\n useEffect(() => {\n targetRef.current = text;\n targetUpdatedAtRef.current =\n typeof performance === \"undefined\" ? null : performance.now();\n\n if (\n !isStreaming ||\n reduceMotionRef.current ||\n !text.startsWith(displayedRef.current)\n ) {\n displayedRef.current = text;\n setDisplayedText(text);\n progressRemainderRef.current = 0;\n }\n }, [isStreaming, text]);\n\n useEffect(() => {\n if (idRef.current === id) return;\n\n idRef.current = id;\n const cachedText = cacheAdapter?.get(id);\n const initial = cachedText && text.startsWith(cachedText) ? cachedText : text;\n displayedRef.current = initial;\n setDisplayedText(initial);\n lastFrameAtRef.current = null;\n targetUpdatedAtRef.current =\n typeof performance === \"undefined\" ? null : performance.now();\n progressRemainderRef.current = 0;\n }, [cacheAdapter, id, isStreaming, text]);\n\n useEffect(() => {\n streamingRef.current = isStreaming;\n\n if (typeof window === \"undefined\") {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n const reduceMotion =\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n reduceMotionRef.current = reduceMotion;\n\n if (reduceMotion || !isStreaming) {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n const cachedText = cacheAdapter?.get(id);\n if (cachedText === text) {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n if (!text.startsWith(displayedRef.current)) {\n displayedRef.current = text;\n setDisplayedText(text);\n }\n\n const tick = (timestamp: number) => {\n const previousTimestamp = lastFrameAtRef.current ?? timestamp;\n lastFrameAtRef.current = timestamp;\n\n const target = targetRef.current;\n const current = displayedRef.current;\n\n if (!streamingRef.current || reduceMotionRef.current) {\n displayedRef.current = target;\n setDisplayedText(target);\n rafRef.current = null;\n return;\n }\n\n if (!target.startsWith(current)) {\n displayedRef.current = target;\n setDisplayedText(target);\n progressRemainderRef.current = 0;\n rafRef.current = window.requestAnimationFrame(tick);\n return;\n }\n\n const pending = target.slice(current.length);\n const pendingOffsets = graphemeEndOffsets(pending);\n if (pendingOffsets.length === 0) {\n rafRef.current = window.requestAnimationFrame(tick);\n return;\n }\n\n const elapsedMs = Math.max(0, timestamp - previousTimestamp);\n const targetIdleMs =\n targetUpdatedAtRef.current === null\n ? STREAM_IDLE_RELEASE_MS\n : Math.max(0, timestamp - targetUpdatedAtRef.current);\n const runway =\n targetIdleMs >= STREAM_IDLE_RELEASE_MS\n ? 0\n : Math.min(\n pendingOffsets.length - 1,\n Math.max(1, Math.ceil((charsPerSecond * STREAM_RUNWAY_MS) / 1000))\n );\n const eligibleGraphemes = pendingOffsets.length - runway;\n\n progressRemainderRef.current += (elapsedMs / 1000) * charsPerSecond;\n let step = Math.floor(progressRemainderRef.current);\n if (current.length === 0 && eligibleGraphemes > 0) step = Math.max(1, step);\n\n const catchupStep =\n pendingOffsets.length > catchupThreshold\n ? Math.min(maxCatchupChars, Math.ceil(pendingOffsets.length / 10))\n : 0;\n step = Math.min(eligibleGraphemes, Math.max(step, catchupStep));\n\n if (step > 0) {\n progressRemainderRef.current = Math.max(0, progressRemainderRef.current - step);\n const next = current + pending.slice(0, pendingOffsets[step - 1]);\n displayedRef.current = next;\n setDisplayedText(next);\n }\n rafRef.current = window.requestAnimationFrame(tick);\n };\n\n if (rafRef.current === null) {\n rafRef.current = window.requestAnimationFrame(tick);\n }\n\n return () => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n lastFrameAtRef.current = null;\n progressRemainderRef.current = 0;\n };\n }, [cacheAdapter, catchupThreshold, charsPerSecond, id, isStreaming, maxCatchupChars]);\n\n const reduceMotion =\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n return {\n displayedText: !isStreaming || reduceMotion ? text : displayedText,\n isAnimating: isStreaming,\n mode: isStreaming ? \"streaming\" : \"static\",\n parseIncompleteMarkdown: isStreaming,\n };\n}\n","export {\n MessageScroller,\n useMessageScroller,\n useMessageScrollerScrollable,\n useMessageScrollerVisibility,\n} from \"@shadcn/react/message-scroller\";\nexport type {\n MessageScrollerDefaultScrollPosition,\n MessageScrollerScrollAlign,\n MessageScrollerScrollable,\n MessageScrollerScrollOptions,\n MessageScrollerVisibilityState,\n} from \"@shadcn/react/message-scroller\";\n"],"mappings":"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","names":["content","reduceMotion","import_message_scroller"]}
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  getActiveStreamingTextPartId,
3
3
  isActiveStreamingTextPart,
4
4
  useStreamingText
5
- } from "./chunk-SSUO4EPD.js";
5
+ } from "./chunk-5PWUQTLK.js";
6
6
  import {
7
7
  browserChatCrypto,
8
8
  createMcpPkceProof,
package/dist/ui/index.cjs CHANGED
@@ -1443,7 +1443,7 @@ var defaultStreamingTextCache = {
1443
1443
  }
1444
1444
  };
1445
1445
  var getActiveStreamingTextPartId = (message, streamingMessageId) => {
1446
- if (message.role !== "assistant" || streamingMessageId !== message.id) return null;
1446
+ if (message.role !== "assistant" || message.responseCompletion || streamingMessageId !== message.id) return null;
1447
1447
  const trailingPart = message.parts[message.parts.length - 1];
1448
1448
  return trailingPart?.kind === "text" ? trailingPart.id : null;
1449
1449
  };
@@ -2796,6 +2796,7 @@ function AgentResponseTimeline({
2796
2796
  toolSlots,
2797
2797
  toolViewMode = "closed"
2798
2798
  }) {
2799
+ isLoading = isLoading && !message.responseCompletion;
2799
2800
  const parts = (displayParts || message.parts || []).filter((part) => (part.kind !== "tool" || !isInternalAskUserTool(part)) && (part.kind !== "model-turn" || part.turnKind === "agent") && (part.kind !== "node-activity" || nodeActivityMode === "all" || nodeActivityMode === "default" && part.defaultChatVisible));
2800
2801
  const toolParts = parts.filter((part) => part.kind === "tool");
2801
2802
  const activeToolId = latestRunningAgentChatToolId(toolParts);
@@ -2971,7 +2972,7 @@ function AgentChatMessage({
2971
2972
  userMessageShowMoreLabel
2972
2973
  }) {
2973
2974
  const isAssistant = message.role === "assistant";
2974
- const isStreaming = isAssistant && message.id === streamingMessageId;
2975
+ const isStreaming = isAssistant && message.id === streamingMessageId && !message.responseCompletion;
2975
2976
  const resolvedUserContent = userMessageContent ?? message.content;
2976
2977
  const shouldRenderContent = isAssistant || Boolean(renderUserContent || resolvedUserContent);
2977
2978
  const showAttachments = Boolean(message.attachments?.length) && (message.role === "user" || showAssistantAttachments);