@agents24/chat-react 0.1.7 → 0.1.8

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.
Files changed (42) hide show
  1. package/README.md +25 -12
  2. package/dist/chunk-E3TJ3I6G.js +358 -0
  3. package/dist/chunk-E3TJ3I6G.js.map +1 -0
  4. package/dist/chunk-EWZO4QJI.js +140 -0
  5. package/dist/chunk-EWZO4QJI.js.map +1 -0
  6. package/dist/chunk-UU7OXHL3.js +11 -0
  7. package/dist/chunk-UU7OXHL3.js.map +1 -0
  8. package/dist/context-window.d.ts +38 -0
  9. package/dist/controller.d.ts +22 -0
  10. package/dist/index.cjs +392 -314
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.ts +10 -530
  13. package/dist/index.js +41 -439
  14. package/dist/index.js.map +1 -1
  15. package/dist/latest-thread-scroller.d.ts +54 -0
  16. package/dist/model.d.ts +29 -0
  17. package/dist/renderers.d.ts +10 -0
  18. package/dist/sse.d.ts +3 -0
  19. package/dist/streaming-text.d.ts +24 -0
  20. package/dist/templates/agent-chat-shell.d.ts +25 -0
  21. package/dist/templates/index.cjs +523 -0
  22. package/dist/templates/index.cjs.map +1 -0
  23. package/dist/templates/index.d.ts +1 -0
  24. package/dist/templates/index.js +140 -0
  25. package/dist/templates/index.js.map +1 -0
  26. package/dist/transport.d.ts +29 -0
  27. package/dist/types.d.ts +312 -0
  28. package/dist/ui/adapters.d.ts +36 -0
  29. package/dist/ui/attachment.d.ts +23 -0
  30. package/dist/ui/bubble.d.ts +17 -0
  31. package/dist/ui/index.cjs +943 -0
  32. package/dist/ui/index.cjs.map +1 -0
  33. package/dist/ui/index.d.ts +7 -0
  34. package/dist/ui/index.js +734 -0
  35. package/dist/ui/index.js.map +1 -0
  36. package/dist/ui/marker.d.ts +11 -0
  37. package/dist/ui/message-response.d.ts +7 -0
  38. package/dist/ui/message.d.ts +10 -0
  39. package/dist/ui/utils.d.ts +2 -0
  40. package/dist/viewport.d.ts +2 -0
  41. package/package.json +22 -4
  42. package/dist/index.d.cts +0 -530
package/dist/index.js CHANGED
@@ -1,3 +1,19 @@
1
+ import {
2
+ LatestThreadScroller,
3
+ LatestThreadScrollerButton,
4
+ LatestThreadScrollerContent,
5
+ LatestThreadScrollerItem,
6
+ LatestThreadScrollerOutline,
7
+ LatestThreadScrollerProvider,
8
+ LatestThreadScrollerRoot,
9
+ LatestThreadScrollerViewport
10
+ } from "./chunk-E3TJ3I6G.js";
11
+ import {
12
+ getActiveStreamingTextPartId,
13
+ isActiveStreamingTextPart,
14
+ useStreamingText
15
+ } from "./chunk-EWZO4QJI.js";
16
+
1
17
  // src/controller.ts
2
18
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
19
 
