@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.
- package/README.md +25 -12
- package/dist/chunk-E3TJ3I6G.js +358 -0
- package/dist/chunk-E3TJ3I6G.js.map +1 -0
- package/dist/chunk-EWZO4QJI.js +140 -0
- package/dist/chunk-EWZO4QJI.js.map +1 -0
- package/dist/chunk-UU7OXHL3.js +11 -0
- package/dist/chunk-UU7OXHL3.js.map +1 -0
- package/dist/context-window.d.ts +38 -0
- package/dist/controller.d.ts +22 -0
- package/dist/index.cjs +392 -314
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -530
- package/dist/index.js +41 -439
- package/dist/index.js.map +1 -1
- package/dist/latest-thread-scroller.d.ts +54 -0
- package/dist/model.d.ts +29 -0
- package/dist/renderers.d.ts +10 -0
- package/dist/sse.d.ts +3 -0
- package/dist/streaming-text.d.ts +24 -0
- package/dist/templates/agent-chat-shell.d.ts +25 -0
- package/dist/templates/index.cjs +523 -0
- package/dist/templates/index.cjs.map +1 -0
- package/dist/templates/index.d.ts +1 -0
- package/dist/templates/index.js +140 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/transport.d.ts +29 -0
- package/dist/types.d.ts +312 -0
- package/dist/ui/adapters.d.ts +36 -0
- package/dist/ui/attachment.d.ts +23 -0
- package/dist/ui/bubble.d.ts +17 -0
- package/dist/ui/index.cjs +943 -0
- package/dist/ui/index.cjs.map +1 -0
- package/dist/ui/index.d.ts +7 -0
- package/dist/ui/index.js +734 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/marker.d.ts +11 -0
- package/dist/ui/message-response.d.ts +7 -0
- package/dist/ui/message.d.ts +10 -0
- package/dist/ui/utils.d.ts +2 -0
- package/dist/viewport.d.ts +2 -0
- package/package.json +22 -4
- 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(
|
|
27
|
-
return STAGE_PRIORITY[
|
|
42
|
+
function stagePriority(window) {
|
|
43
|
+
return STAGE_PRIORITY[window?.stage || "sent_prompt"] ?? STAGE_PRIORITY.sent_prompt;
|
|
28
44
|
}
|
|
29
|
-
function hasRenderableContextWindow(
|
|
30
|
-
const maxTokens =
|
|
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(
|
|
34
|
-
if (!
|
|
35
|
-
return [stagePriority(
|
|
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.
|
|
1348
|
+
// src/viewport.ts
|
|
1467
1349
|
import {
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1398
|
+
useMessageScroller,
|
|
1399
|
+
useMessageScrollerScrollable,
|
|
1400
|
+
useMessageScrollerVisibility,
|
|
1799
1401
|
useStreamingText
|
|
1800
1402
|
};
|
|
1801
1403
|
//# sourceMappingURL=index.js.map
|