@agents24/chat-react 0.1.4 → 0.1.6
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 +13 -1
- package/dist/index.cjs +92 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +91 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -405,6 +405,7 @@ type FetchChatTransportOptions = {
|
|
|
405
405
|
};
|
|
406
406
|
declare const createFetchChatTransport: ({ routes, fetchImpl, headers, streamBody, }: FetchChatTransportOptions) => ChatTransport;
|
|
407
407
|
|
|
408
|
+
type LatestFollowState = "following" | "detached";
|
|
408
409
|
declare const isScrollable: (element: Pick<HTMLDivElement, "scrollHeight" | "clientHeight">) => boolean;
|
|
409
410
|
declare const isAtTimelineLatestEdge: (element: Pick<HTMLDivElement, "scrollHeight" | "clientHeight" | "scrollTop">, isTopOrigin: boolean) => boolean;
|
|
410
411
|
declare const shouldPrefetchOlder: (element: Pick<HTMLDivElement, "scrollHeight" | "clientHeight" | "scrollTop">) => boolean;
|
|
@@ -414,6 +415,11 @@ declare const shouldUseTopOriginTimeline: ({ hasOlder, itemCount, topOriginMaxIt
|
|
|
414
415
|
itemCount: number;
|
|
415
416
|
topOriginMaxItems?: number;
|
|
416
417
|
}) => boolean;
|
|
418
|
+
declare const nextLatestFollowStateOnScroll: ({ atLatest, current, isProgrammatic, }: {
|
|
419
|
+
atLatest: boolean;
|
|
420
|
+
current: LatestFollowState;
|
|
421
|
+
isProgrammatic: boolean;
|
|
422
|
+
}) => LatestFollowState;
|
|
417
423
|
type UseLatestThreadViewportOptions = {
|
|
418
424
|
itemCount: number;
|
|
419
425
|
hasOlder: boolean;
|
|
@@ -426,15 +432,22 @@ type UseLatestThreadViewportOptions = {
|
|
|
426
432
|
type LatestThreadViewportState = {
|
|
427
433
|
scrollContainerRef: RefObject<HTMLDivElement | null>;
|
|
428
434
|
isAtLatest: boolean;
|
|
435
|
+
isFollowingLatest: boolean;
|
|
429
436
|
isTopOrigin: boolean;
|
|
430
437
|
shouldShowLatestButton: boolean;
|
|
431
438
|
handleScroll: (event: UIEvent<HTMLDivElement>) => void;
|
|
432
|
-
|
|
439
|
+
handleUserScrollIntent: () => void;
|
|
440
|
+
scrollToLatest: (options?: {
|
|
441
|
+
reattach?: boolean;
|
|
442
|
+
}) => void;
|
|
443
|
+
detachFromLatest: () => void;
|
|
444
|
+
reattachToLatest: () => void;
|
|
433
445
|
preserveIntrinsicResize: () => void;
|
|
434
446
|
};
|
|
435
447
|
declare function useLatestThreadViewport({ itemCount, hasOlder, isLoadingOlder, onLoadOlder, activeStreamKey, shouldAutoFollow, topOriginMaxItems, }: UseLatestThreadViewportOptions): LatestThreadViewportState;
|
|
436
448
|
type LatestThreadViewportRenderContext = {
|
|
437
449
|
preserveIntrinsicResize: () => void;
|
|
450
|
+
isFollowingLatest: boolean;
|
|
438
451
|
isTopOrigin: boolean;
|
|
439
452
|
};
|
|
440
453
|
type LatestThreadViewportProps<T> = {
|
|
@@ -450,4 +463,4 @@ type LatestThreadViewportProps<T> = {
|
|
|
450
463
|
};
|
|
451
464
|
declare function LatestThreadViewport<T>({ items, hasOlder, isLoadingOlder, onLoadOlder, activeStreamKey, className, latestSpacer, trailingSpacer, renderItem, }: LatestThreadViewportProps<T>): react.JSX.Element;
|
|
452
465
|
|
|
453
|
-
export { type Agents24ChatRenderOptions, type ChatActiveRun, type ChatApprovalPart, type ChatAttachment, type ChatCitation, type ChatContextWindow, type ChatController, type ChatDataPart, type ChatErrorPart, type ChatMessage, type ChatPart, type ChatReasoningPart, type ChatReasoningStep, type ChatRunStatus, type ChatRuntimeEvent, type ChatStorageAdapter, type ChatStreamResult, type ChatTextPart, type ChatThreadDetail, type ChatThreadSummary, type ChatThreadTurn, type ChatToolPart, type ChatToolState, type ChatTransport, type ChatUiBlocksPart, DEFAULT_THREAD_PAGE_SIZE, DefaultChatPart, DefaultToolPart, type FetchChatTransportOptions, type FetchChatTransportRoutes, LatestThreadViewport, type LatestThreadViewportProps, type LatestThreadViewportRenderContext, type LatestThreadViewportState, type StoredChatThread, type StreamingTextCache, type StreamingTextMode, type ToolPresentation, type ToolRenderer, type UseAgents24ChatControllerOptions, type UseLatestThreadViewportOptions, type UseStreamingTextOptions, type UseStreamingTextResult, activeRunIdFromThread, activeRunIdFromThreadDetail, assistantTextFromParts, assistantTextFromResponseBlocks, consumeSseResponse, createChatId, createFetchChatTransport, getActiveStreamingTextPartId, getLatestScrollTop, hasStaleUnfinishedAssistantCache, hasUnfinishedAssistantMessage, isActiveStreamingTextPart, isAtTimelineLatestEdge, isRunningThreadStatus, isScrollable, latestContextWindowFromThread, mergeReasoningSteps, parseSseBlock, partsFromResponseBlocks, reasoningStepsFromParts, renderChatPart, shouldPrefetchOlder, shouldUseTopOriginTimeline, textFromFinalOutput, threadActivityDate, threadDetailToMessages, threadPaging, titleFromMessage, toolStateFromStatus, useAgents24ChatController, useLatestThreadViewport, useStreamingText };
|
|
466
|
+
export { type Agents24ChatRenderOptions, type ChatActiveRun, type ChatApprovalPart, type ChatAttachment, type ChatCitation, type ChatContextWindow, type ChatController, type ChatDataPart, type ChatErrorPart, type ChatMessage, type ChatPart, type ChatReasoningPart, type ChatReasoningStep, type ChatRunStatus, type ChatRuntimeEvent, type ChatStorageAdapter, type ChatStreamResult, type ChatTextPart, type ChatThreadDetail, type ChatThreadSummary, type ChatThreadTurn, type ChatToolPart, type ChatToolState, type ChatTransport, type ChatUiBlocksPart, DEFAULT_THREAD_PAGE_SIZE, DefaultChatPart, DefaultToolPart, type FetchChatTransportOptions, type FetchChatTransportRoutes, type LatestFollowState, LatestThreadViewport, type LatestThreadViewportProps, type LatestThreadViewportRenderContext, type LatestThreadViewportState, type StoredChatThread, type StreamingTextCache, type StreamingTextMode, type ToolPresentation, type ToolRenderer, type UseAgents24ChatControllerOptions, type UseLatestThreadViewportOptions, type UseStreamingTextOptions, type UseStreamingTextResult, activeRunIdFromThread, activeRunIdFromThreadDetail, assistantTextFromParts, assistantTextFromResponseBlocks, consumeSseResponse, createChatId, createFetchChatTransport, getActiveStreamingTextPartId, getLatestScrollTop, hasStaleUnfinishedAssistantCache, hasUnfinishedAssistantMessage, isActiveStreamingTextPart, isAtTimelineLatestEdge, isRunningThreadStatus, isScrollable, latestContextWindowFromThread, mergeReasoningSteps, nextLatestFollowStateOnScroll, parseSseBlock, partsFromResponseBlocks, reasoningStepsFromParts, renderChatPart, shouldPrefetchOlder, shouldUseTopOriginTimeline, textFromFinalOutput, threadActivityDate, threadDetailToMessages, threadPaging, titleFromMessage, toolStateFromStatus, useAgents24ChatController, useLatestThreadViewport, useStreamingText };
|
package/dist/index.js
CHANGED
|
@@ -1274,6 +1274,14 @@ var shouldUseTopOriginTimeline = ({
|
|
|
1274
1274
|
itemCount,
|
|
1275
1275
|
topOriginMaxItems = 4
|
|
1276
1276
|
}) => !hasOlder && itemCount > 0 && itemCount <= topOriginMaxItems;
|
|
1277
|
+
var nextLatestFollowStateOnScroll = ({
|
|
1278
|
+
atLatest,
|
|
1279
|
+
current,
|
|
1280
|
+
isProgrammatic
|
|
1281
|
+
}) => {
|
|
1282
|
+
if (isProgrammatic) return current;
|
|
1283
|
+
return atLatest ? "following" : "detached";
|
|
1284
|
+
};
|
|
1277
1285
|
function useLatestThreadViewport({
|
|
1278
1286
|
itemCount,
|
|
1279
1287
|
hasOlder,
|
|
@@ -1287,12 +1295,19 @@ function useLatestThreadViewport({
|
|
|
1287
1295
|
const olderPagePreserveRef = useRef3(null);
|
|
1288
1296
|
const olderPageRequestInFlightRef = useRef3(false);
|
|
1289
1297
|
const intrinsicResizePreserveRef = useRef3(null);
|
|
1290
|
-
const
|
|
1298
|
+
const followStateRef = useRef3("following");
|
|
1291
1299
|
const programmaticScrollRef = useRef3(false);
|
|
1292
1300
|
const programmaticScrollTimeoutRef = useRef3(null);
|
|
1293
1301
|
const activeStreamKeyRef = useRef3(null);
|
|
1302
|
+
const observedScrollHeightRef = useRef3(null);
|
|
1294
1303
|
const [isAtLatest, setIsAtLatest] = useState3(true);
|
|
1304
|
+
const [followState, setFollowState] = useState3("following");
|
|
1295
1305
|
const isTopOrigin = shouldUseTopOriginTimeline({ hasOlder, itemCount, topOriginMaxItems });
|
|
1306
|
+
const setLatestFollowState = useCallback2((next) => {
|
|
1307
|
+
if (followStateRef.current === next) return;
|
|
1308
|
+
followStateRef.current = next;
|
|
1309
|
+
setFollowState(next);
|
|
1310
|
+
}, []);
|
|
1296
1311
|
const markProgrammaticScroll = useCallback2(() => {
|
|
1297
1312
|
programmaticScrollRef.current = true;
|
|
1298
1313
|
if (programmaticScrollTimeoutRef.current) clearTimeout(programmaticScrollTimeoutRef.current);
|
|
@@ -1301,13 +1316,26 @@ function useLatestThreadViewport({
|
|
|
1301
1316
|
programmaticScrollTimeoutRef.current = null;
|
|
1302
1317
|
}, 80);
|
|
1303
1318
|
}, []);
|
|
1304
|
-
const scrollToLatest = useCallback2(() => {
|
|
1319
|
+
const scrollToLatest = useCallback2((options) => {
|
|
1305
1320
|
const element = scrollContainerRef.current;
|
|
1306
1321
|
if (!element) return;
|
|
1322
|
+
if (options?.reattach !== false) setLatestFollowState("following");
|
|
1307
1323
|
markProgrammaticScroll();
|
|
1308
1324
|
element.scrollTop = getLatestScrollTop(element, isTopOrigin);
|
|
1309
1325
|
setIsAtLatest(true);
|
|
1310
|
-
|
|
1326
|
+
observedScrollHeightRef.current = element.scrollHeight;
|
|
1327
|
+
}, [isTopOrigin, markProgrammaticScroll, setLatestFollowState]);
|
|
1328
|
+
const detachFromLatest = useCallback2(() => {
|
|
1329
|
+
setLatestFollowState("detached");
|
|
1330
|
+
}, [setLatestFollowState]);
|
|
1331
|
+
const reattachToLatest = useCallback2(() => {
|
|
1332
|
+
scrollToLatest({ reattach: true });
|
|
1333
|
+
}, [scrollToLatest]);
|
|
1334
|
+
const handleUserScrollIntent = useCallback2(() => {
|
|
1335
|
+
const element = scrollContainerRef.current;
|
|
1336
|
+
if (!activeStreamKey || !element) return;
|
|
1337
|
+
if (!isAtTimelineLatestEdge(element, isTopOrigin)) detachFromLatest();
|
|
1338
|
+
}, [activeStreamKey, detachFromLatest, isTopOrigin]);
|
|
1311
1339
|
useEffect3(() => {
|
|
1312
1340
|
return () => {
|
|
1313
1341
|
if (programmaticScrollTimeoutRef.current) clearTimeout(programmaticScrollTimeoutRef.current);
|
|
@@ -1319,6 +1347,7 @@ function useLatestThreadViewport({
|
|
|
1319
1347
|
const element = scrollContainerRef.current;
|
|
1320
1348
|
const preserve = olderPagePreserveRef.current;
|
|
1321
1349
|
if (!element) return;
|
|
1350
|
+
observedScrollHeightRef.current = element.scrollHeight;
|
|
1322
1351
|
if (!preserve) {
|
|
1323
1352
|
setIsAtLatest(isAtTimelineLatestEdge(element, isTopOrigin));
|
|
1324
1353
|
return;
|
|
@@ -1335,7 +1364,13 @@ function useLatestThreadViewport({
|
|
|
1335
1364
|
const element = event.currentTarget;
|
|
1336
1365
|
const atLatest = isAtTimelineLatestEdge(element, isTopOrigin);
|
|
1337
1366
|
setIsAtLatest(atLatest);
|
|
1338
|
-
|
|
1367
|
+
setLatestFollowState(
|
|
1368
|
+
nextLatestFollowStateOnScroll({
|
|
1369
|
+
atLatest,
|
|
1370
|
+
current: followStateRef.current,
|
|
1371
|
+
isProgrammatic: programmaticScrollRef.current
|
|
1372
|
+
})
|
|
1373
|
+
);
|
|
1339
1374
|
if (isTopOrigin || !hasOlder || isLoadingOlder || olderPageRequestInFlightRef.current || !shouldPrefetchOlder(element)) {
|
|
1340
1375
|
return;
|
|
1341
1376
|
}
|
|
@@ -1352,7 +1387,7 @@ function useLatestThreadViewport({
|
|
|
1352
1387
|
});
|
|
1353
1388
|
});
|
|
1354
1389
|
},
|
|
1355
|
-
[hasOlder, isLoadingOlder, isTopOrigin, onLoadOlder]
|
|
1390
|
+
[hasOlder, isLoadingOlder, isTopOrigin, onLoadOlder, setLatestFollowState]
|
|
1356
1391
|
);
|
|
1357
1392
|
const preserveIntrinsicResize = useCallback2(() => {
|
|
1358
1393
|
const element = scrollContainerRef.current;
|
|
@@ -1383,37 +1418,73 @@ function useLatestThreadViewport({
|
|
|
1383
1418
|
};
|
|
1384
1419
|
intrinsicResizePreserveRef.current.frame = requestAnimationFrame(preserveFrame);
|
|
1385
1420
|
}, [isTopOrigin, markProgrammaticScroll]);
|
|
1386
|
-
|
|
1421
|
+
useLayoutEffect(() => {
|
|
1387
1422
|
const key = activeStreamKey || null;
|
|
1388
|
-
|
|
1389
|
-
|
|
1423
|
+
const previousKey = activeStreamKeyRef.current;
|
|
1424
|
+
if (!key) {
|
|
1425
|
+
activeStreamKeyRef.current = null;
|
|
1426
|
+
if (previousKey && shouldAutoFollow && followStateRef.current === "following" && !isLoadingOlder && !olderPageRequestInFlightRef.current) {
|
|
1427
|
+
const frame2 = requestAnimationFrame(() => {
|
|
1428
|
+
if (followStateRef.current === "following" && !isLoadingOlder && !olderPageRequestInFlightRef.current) {
|
|
1429
|
+
scrollToLatest({ reattach: false });
|
|
1430
|
+
}
|
|
1431
|
+
});
|
|
1432
|
+
return () => cancelAnimationFrame(frame2);
|
|
1433
|
+
}
|
|
1390
1434
|
return;
|
|
1391
1435
|
}
|
|
1392
|
-
|
|
1393
|
-
if (isTopOrigin) {
|
|
1436
|
+
if (previousKey === key) {
|
|
1394
1437
|
activeStreamKeyRef.current = key;
|
|
1395
1438
|
return;
|
|
1396
1439
|
}
|
|
1397
|
-
|
|
1440
|
+
setLatestFollowState("following");
|
|
1441
|
+
const frame = requestAnimationFrame(() => scrollToLatest());
|
|
1398
1442
|
activeStreamKeyRef.current = key;
|
|
1399
1443
|
return () => cancelAnimationFrame(frame);
|
|
1400
|
-
}, [activeStreamKey,
|
|
1444
|
+
}, [activeStreamKey, isLoadingOlder, scrollToLatest, setLatestFollowState, shouldAutoFollow]);
|
|
1401
1445
|
useLayoutEffect(() => {
|
|
1402
|
-
if (
|
|
1403
|
-
if (!activeStreamKey || !shouldAutoFollow || !autoFollowLatestRef.current) return;
|
|
1446
|
+
if (!activeStreamKey || !shouldAutoFollow || followStateRef.current !== "following") return;
|
|
1404
1447
|
if (isLoadingOlder || olderPageRequestInFlightRef.current) return;
|
|
1405
1448
|
const frame = requestAnimationFrame(() => {
|
|
1406
|
-
if (
|
|
1449
|
+
if (followStateRef.current === "following" && !isLoadingOlder && !olderPageRequestInFlightRef.current) {
|
|
1450
|
+
scrollToLatest({ reattach: false });
|
|
1451
|
+
}
|
|
1407
1452
|
});
|
|
1408
1453
|
return () => cancelAnimationFrame(frame);
|
|
1409
|
-
}, [activeStreamKey, isLoadingOlder,
|
|
1454
|
+
}, [activeStreamKey, isLoadingOlder, itemCount, scrollToLatest, shouldAutoFollow]);
|
|
1455
|
+
useEffect3(() => {
|
|
1456
|
+
if (!activeStreamKey) {
|
|
1457
|
+
observedScrollHeightRef.current = scrollContainerRef.current?.scrollHeight ?? null;
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
let frame = null;
|
|
1461
|
+
const watchStreamResize = () => {
|
|
1462
|
+
const element = scrollContainerRef.current;
|
|
1463
|
+
if (!element) return;
|
|
1464
|
+
const previousHeight = observedScrollHeightRef.current;
|
|
1465
|
+
const nextHeight = element.scrollHeight;
|
|
1466
|
+
observedScrollHeightRef.current = nextHeight;
|
|
1467
|
+
if (previousHeight !== null && Math.abs(nextHeight - previousHeight) >= 1 && shouldAutoFollow && followStateRef.current === "following" && !isLoadingOlder && !olderPageRequestInFlightRef.current) {
|
|
1468
|
+
scrollToLatest({ reattach: false });
|
|
1469
|
+
}
|
|
1470
|
+
frame = requestAnimationFrame(watchStreamResize);
|
|
1471
|
+
};
|
|
1472
|
+
frame = requestAnimationFrame(watchStreamResize);
|
|
1473
|
+
return () => {
|
|
1474
|
+
if (frame !== null) cancelAnimationFrame(frame);
|
|
1475
|
+
};
|
|
1476
|
+
}, [activeStreamKey, isLoadingOlder, scrollToLatest, shouldAutoFollow]);
|
|
1410
1477
|
return {
|
|
1411
1478
|
scrollContainerRef,
|
|
1412
1479
|
isAtLatest,
|
|
1480
|
+
isFollowingLatest: followState === "following",
|
|
1413
1481
|
isTopOrigin,
|
|
1414
1482
|
shouldShowLatestButton: !isAtLatest,
|
|
1415
1483
|
handleScroll,
|
|
1484
|
+
handleUserScrollIntent,
|
|
1416
1485
|
scrollToLatest,
|
|
1486
|
+
detachFromLatest,
|
|
1487
|
+
reattachToLatest,
|
|
1417
1488
|
preserveIntrinsicResize
|
|
1418
1489
|
};
|
|
1419
1490
|
}
|
|
@@ -1441,7 +1512,10 @@ function LatestThreadViewport({
|
|
|
1441
1512
|
{
|
|
1442
1513
|
ref: viewport.scrollContainerRef,
|
|
1443
1514
|
className,
|
|
1515
|
+
onKeyDown: viewport.handleUserScrollIntent,
|
|
1444
1516
|
onScroll: viewport.handleScroll,
|
|
1517
|
+
onTouchMove: viewport.handleUserScrollIntent,
|
|
1518
|
+
onWheel: viewport.handleUserScrollIntent,
|
|
1445
1519
|
role: "log",
|
|
1446
1520
|
style: { overflowAnchor: "none" },
|
|
1447
1521
|
children: [
|
|
@@ -1474,6 +1548,7 @@ export {
|
|
|
1474
1548
|
isScrollable,
|
|
1475
1549
|
latestContextWindowFromThread,
|
|
1476
1550
|
mergeReasoningSteps,
|
|
1551
|
+
nextLatestFollowStateOnScroll,
|
|
1477
1552
|
parseSseBlock,
|
|
1478
1553
|
partsFromResponseBlocks,
|
|
1479
1554
|
reasoningStepsFromParts,
|