@@ -23,16 +39,16 @@ var STAGE_PRIORITY = {
23
39
  function numberOrNull(value) {
24
40
  return typeof value === "number" && Number.isFinite(value) ? value : null;
25
41
  }
26
- function stagePriority(window2) {
27
- return STAGE_PRIORITY[window2?.stage || "sent_prompt"] ?? STAGE_PRIORITY.sent_prompt;
42
+ function stagePriority(window) {
43
+ return STAGE_PRIORITY[window?.stage || "sent_prompt"] ?? STAGE_PRIORITY.sent_prompt;
28
44
  }
29
- function hasRenderableContextWindow(window2) {
30
- const maxTokens = window2?.max_tokens;
45
+ function hasRenderableContextWindow(window) {
46
+ const maxTokens = window?.max_tokens;
31
47
  return typeof maxTokens === "number" && Number.isFinite(maxTokens) && maxTokens > 0;
32
48
  }
33
- function windowWeight(window2) {
34
- if (!window2) return [0, 0];
35
- return [stagePriority(window2), SOURCE_PRIORITY[window2.source] || 0];
49
+ function windowWeight(window) {
50
+ if (!window) return [0, 0];
51
+ return [stagePriority(window), SOURCE_PRIORITY[window.source] || 0];
36
52
  }
37
53
  function normalizeContextCompression(value) {
38
54
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
@@ -1249,140 +1265,6 @@ var consumeSseResponse = async (response, onEvent) => {
1249
1265
  return { threadId, runId };
1250
1266
  };
1251
1267
 
1252
- // src/streaming-text.ts
1253
- import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
1254
- var DEFAULT_COMPLETED_TEXT_CACHE_SIZE = 200;
1255
- var defaultCompletedTextCache = /* @__PURE__ */ new Map();
1256
- var defaultStreamingTextCache = {
1257
- get: (id) => defaultCompletedTextCache.get(id),
1258
- set: (id, text) => {
1259
- defaultCompletedTextCache.set(id, text);
1260
- if (defaultCompletedTextCache.size > DEFAULT_COMPLETED_TEXT_CACHE_SIZE) {
1261
- const firstKey = defaultCompletedTextCache.keys().next().value;
1262
- if (firstKey) defaultCompletedTextCache.delete(firstKey);
1263
- }
1264
- }
1265
- };
1266
- var getActiveStreamingTextPartId = (message, streamingMessageId) => {
1267
- if (message.role !== "assistant" || streamingMessageId !== message.id) return null;
1268
- return message.parts.slice().reverse().find((part) => part.kind === "text")?.id || null;
1269
- };
1270
- var isActiveStreamingTextPart = (message, part, streamingMessageId) => part.kind === "text" && part.id === getActiveStreamingTextPartId(message, streamingMessageId);
1271
- function useStreamingText({
1272
- id,
1273
- isStreaming,
1274
- text,
1275
- cache = defaultStreamingTextCache,
1276
- charsPerSecond = 72,
1277
- catchupThreshold = 40,
1278
- maxCatchupChars = 20
1279
- }) {
1280
- const cacheAdapter = cache === false ? null : cache;
1281
- const [displayedText, setDisplayedText] = useState2(() => {
1282
- const cachedText = cacheAdapter?.get(id);
1283
- return isStreaming && cachedText !== text ? "" : text;
1284
- });
1285
- const targetRef = useRef2(text);
1286
- const displayedRef = useRef2(displayedText);
1287
- const rafRef = useRef2(null);
1288
- const lastFrameAtRef = useRef2(null);
1289
- const idRef = useRef2(id);
1290
- const shouldAnimateRef = useRef2(isStreaming);
1291
- useEffect2(() => {
1292
- if (isStreaming || !text) return;
1293
- cacheAdapter?.set(id, text);
1294
- }, [cacheAdapter, id, isStreaming, text]);
1295
- useEffect2(() => {
1296
- targetRef.current = text;
1297
- }, [text]);
1298
- useEffect2(() => {
1299
- if (idRef.current === id) return;
1300
- idRef.current = id;
1301
- const cachedText = cacheAdapter?.get(id);
1302
- const initial = isStreaming && cachedText !== text ? "" : text;
1303
- shouldAnimateRef.current = isStreaming && initial !== text;
1304
- displayedRef.current = initial;
1305
- setDisplayedText(initial);
1306
- if (rafRef.current !== null) {
1307
- cancelAnimationFrame(rafRef.current);
1308
- rafRef.current = null;
1309
- }
1310
- lastFrameAtRef.current = null;
1311
- }, [cacheAdapter, id, isStreaming, text]);
1312
- useEffect2(() => {
1313
- if (typeof window === "undefined") {
1314
- displayedRef.current = text;
1315
- setDisplayedText(text);
1316
- return;
1317
- }
1318
- const reduceMotion = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1319
- if (reduceMotion) {
1320
- displayedRef.current = text;
1321
- setDisplayedText(text);
1322
- shouldAnimateRef.current = false;
1323
- return;
1324
- }
1325
- const cachedText = cacheAdapter?.get(id);
1326
- if (cachedText === text) {
1327
- displayedRef.current = text;
1328
- setDisplayedText(text);
1329
- shouldAnimateRef.current = false;
1330
- return;
1331
- }
1332
- if (isStreaming) {
1333
- shouldAnimateRef.current = true;
1334
- }
1335
- if (!shouldAnimateRef.current) {
1336
- displayedRef.current = text;
1337
- setDisplayedText(text);
1338
- return;
1339
- }
1340
- if (!text.startsWith(displayedRef.current)) {
1341
- displayedRef.current = "";
1342
- setDisplayedText("");
1343
- }
1344
- const tick = (timestamp) => {
1345
- const previousTimestamp = lastFrameAtRef.current ?? timestamp;
1346
- lastFrameAtRef.current = timestamp;
1347
- const target = targetRef.current;
1348
- const current = displayedRef.current;
1349
- if (current.length >= target.length) {
1350
- shouldAnimateRef.current = false;
1351
- rafRef.current = null;
1352
- return;
1353
- }
1354
- const elapsedMs = Math.max(8, timestamp - previousTimestamp);
1355
- const charsFromTime = Math.max(1, Math.floor(elapsedMs / 1e3 * charsPerSecond));
1356
- const gap = target.length - current.length;
1357
- const catchupStep = gap > catchupThreshold ? Math.min(maxCatchupChars, Math.ceil(gap / 10)) : charsFromTime;
1358
- const nextLength = Math.min(
1359
- target.length,
1360
- current.length + Math.max(charsFromTime, catchupStep)
1361
- );
1362
- const next = target.slice(0, nextLength);
1363
- displayedRef.current = next;
1364
- setDisplayedText(next);
1365
- rafRef.current = window.requestAnimationFrame(tick);
1366
- };
1367
- if (rafRef.current === null && displayedRef.current.length < text.length) {
1368
- rafRef.current = window.requestAnimationFrame(tick);
1369
- }
1370
- return () => {
1371
- if (rafRef.current !== null) {
1372
- cancelAnimationFrame(rafRef.current);
1373
- rafRef.current = null;
1374
- }
1375
- lastFrameAtRef.current = null;
1376
- };
1377
- }, [cacheAdapter, catchupThreshold, charsPerSecond, id, isStreaming, maxCatchupChars, text]);
1378
- return {
1379
- displayedText,
1380
- isAnimating: isStreaming,
1381
- mode: isStreaming ? "streaming" : "static",
1382
- parseIncompleteMarkdown: isStreaming
1383
- };
1384
- }
1385
-
1386
1268
  // src/transport.ts
1387
1269
  var jsonHeaders = (headers) => ({
1388
1270
  ...headers || {},
@@ -1463,301 +1345,26 @@ var createFetchChatTransport = ({
1463
1345
  };
1464
1346
  };
1465
1347
 
1466
- // src/viewport.tsx
1348
+ // src/viewport.ts
1467
1349
  import {
1468
- useCallback as useCallback2,
1469
- useEffect as useEffect3,
1470
- useLayoutEffect,
1471
- useMemo as useMemo2,
1472
- useRef as useRef3,
1473
- useState as useState3
1474
- } from "react";
1475
- import { jsxs as jsxs2 } from "react/jsx-runtime";
1476
- var LATEST_EDGE_THRESHOLD_PX = 2;
1477
- var MIN_OLDER_PREFETCH_PX = 320;
1478
- var MAX_OLDER_PREFETCH_PX = 900;
1479
- var isScrollable = (element) => element.scrollHeight - element.clientHeight > LATEST_EDGE_THRESHOLD_PX;
1480
- var isAtTimelineLatestEdge = (element, isTopOrigin) => {
1481
- if (!isScrollable(element)) return true;
1482
- return isTopOrigin ? element.scrollHeight - element.clientHeight - element.scrollTop <= LATEST_EDGE_THRESHOLD_PX : Math.abs(element.scrollTop) <= LATEST_EDGE_THRESHOLD_PX;
1483
- };
1484
- var shouldPrefetchOlder = (element) => Math.abs(element.scrollTop) + element.clientHeight >= element.scrollHeight - Math.min(MAX_OLDER_PREFETCH_PX, Math.max(MIN_OLDER_PREFETCH_PX, element.clientHeight * 0.75));
1485
- var getLatestScrollTop = (element, isTopOrigin) => isTopOrigin ? Math.max(0, element.scrollHeight - element.clientHeight) : 0;
1486
- var shouldUseTopOriginTimeline = ({
1487
- hasOlder,
1488
- itemCount,
1489
- topOriginMaxItems = 4
1490
- }) => !hasOlder && itemCount > 0 && itemCount <= topOriginMaxItems;
1491
- var nextLatestFollowStateOnScroll = ({
1492
- atLatest,
1493
- current,
1494
- isProgrammatic
1495
- }) => {
1496
- if (isProgrammatic) return current;
1497
- return atLatest ? "following" : "detached";
1498
- };
1499
- var isUserScrollIntentAwayFromLatest = (intent) => {
1500
- if (!intent) return false;
1501
- if ("deltaY" in intent && typeof intent.deltaY === "number") {
1502
- return intent.deltaY < 0;
1503
- }
1504
- if ("key" in intent && typeof intent.key === "string") {
1505
- if (intent.key === "ArrowUp" || intent.key === "PageUp" || intent.key === "Home") return true;
1506
- if ((intent.key === " " || intent.key === "Spacebar") && intent.shiftKey) return true;
1507
- return false;
1508
- }
1509
- return "touches" in intent;
1510
- };
1511
- function useLatestThreadViewport({
1512
- itemCount,
1513
- hasOlder,
1514
- isLoadingOlder,
1515
- onLoadOlder,
1516
- activeStreamKey,
1517
- shouldAutoFollow = true,
1518
- topOriginMaxItems = 4
1519
- }) {
1520
- const scrollContainerRef = useRef3(null);
1521
- const olderPagePreserveRef = useRef3(null);
1522
- const olderPageRequestInFlightRef = useRef3(false);
1523
- const intrinsicResizePreserveRef = useRef3(null);
1524
- const followStateRef = useRef3("following");
1525
- const programmaticScrollRef = useRef3(false);
1526
- const programmaticScrollTimeoutRef = useRef3(null);
1527
- const activeStreamKeyRef = useRef3(null);
1528
- const observedScrollHeightRef = useRef3(null);
1529
- const [isAtLatest, setIsAtLatest] = useState3(true);
1530
- const [followState, setFollowState] = useState3("following");
1531
- const isTopOrigin = shouldUseTopOriginTimeline({ hasOlder, itemCount, topOriginMaxItems });
1532
- const setLatestFollowState = useCallback2((next) => {
1533
- if (followStateRef.current === next) return;
1534
- followStateRef.current = next;
1535
- setFollowState(next);
1536
- }, []);
1537
- const markProgrammaticScroll = useCallback2(() => {
1538
- programmaticScrollRef.current = true;
1539
- if (programmaticScrollTimeoutRef.current) clearTimeout(programmaticScrollTimeoutRef.current);
1540
- programmaticScrollTimeoutRef.current = setTimeout(() => {
1541
- programmaticScrollRef.current = false;
1542
- programmaticScrollTimeoutRef.current = null;
1543
- }, 80);
1544
- }, []);
1545
- const scrollToLatest = useCallback2((options) => {
1546
- const element = scrollContainerRef.current;
1547
- if (!element) return;
1548
- if (options?.reattach !== false) setLatestFollowState("following");
1549
- markProgrammaticScroll();
1550
- element.scrollTop = getLatestScrollTop(element, isTopOrigin);
1551
- setIsAtLatest(true);
1552
- observedScrollHeightRef.current = element.scrollHeight;
1553
- }, [isTopOrigin, markProgrammaticScroll, setLatestFollowState]);
1554
- const detachFromLatest = useCallback2(() => {
1555
- setLatestFollowState("detached");
1556
- }, [setLatestFollowState]);
1557
- const reattachToLatest = useCallback2(() => {
1558
- scrollToLatest({ reattach: true });
1559
- }, [scrollToLatest]);
1560
- const handleUserScrollIntent = useCallback2((intent) => {
1561
- const element = scrollContainerRef.current;
1562
- if (!activeStreamKey || !element) return;
1563
- const atLatest = isAtTimelineLatestEdge(element, isTopOrigin);
1564
- if (!atLatest || isUserScrollIntentAwayFromLatest(intent)) detachFromLatest();
1565
- }, [activeStreamKey, detachFromLatest, isTopOrigin]);
1566
- useEffect3(() => {
1567
- return () => {
1568
- if (programmaticScrollTimeoutRef.current) clearTimeout(programmaticScrollTimeoutRef.current);
1569
- const preserve = intrinsicResizePreserveRef.current;
1570
- if (preserve?.frame !== null && preserve?.frame !== void 0) cancelAnimationFrame(preserve.frame);
1571
- };
1572
- }, []);
1573
- useLayoutEffect(() => {
1574
- const element = scrollContainerRef.current;
1575
- const preserve = olderPagePreserveRef.current;
1576
- if (!element) return;
1577
- observedScrollHeightRef.current = element.scrollHeight;
1578
- if (!preserve) {
1579
- setIsAtLatest(isAtTimelineLatestEdge(element, isTopOrigin));
1580
- return;
1581
- }
1582
- const addedHeight = element.scrollHeight - preserve.previousHeight;
1583
- markProgrammaticScroll();
1584
- element.scrollTop = preserve.previousTop - addedHeight;
1585
- olderPagePreserveRef.current = null;
1586
- olderPageRequestInFlightRef.current = false;
1587
- setIsAtLatest(isAtTimelineLatestEdge(element, isTopOrigin));
1588
- }, [isTopOrigin, itemCount, markProgrammaticScroll]);
1589
- const handleScroll = useCallback2(
1590
- (event) => {
1591
- const element = event.currentTarget;
1592
- const atLatest = isAtTimelineLatestEdge(element, isTopOrigin);
1593
- setIsAtLatest(atLatest);
1594
- setLatestFollowState(
1595
- nextLatestFollowStateOnScroll({
1596
- atLatest,
1597
- current: followStateRef.current,
1598
- isProgrammatic: programmaticScrollRef.current
1599
- })
1600
- );
1601
- if (isTopOrigin || !hasOlder || isLoadingOlder || olderPageRequestInFlightRef.current || !shouldPrefetchOlder(element)) {
1602
- return;
1603
- }
1604
- olderPageRequestInFlightRef.current = true;
1605
- olderPagePreserveRef.current = {
1606
- previousHeight: element.scrollHeight,
1607
- previousTop: element.scrollTop
1608
- };
1609
- void Promise.resolve(onLoadOlder()).finally(() => {
1610
- requestAnimationFrame(() => {
1611
- if (!olderPagePreserveRef.current) return;
1612
- olderPagePreserveRef.current = null;
1613
- olderPageRequestInFlightRef.current = false;
1614
- });
1615
- });
1616
- },
1617
- [hasOlder, isLoadingOlder, isTopOrigin, onLoadOlder, setLatestFollowState]
1618
- );
1619
- const preserveIntrinsicResize = useCallback2(() => {
1620
- const element = scrollContainerRef.current;
1621
- if (!element || isTopOrigin) return;
1622
- const active = intrinsicResizePreserveRef.current;
1623
- if (active?.frame !== null && active?.frame !== void 0) cancelAnimationFrame(active.frame);
1624
- intrinsicResizePreserveRef.current = {
1625
- lastHeight: element.scrollHeight,
1626
- endAt: Date.now() + 260,
1627
- frame: null
1628
- };
1629
- const preserveFrame = () => {
1630
- const nextElement = scrollContainerRef.current;
1631
- const preserve = intrinsicResizePreserveRef.current;
1632
- if (!nextElement || !preserve) return;
1633
- const heightDelta = nextElement.scrollHeight - preserve.lastHeight;
1634
- if (Math.abs(heightDelta) >= 1) {
1635
- markProgrammaticScroll();
1636
- nextElement.scrollTop -= heightDelta;
1637
- preserve.lastHeight = nextElement.scrollHeight;
1638
- setIsAtLatest(isAtTimelineLatestEdge(nextElement, isTopOrigin));
1639
- }
1640
- if (Date.now() < preserve.endAt) {
1641
- preserve.frame = requestAnimationFrame(preserveFrame);
1642
- } else {
1643
- intrinsicResizePreserveRef.current = null;
1644
- }
1645
- };
1646
- intrinsicResizePreserveRef.current.frame = requestAnimationFrame(preserveFrame);
1647
- }, [isTopOrigin, markProgrammaticScroll]);
1648
- useLayoutEffect(() => {
1649
- const key = activeStreamKey || null;
1650
- const previousKey = activeStreamKeyRef.current;
1651
- if (!key) {
1652
- activeStreamKeyRef.current = null;
1653
- if (previousKey && shouldAutoFollow && followStateRef.current === "following" && !isLoadingOlder && !olderPageRequestInFlightRef.current) {
1654
- const frame2 = requestAnimationFrame(() => {
1655
- if (followStateRef.current === "following" && !isLoadingOlder && !olderPageRequestInFlightRef.current) {
1656
- scrollToLatest({ reattach: false });
1657
- }
1658
- });
1659
- return () => cancelAnimationFrame(frame2);
1660
- }
1661
- return;
1662
- }
1663
- if (previousKey === key) {
1664
- activeStreamKeyRef.current = key;
1665
- return;
1666
- }
1667
- setLatestFollowState("following");
1668
- const frame = requestAnimationFrame(() => scrollToLatest());
1669
- activeStreamKeyRef.current = key;
1670
- return () => cancelAnimationFrame(frame);
1671
- }, [activeStreamKey, isLoadingOlder, scrollToLatest, setLatestFollowState, shouldAutoFollow]);
1672
- useLayoutEffect(() => {
1673
- if (!activeStreamKey || !shouldAutoFollow || followStateRef.current !== "following") return;
1674
- if (isLoadingOlder || olderPageRequestInFlightRef.current) return;
1675
- const frame = requestAnimationFrame(() => {
1676
- if (followStateRef.current === "following" && !isLoadingOlder && !olderPageRequestInFlightRef.current) {
1677
- scrollToLatest({ reattach: false });
1678
- }
1679
- });
1680
- return () => cancelAnimationFrame(frame);
1681
- }, [activeStreamKey, isLoadingOlder, itemCount, scrollToLatest, shouldAutoFollow]);
1682
- useEffect3(() => {
1683
- if (!activeStreamKey) {
1684
- observedScrollHeightRef.current = scrollContainerRef.current?.scrollHeight ?? null;
1685
- return;
1686
- }
1687
- let frame = null;
1688
- const watchStreamResize = () => {
1689
- const element = scrollContainerRef.current;
1690
- if (!element) return;
1691
- const previousHeight = observedScrollHeightRef.current;
1692
- const nextHeight = element.scrollHeight;
1693
- observedScrollHeightRef.current = nextHeight;
1694
- if (previousHeight !== null && Math.abs(nextHeight - previousHeight) >= 1 && shouldAutoFollow && followStateRef.current === "following" && !isLoadingOlder && !olderPageRequestInFlightRef.current) {
1695
- scrollToLatest({ reattach: false });
1696
- }
1697
- frame = requestAnimationFrame(watchStreamResize);
1698
- };
1699
- frame = requestAnimationFrame(watchStreamResize);
1700
- return () => {
1701
- if (frame !== null) cancelAnimationFrame(frame);
1702
- };
1703
- }, [activeStreamKey, isLoadingOlder, scrollToLatest, shouldAutoFollow]);
1704
- return {
1705
- scrollContainerRef,
1706
- isAtLatest,
1707
- isFollowingLatest: followState === "following",
1708
- isTopOrigin,
1709
- shouldShowLatestButton: !isAtLatest,
1710
- handleScroll,
1711
- handleUserScrollIntent,
1712
- scrollToLatest,
1713
- detachFromLatest,
1714
- reattachToLatest,
1715
- preserveIntrinsicResize
1716
- };
1717
- }
1718
- function LatestThreadViewport({
1719
- items,
1720
- hasOlder,
1721
- isLoadingOlder,
1722
- onLoadOlder,
1723
- activeStreamKey,
1724
- className,
1725
- latestSpacer,
1726
- trailingSpacer,
1727
- renderItem
1728
- }) {
1729
- const viewport = useLatestThreadViewport({
1730
- itemCount: items.length,
1731
- hasOlder,
1732
- isLoadingOlder,
1733
- onLoadOlder,
1734
- activeStreamKey
1735
- });
1736
- const timelineItems = useMemo2(() => viewport.isTopOrigin ? items : [...items].reverse(), [items, viewport.isTopOrigin]);
1737
- return /* @__PURE__ */ jsxs2(
1738
- "div",
1739
- {
1740
- ref: viewport.scrollContainerRef,
1741
- className,
1742
- onKeyDownCapture: viewport.handleUserScrollIntent,
1743
- onScroll: viewport.handleScroll,
1744
- onTouchMoveCapture: viewport.handleUserScrollIntent,
1745
- onWheelCapture: viewport.handleUserScrollIntent,
1746
- role: "log",
1747
- style: { overflowAnchor: "none" },
1748
- children: [
1749
- !viewport.isTopOrigin && (latestSpacer ?? null),
1750
- timelineItems.map((item) => renderItem(item, viewport)),
1751
- viewport.isTopOrigin && (trailingSpacer ?? latestSpacer ?? null)
1752
- ]
1753
- }
1754
- );
1755
- }
1350
+ MessageScroller,
1351
+ useMessageScroller,
1352
+ useMessageScrollerScrollable,
1353
+ useMessageScrollerVisibility
1354
+ } from "@shadcn/react/message-scroller";
1756
1355
  export {
1757
1356
  DEFAULT_THREAD_PAGE_SIZE,
1758
1357
  DefaultChatPart,
1759
1358
  DefaultToolPart,
1760
- LatestThreadViewport,
1359
+ LatestThreadScroller,
1360
+ LatestThreadScrollerButton,
1361
+ LatestThreadScrollerContent,
1362
+ LatestThreadScrollerItem,
1363
+ LatestThreadScrollerOutline,
1364
+ LatestThreadScrollerProvider,
1365
+ LatestThreadScrollerRoot,
1366
+ LatestThreadScrollerViewport,
1367
+ MessageScroller,
1761
1368
  activeRunIdFromThread,
1762
1369
  activeRunIdFromThreadDetail,
1763
1370
  assistantTextFromParts,
@@ -1767,27 +1374,20 @@ export {
1767
1374
  createChatId,
1768
1375
  createFetchChatTransport,
1769
1376
  getActiveStreamingTextPartId,
1770
- getLatestScrollTop,
1771
1377
  hasStaleUnfinishedAssistantCache,
1772
1378
  hasUnfinishedAssistantMessage,
1773
1379
  isActiveStreamingTextPart,
1774
- isAtTimelineLatestEdge,
1775
1380
  isRunningThreadStatus,
1776
- isScrollable,
1777
- isUserScrollIntentAwayFromLatest,
1778
1381
  latestContextWindowFromThread,
1779
1382
  mergeContextWindow,
1780
1383
  mergeContextWindowUpdate,
1781
1384
  mergeReasoningSteps,
1782
- nextLatestFollowStateOnScroll,
1783
1385
  normalizeContextCompression,
1784
1386
  normalizeContextWindow,
1785
1387
  parseSseBlock,
1786
1388
  partsFromResponseBlocks,
1787
1389
  reasoningStepsFromParts,
1788
1390
  renderChatPart,
1789
- shouldPrefetchOlder,
1790
- shouldUseTopOriginTimeline,
1791
1391
  textFromFinalOutput,
1792
1392
  threadActivityDate,
1793
1393
  threadDetailToMessages,
@@ -1795,7 +1395,9 @@ export {
1795
1395
  titleFromMessage,
1796
1396
  toolStateFromStatus,
1797
1397
  useAgents24ChatController,
1798
- useLatestThreadViewport,
1398
+ useMessageScroller,
1399
+ useMessageScrollerScrollable,
1400
+ useMessageScrollerVisibility,
1799
1401
  useStreamingText
1800
1402
  };
1801
1403
  //# sourceMappingURL=index.js.map