@agents24/chat-react 0.4.0 → 0.5.1
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 +92 -18
- package/compatibility.json +10 -10
- package/dist/chunk-SSUO4EPD.js +189 -0
- package/dist/chunk-SSUO4EPD.js.map +1 -0
- package/dist/chunk-ZCNHLFRB.js +108 -0
- package/dist/chunk-ZCNHLFRB.js.map +1 -0
- package/dist/index.cjs +112 -95
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +362 -68
- package/dist/index.js.map +1 -1
- package/dist/mcp-oauth.d.ts +13 -0
- package/dist/runtime/index.cjs +594 -0
- package/dist/runtime/index.cjs.map +1 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +458 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/input-contract.d.ts +20 -0
- package/dist/runtime/use-agent-chat-runtime.d.ts +83 -0
- package/dist/scaffold/app.d.ts +30 -0
- package/dist/scaffold/components/chat/chat-composer.d.ts +21 -0
- package/dist/scaffold/components/chat/chat-message.d.ts +21 -0
- package/dist/scaffold/components/chat/chat-shell.d.ts +8 -0
- package/dist/scaffold/components/chat/collapsible-user-message.d.ts +3 -0
- package/dist/scaffold/components/chat/external-link-dialog.d.ts +2 -0
- package/dist/scaffold/components/chat/identity-control.d.ts +4 -0
- package/dist/scaffold/components/chat/message-parts.d.ts +12 -0
- package/dist/scaffold/components/chat/theme-menu.d.ts +1 -0
- package/dist/scaffold/components/chat/thread-sidebar.d.ts +16 -0
- package/dist/scaffold/components/chat/timeline-loading.d.ts +7 -0
- package/dist/scaffold/components/chat/turn-outline.d.ts +4 -0
- package/dist/scaffold/components/theme-provider.d.ts +20 -0
- package/dist/scaffold/components/ui/attachment.d.ts +24 -0
- package/dist/scaffold/components/ui/bubble.d.ts +17 -0
- package/dist/scaffold/components/ui/button-group.d.ts +11 -0
- package/dist/scaffold/components/ui/button.d.ts +10 -0
- package/dist/scaffold/components/ui/dialog.d.ts +17 -0
- package/dist/scaffold/components/ui/dropdown-menu.d.ts +29 -0
- package/dist/scaffold/components/ui/input.d.ts +3 -0
- package/dist/scaffold/components/ui/marker.d.ts +11 -0
- package/dist/scaffold/components/ui/message-scroller.d.ts +10 -0
- package/dist/scaffold/components/ui/message.d.ts +10 -0
- package/dist/scaffold/components/ui/popover.d.ts +6 -0
- package/dist/scaffold/components/ui/select.d.ts +8 -0
- package/dist/scaffold/components/ui/separator.d.ts +4 -0
- package/dist/scaffold/components/ui/sheet.d.ts +14 -0
- package/dist/scaffold/components/ui/sidebar.d.ts +69 -0
- package/dist/scaffold/components/ui/skeleton.d.ts +2 -0
- package/dist/scaffold/components/ui/textarea.d.ts +3 -0
- package/dist/scaffold/components/ui/tooltip.d.ts +15 -0
- package/dist/scaffold/hooks/use-mobile.d.ts +1 -0
- package/dist/scaffold/identity.d.ts +10 -0
- package/dist/scaffold/index.cjs +2270 -0
- package/dist/scaffold/index.cjs.map +1 -0
- package/dist/scaffold/index.d.ts +14 -0
- package/dist/scaffold/index.js +2244 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/lib/utils.d.ts +2 -0
- package/dist/styles.css +143 -298
- package/dist/types.d.ts +3 -13
- package/dist/ui/adapters.d.ts +1 -1
- package/dist/ui/agent-chat-actions.d.ts +12 -5
- package/dist/ui/agent-chat-composer.d.ts +2 -1
- package/dist/ui/agent-chat-context-compression-row.d.ts +5 -0
- package/dist/ui/agent-chat-context-status.d.ts +13 -0
- package/dist/ui/agent-chat-message.d.ts +7 -5
- package/dist/ui/agent-response-timeline.d.ts +29 -7
- package/dist/ui/ask-user-interaction-state.d.ts +20 -0
- package/dist/ui/ask-user-interaction.d.ts +8 -0
- package/dist/ui/index.cjs +1392 -272
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.ts +5 -0
- package/dist/ui/index.js +2380 -65
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/tool-sessions.d.ts +70 -0
- package/dist/ui/use-audio-recorder.d.ts +8 -0
- package/package.json +27 -12
- package/scaffold/components.json +25 -0
- package/scaffold/manifest.json +28 -0
- package/scaffold/src/app.tsx +71 -0
- package/scaffold/src/chat.css +54 -0
- package/scaffold/src/components/chat/chat-composer.tsx +237 -0
- package/scaffold/src/components/chat/chat-message.tsx +76 -0
- package/scaffold/src/components/chat/chat-shell.tsx +257 -0
- package/scaffold/src/components/chat/collapsible-user-message.tsx +37 -0
- package/scaffold/src/components/chat/external-link-dialog.tsx +48 -0
- package/scaffold/src/components/chat/identity-control.tsx +69 -0
- package/scaffold/src/components/chat/message-parts.tsx +83 -0
- package/scaffold/src/components/chat/theme-menu.tsx +79 -0
- package/scaffold/src/components/chat/thread-sidebar.tsx +114 -0
- package/scaffold/src/components/chat/timeline-loading.ts +17 -0
- package/scaffold/src/components/chat/turn-outline.tsx +73 -0
- package/scaffold/src/components/theme-provider.tsx +91 -0
- package/scaffold/src/components/ui/attachment.tsx +204 -0
- package/scaffold/src/components/ui/bubble.tsx +125 -0
- package/scaffold/src/components/ui/button-group.tsx +83 -0
- package/scaffold/src/components/ui/button.tsx +65 -0
- package/scaffold/src/components/ui/dialog.tsx +171 -0
- package/scaffold/src/components/ui/dropdown-menu.tsx +271 -0
- package/scaffold/src/components/ui/input.tsx +19 -0
- package/scaffold/src/components/ui/marker.tsx +69 -0
- package/scaffold/src/components/ui/message-scroller.tsx +129 -0
- package/scaffold/src/components/ui/message.tsx +92 -0
- package/scaffold/src/components/ui/popover.tsx +40 -0
- package/scaffold/src/components/ui/select.tsx +92 -0
- package/scaffold/src/components/ui/separator.tsx +28 -0
- package/scaffold/src/components/ui/sheet.tsx +150 -0
- package/scaffold/src/components/ui/sidebar.tsx +677 -0
- package/scaffold/src/components/ui/skeleton.tsx +13 -0
- package/scaffold/src/components/ui/textarea.tsx +18 -0
- package/scaffold/src/components/ui/tooltip.tsx +56 -0
- package/scaffold/src/hooks/use-mobile.ts +24 -0
- package/scaffold/src/identity.ts +17 -0
- package/scaffold/src/index.css +222 -0
- package/scaffold/src/index.tsx +39 -0
- package/scaffold/src/lib/utils.ts +6 -0
- package/scaffold/styles.css +3 -0
- package/dist/chunk-CHAU7FNW.js +0 -140
- package/dist/chunk-CHAU7FNW.js.map +0 -1
- package/dist/chunk-LI67M74F.js +0 -445
- package/dist/chunk-LI67M74F.js.map +0 -1
- package/dist/chunk-NLEOWTZG.js +0 -1327
- package/dist/chunk-NLEOWTZG.js.map +0 -1
- package/dist/renderers.d.ts +0 -10
- package/dist/templates/agent-chat-app.d.ts +0 -18
- package/dist/templates/agent-chat-layout.d.ts +0 -69
- package/dist/templates/agent-chat-shell.d.ts +0 -37
- package/dist/templates/index.cjs +0 -2476
- package/dist/templates/index.cjs.map +0 -1
- package/dist/templates/index.d.ts +0 -3
- package/dist/templates/index.js +0 -723
- package/dist/templates/index.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -28,10 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
30
|
// src/index.ts
|
|
31
|
-
var
|
|
32
|
-
__export(
|
|
33
|
-
DefaultChatPart: () => DefaultChatPart,
|
|
34
|
-
DefaultToolPart: () => DefaultToolPart,
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
35
33
|
LatestThreadScroller: () => LatestThreadScroller,
|
|
36
34
|
LatestThreadScrollerButton: () => LatestThreadScrollerButton,
|
|
37
35
|
LatestThreadScrollerContent: () => LatestThreadScrollerContent,
|
|
@@ -41,9 +39,10 @@ __export(index_exports, {
|
|
|
41
39
|
LatestThreadScrollerRoot: () => LatestThreadScrollerRoot,
|
|
42
40
|
LatestThreadScrollerViewport: () => LatestThreadScrollerViewport,
|
|
43
41
|
MessageScroller: () => import_message_scroller2.MessageScroller,
|
|
42
|
+
browserChatCrypto: () => browserChatCrypto,
|
|
43
|
+
createMcpPkceProof: () => createMcpPkceProof,
|
|
44
44
|
getActiveStreamingTextPartId: () => getActiveStreamingTextPartId,
|
|
45
45
|
isActiveStreamingTextPart: () => isActiveStreamingTextPart,
|
|
46
|
-
renderChatPart: () => renderChatPart,
|
|
47
46
|
useMessageScroller: () => import_message_scroller2.useMessageScroller,
|
|
48
47
|
useMessageScrollerScrollable: () => import_message_scroller2.useMessageScrollerScrollable,
|
|
49
48
|
useMessageScrollerVisibility: () => import_message_scroller2.useMessageScrollerVisibility,
|
|
@@ -51,7 +50,7 @@ __export(index_exports, {
|
|
|
51
50
|
validateMcpCallbackResult: () => validateMcpCallbackResult,
|
|
52
51
|
waitForMcpOauthComplete: () => waitForMcpOauthComplete
|
|
53
52
|
});
|
|
54
|
-
module.exports = __toCommonJS(
|
|
53
|
+
module.exports = __toCommonJS(src_exports);
|
|
55
54
|
|
|
56
55
|
// src/latest-thread-scroller.tsx
|
|
57
56
|
var React = __toESM(require("react"), 1);
|
|
@@ -402,6 +401,26 @@ var LatestThreadScroller = {
|
|
|
402
401
|
|
|
403
402
|
// src/mcp-oauth.ts
|
|
404
403
|
var 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;
|
|
404
|
+
function browserChatCrypto() {
|
|
405
|
+
const value = globalThis.crypto;
|
|
406
|
+
if (!value?.subtle || !value.randomUUID) {
|
|
407
|
+
throw new Error("Secure browser crypto is required for MCP authorization.");
|
|
408
|
+
}
|
|
409
|
+
return value;
|
|
410
|
+
}
|
|
411
|
+
function base64Url(bytes) {
|
|
412
|
+
let binary = "";
|
|
413
|
+
bytes.forEach((byte) => {
|
|
414
|
+
binary += String.fromCharCode(byte);
|
|
415
|
+
});
|
|
416
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
417
|
+
}
|
|
418
|
+
async function createMcpPkceProof() {
|
|
419
|
+
const crypto = browserChatCrypto();
|
|
420
|
+
const verifier = base64Url(crypto.getRandomValues(new Uint8Array(32)));
|
|
421
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
|
|
422
|
+
return { challenge: base64Url(new Uint8Array(digest)), verifier };
|
|
423
|
+
}
|
|
405
424
|
function isLoopback(hostname) {
|
|
406
425
|
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
|
|
407
426
|
}
|
|
@@ -481,59 +500,11 @@ function waitForMcpOauthComplete({
|
|
|
481
500
|
});
|
|
482
501
|
}
|
|
483
502
|
|
|
484
|
-
// src/renderers.tsx
|
|
485
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
486
|
-
var DefaultToolPart = ({ part }) => {
|
|
487
|
-
const label = typeof part.presentation?.activity === "string" ? part.presentation.activity : typeof part.presentation?.title === "string" ? part.presentation.title : part.toolName;
|
|
488
|
-
const detail = typeof part.presentation?.detail === "string" ? part.presentation.detail : part.errorText || part.state;
|
|
489
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { "data-agents24-tool-part": part.type, "data-state": part.state, children: [
|
|
490
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: label }),
|
|
491
|
-
detail ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: detail }) : null
|
|
492
|
-
] });
|
|
493
|
-
};
|
|
494
|
-
var DefaultChatPart = ({
|
|
495
|
-
part,
|
|
496
|
-
message,
|
|
497
|
-
renderOptions
|
|
498
|
-
}) => {
|
|
499
|
-
if (renderOptions?.renderPart) {
|
|
500
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: renderOptions.renderPart(part, message) });
|
|
501
|
-
}
|
|
502
|
-
if (part.kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: part.text });
|
|
503
|
-
if (part.kind === "tool") {
|
|
504
|
-
const ToolRenderer = renderOptions?.toolRenderers?.[part.type] || renderOptions?.fallbackToolRenderer || DefaultToolPart;
|
|
505
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: ToolRenderer({ part, message }) });
|
|
506
|
-
}
|
|
507
|
-
if (part.kind === "reasoning") {
|
|
508
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "data-agents24-reasoning-part": true, children: part.text || part.label });
|
|
509
|
-
}
|
|
510
|
-
if (part.kind === "ui-blocks") {
|
|
511
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "data-agents24-ui-blocks-part": true, "data-state": part.state });
|
|
512
|
-
}
|
|
513
|
-
if (part.kind === "hitl") {
|
|
514
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "data-agents24-hitl-part": part.interruptId || "" });
|
|
515
|
-
}
|
|
516
|
-
if (part.kind === "error") {
|
|
517
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "data-agents24-error-part": true, children: part.errorText });
|
|
518
|
-
}
|
|
519
|
-
if (part.kind === "data") {
|
|
520
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "data-agents24-data-part": part.name });
|
|
521
|
-
}
|
|
522
|
-
return null;
|
|
523
|
-
};
|
|
524
|
-
var renderChatPart = (part, message, renderOptions) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
525
|
-
DefaultChatPart,
|
|
526
|
-
{
|
|
527
|
-
part,
|
|
528
|
-
message,
|
|
529
|
-
renderOptions
|
|
530
|
-
},
|
|
531
|
-
part.id
|
|
532
|
-
);
|
|
533
|
-
|
|
534
503
|
// src/streaming-text.ts
|
|
535
504
|
var import_react = require("react");
|
|
536
505
|
var DEFAULT_COMPLETED_TEXT_CACHE_SIZE = 200;
|
|
506
|
+
var STREAM_RUNWAY_MS = 80;
|
|
507
|
+
var STREAM_IDLE_RELEASE_MS = 120;
|
|
537
508
|
var defaultCompletedTextCache = /* @__PURE__ */ new Map();
|
|
538
509
|
var defaultStreamingTextCache = {
|
|
539
510
|
get: (id) => defaultCompletedTextCache.get(id),
|
|
@@ -547,9 +518,35 @@ var defaultStreamingTextCache = {
|
|
|
547
518
|
};
|
|
548
519
|
var getActiveStreamingTextPartId = (message, streamingMessageId) => {
|
|
549
520
|
if (message.role !== "assistant" || streamingMessageId !== message.id) return null;
|
|
550
|
-
|
|
521
|
+
const trailingPart = message.parts[message.parts.length - 1];
|
|
522
|
+
return trailingPart?.kind === "text" ? trailingPart.id : null;
|
|
551
523
|
};
|
|
552
524
|
var isActiveStreamingTextPart = (message, part, streamingMessageId) => part.kind === "text" && part.id === getActiveStreamingTextPartId(message, streamingMessageId);
|
|
525
|
+
var graphemeEndOffsets = (value) => {
|
|
526
|
+
if (!value) return [];
|
|
527
|
+
if (typeof Intl !== "undefined" && "Segmenter" in Intl) {
|
|
528
|
+
const segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
529
|
+
return Array.from(segmenter.segment(value), ({ index, segment }) => index + segment.length);
|
|
530
|
+
}
|
|
531
|
+
const characters = Array.from(value);
|
|
532
|
+
const offsets = [];
|
|
533
|
+
let offset = 0;
|
|
534
|
+
let regionalIndicators = 0;
|
|
535
|
+
characters.forEach((character, index) => {
|
|
536
|
+
const previous = characters[index - 1];
|
|
537
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
538
|
+
const isRegionalIndicator = codePoint >= 127462 && codePoint <= 127487;
|
|
539
|
+
const continuesCluster = index > 0 && (/^\p{Mark}$/u.test(character) || codePoint >= 65024 && codePoint <= 65039 || codePoint >= 127995 && codePoint <= 127999 || character === "\u200D" || previous === "\u200D" || isRegionalIndicator && regionalIndicators % 2 === 1);
|
|
540
|
+
if (!continuesCluster) {
|
|
541
|
+
if (offset > 0) offsets.push(offset);
|
|
542
|
+
regionalIndicators = 0;
|
|
543
|
+
}
|
|
544
|
+
offset += character.length;
|
|
545
|
+
regionalIndicators = isRegionalIndicator ? regionalIndicators + 1 : 0;
|
|
546
|
+
});
|
|
547
|
+
offsets.push(offset);
|
|
548
|
+
return offsets;
|
|
549
|
+
};
|
|
553
550
|
function useStreamingText({
|
|
554
551
|
id,
|
|
555
552
|
isStreaming,
|
|
@@ -568,85 +565,104 @@ function useStreamingText({
|
|
|
568
565
|
const displayedRef = (0, import_react.useRef)(displayedText);
|
|
569
566
|
const rafRef = (0, import_react.useRef)(null);
|
|
570
567
|
const lastFrameAtRef = (0, import_react.useRef)(null);
|
|
568
|
+
const targetUpdatedAtRef = (0, import_react.useRef)(null);
|
|
569
|
+
const progressRemainderRef = (0, import_react.useRef)(0);
|
|
571
570
|
const idRef = (0, import_react.useRef)(id);
|
|
572
|
-
const
|
|
571
|
+
const streamingRef = (0, import_react.useRef)(isStreaming);
|
|
572
|
+
const reduceMotionRef = (0, import_react.useRef)(false);
|
|
573
573
|
(0, import_react.useEffect)(() => {
|
|
574
574
|
if (isStreaming || !text) return;
|
|
575
575
|
cacheAdapter?.set(id, text);
|
|
576
576
|
}, [cacheAdapter, id, isStreaming, text]);
|
|
577
577
|
(0, import_react.useEffect)(() => {
|
|
578
578
|
targetRef.current = text;
|
|
579
|
-
|
|
579
|
+
targetUpdatedAtRef.current = typeof performance === "undefined" ? null : performance.now();
|
|
580
|
+
if (!isStreaming || reduceMotionRef.current || !text.startsWith(displayedRef.current)) {
|
|
581
|
+
displayedRef.current = text;
|
|
582
|
+
setDisplayedText(text);
|
|
583
|
+
progressRemainderRef.current = 0;
|
|
584
|
+
}
|
|
585
|
+
}, [isStreaming, text]);
|
|
580
586
|
(0, import_react.useEffect)(() => {
|
|
581
587
|
if (idRef.current === id) return;
|
|
582
588
|
idRef.current = id;
|
|
583
589
|
const cachedText = cacheAdapter?.get(id);
|
|
584
590
|
const initial = cachedText && text.startsWith(cachedText) ? cachedText : text;
|
|
585
|
-
shouldAnimateRef.current = isStreaming && initial !== text;
|
|
586
591
|
displayedRef.current = initial;
|
|
587
592
|
setDisplayedText(initial);
|
|
588
|
-
if (rafRef.current !== null) {
|
|
589
|
-
cancelAnimationFrame(rafRef.current);
|
|
590
|
-
rafRef.current = null;
|
|
591
|
-
}
|
|
592
593
|
lastFrameAtRef.current = null;
|
|
594
|
+
targetUpdatedAtRef.current = typeof performance === "undefined" ? null : performance.now();
|
|
595
|
+
progressRemainderRef.current = 0;
|
|
593
596
|
}, [cacheAdapter, id, isStreaming, text]);
|
|
594
597
|
(0, import_react.useEffect)(() => {
|
|
598
|
+
streamingRef.current = isStreaming;
|
|
595
599
|
if (typeof window === "undefined") {
|
|
596
600
|
displayedRef.current = text;
|
|
597
601
|
setDisplayedText(text);
|
|
598
602
|
return;
|
|
599
603
|
}
|
|
600
|
-
const
|
|
601
|
-
|
|
604
|
+
const reduceMotion2 = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
605
|
+
reduceMotionRef.current = reduceMotion2;
|
|
606
|
+
if (reduceMotion2 || !isStreaming) {
|
|
602
607
|
displayedRef.current = text;
|
|
603
608
|
setDisplayedText(text);
|
|
604
|
-
shouldAnimateRef.current = false;
|
|
605
609
|
return;
|
|
606
610
|
}
|
|
607
611
|
const cachedText = cacheAdapter?.get(id);
|
|
608
612
|
if (cachedText === text) {
|
|
609
613
|
displayedRef.current = text;
|
|
610
614
|
setDisplayedText(text);
|
|
611
|
-
shouldAnimateRef.current = false;
|
|
612
615
|
return;
|
|
613
616
|
}
|
|
614
|
-
if (
|
|
615
|
-
shouldAnimateRef.current = true;
|
|
616
|
-
}
|
|
617
|
-
if (!shouldAnimateRef.current) {
|
|
617
|
+
if (!text.startsWith(displayedRef.current)) {
|
|
618
618
|
displayedRef.current = text;
|
|
619
619
|
setDisplayedText(text);
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
if (!text.startsWith(displayedRef.current)) {
|
|
623
|
-
displayedRef.current = "";
|
|
624
|
-
setDisplayedText("");
|
|
625
620
|
}
|
|
626
621
|
const tick = (timestamp) => {
|
|
627
622
|
const previousTimestamp = lastFrameAtRef.current ?? timestamp;
|
|
628
623
|
lastFrameAtRef.current = timestamp;
|
|
629
624
|
const target = targetRef.current;
|
|
630
625
|
const current = displayedRef.current;
|
|
631
|
-
if (current
|
|
632
|
-
|
|
626
|
+
if (!streamingRef.current || reduceMotionRef.current) {
|
|
627
|
+
displayedRef.current = target;
|
|
628
|
+
setDisplayedText(target);
|
|
633
629
|
rafRef.current = null;
|
|
634
630
|
return;
|
|
635
631
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
632
|
+
if (!target.startsWith(current)) {
|
|
633
|
+
displayedRef.current = target;
|
|
634
|
+
setDisplayedText(target);
|
|
635
|
+
progressRemainderRef.current = 0;
|
|
636
|
+
rafRef.current = window.requestAnimationFrame(tick);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
const pending = target.slice(current.length);
|
|
640
|
+
const pendingOffsets = graphemeEndOffsets(pending);
|
|
641
|
+
if (pendingOffsets.length === 0) {
|
|
642
|
+
rafRef.current = window.requestAnimationFrame(tick);
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
const elapsedMs = Math.max(0, timestamp - previousTimestamp);
|
|
646
|
+
const targetIdleMs = targetUpdatedAtRef.current === null ? STREAM_IDLE_RELEASE_MS : Math.max(0, timestamp - targetUpdatedAtRef.current);
|
|
647
|
+
const runway = targetIdleMs >= STREAM_IDLE_RELEASE_MS ? 0 : Math.min(
|
|
648
|
+
pendingOffsets.length - 1,
|
|
649
|
+
Math.max(1, Math.ceil(charsPerSecond * STREAM_RUNWAY_MS / 1e3))
|
|
643
650
|
);
|
|
644
|
-
const
|
|
645
|
-
|
|
646
|
-
|
|
651
|
+
const eligibleGraphemes = pendingOffsets.length - runway;
|
|
652
|
+
progressRemainderRef.current += elapsedMs / 1e3 * charsPerSecond;
|
|
653
|
+
let step = Math.floor(progressRemainderRef.current);
|
|
654
|
+
if (current.length === 0 && eligibleGraphemes > 0) step = Math.max(1, step);
|
|
655
|
+
const catchupStep = pendingOffsets.length > catchupThreshold ? Math.min(maxCatchupChars, Math.ceil(pendingOffsets.length / 10)) : 0;
|
|
656
|
+
step = Math.min(eligibleGraphemes, Math.max(step, catchupStep));
|
|
657
|
+
if (step > 0) {
|
|
658
|
+
progressRemainderRef.current = Math.max(0, progressRemainderRef.current - step);
|
|
659
|
+
const next = current + pending.slice(0, pendingOffsets[step - 1]);
|
|
660
|
+
displayedRef.current = next;
|
|
661
|
+
setDisplayedText(next);
|
|
662
|
+
}
|
|
647
663
|
rafRef.current = window.requestAnimationFrame(tick);
|
|
648
664
|
};
|
|
649
|
-
if (rafRef.current === null
|
|
665
|
+
if (rafRef.current === null) {
|
|
650
666
|
rafRef.current = window.requestAnimationFrame(tick);
|
|
651
667
|
}
|
|
652
668
|
return () => {
|
|
@@ -655,10 +671,12 @@ function useStreamingText({
|
|
|
655
671
|
rafRef.current = null;
|
|
656
672
|
}
|
|
657
673
|
lastFrameAtRef.current = null;
|
|
674
|
+
progressRemainderRef.current = 0;
|
|
658
675
|
};
|
|
659
|
-
}, [cacheAdapter, catchupThreshold, charsPerSecond, id, isStreaming, maxCatchupChars
|
|
676
|
+
}, [cacheAdapter, catchupThreshold, charsPerSecond, id, isStreaming, maxCatchupChars]);
|
|
677
|
+
const reduceMotion = typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
660
678
|
return {
|
|
661
|
-
displayedText,
|
|
679
|
+
displayedText: !isStreaming || reduceMotion ? text : displayedText,
|
|
662
680
|
isAnimating: isStreaming,
|
|
663
681
|
mode: isStreaming ? "streaming" : "static",
|
|
664
682
|
parseIncompleteMarkdown: isStreaming
|
|
@@ -669,8 +687,6 @@ function useStreamingText({
|
|
|
669
687
|
var import_message_scroller2 = require("@shadcn/react/message-scroller");
|
|
670
688
|
// Annotate the CommonJS export names for ESM import in node:
|
|
671
689
|
0 && (module.exports = {
|
|
672
|
-
DefaultChatPart,
|
|
673
|
-
DefaultToolPart,
|
|
674
690
|
LatestThreadScroller,
|
|
675
691
|
LatestThreadScrollerButton,
|
|
676
692
|
LatestThreadScrollerContent,
|
|
@@ -680,9 +696,10 @@ var import_message_scroller2 = require("@shadcn/react/message-scroller");
|
|
|
680
696
|
LatestThreadScrollerRoot,
|
|
681
697
|
LatestThreadScrollerViewport,
|
|
682
698
|
MessageScroller,
|
|
699
|
+
browserChatCrypto,
|
|
700
|
+
createMcpPkceProof,
|
|
683
701
|
getActiveStreamingTextPartId,
|
|
684
702
|
isActiveStreamingTextPart,
|
|
685
|
-
renderChatPart,
|
|
686
703
|
useMessageScroller,
|
|
687
704
|
useMessageScrollerScrollable,
|
|
688
705
|
useMessageScrollerVisibility,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/latest-thread-scroller.tsx","../src/mcp-oauth.ts","../src/renderers.tsx","../src/streaming-text.ts","../src/viewport.ts"],"sourcesContent":["export * from \"./latest-thread-scroller\";\nexport * from \"./mcp-oauth\";\nexport * from \"./renderers\";\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\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\nexport type LatestThreadScrollerProviderProps = MessageScrollerProviderProps;\n\nexport function LatestThreadScrollerProvider({\n autoScroll = true,\n defaultScrollPosition = \"last-anchor\",\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 );\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-8 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};\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}: 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 top-[46%] z-10 max-h-[min(18rem,calc(100%-10rem))] w-16 -translate-y-1/2 overflow-visible\",\n hasSideRoom ? \"hidden md:block\" : \"hidden\",\n railSide === \"left\" ? \"left-1\" : \"right-1\",\n className\n )}\n dir={dir}\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 barOpacity = isFocused ? 1 : isNear ? 0.78 : isNextNear ? 0.58 : 0.36;\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 bg-muted-foreground/55 transition-[width,background-color,opacity] duration-150 ease-out group-hover:bg-foreground group-focus-visible:bg-foreground group-data-[active=true]:bg-foreground\"\n style={{\n opacity: barOpacity,\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\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 type {\n Agents24ChatRenderOptions,\n ChatMessage,\n ChatPart,\n ChatToolPart,\n} from \"./types\";\n\nexport const DefaultToolPart = ({ part }: { part: ChatToolPart }) => {\n const label =\n typeof part.presentation?.activity === \"string\"\n ? part.presentation.activity\n : typeof part.presentation?.title === \"string\"\n ? part.presentation.title\n : part.toolName;\n const detail =\n typeof part.presentation?.detail === \"string\"\n ? part.presentation.detail\n : part.errorText || part.state;\n\n return (\n <div data-agents24-tool-part={part.type} data-state={part.state}>\n <div>{label}</div>\n {detail ? <div>{detail}</div> : null}\n </div>\n );\n};\n\nexport const DefaultChatPart = ({\n part,\n message,\n renderOptions,\n}: {\n part: ChatPart;\n message: ChatMessage;\n renderOptions?: Agents24ChatRenderOptions;\n}) => {\n if (renderOptions?.renderPart) {\n return <>{renderOptions.renderPart(part, message)}</>;\n }\n\n if (part.kind === \"text\") return <>{part.text}</>;\n\n if (part.kind === \"tool\") {\n const ToolRenderer =\n renderOptions?.toolRenderers?.[part.type] ||\n renderOptions?.fallbackToolRenderer ||\n DefaultToolPart;\n return <>{ToolRenderer({ part, message })}</>;\n }\n\n if (part.kind === \"reasoning\") {\n return <div data-agents24-reasoning-part>{part.text || part.label}</div>;\n }\n\n if (part.kind === \"ui-blocks\") {\n return <div data-agents24-ui-blocks-part data-state={part.state} />;\n }\n\n if (part.kind === \"hitl\") {\n return <div data-agents24-hitl-part={part.interruptId || \"\"} />;\n }\n\n if (part.kind === \"error\") {\n return <div data-agents24-error-part>{part.errorText}</div>;\n }\n\n if (part.kind === \"data\") {\n return <div data-agents24-data-part={part.name} />;\n }\n\n return null;\n};\n\nexport const renderChatPart = (\n part: ChatPart,\n message: ChatMessage,\n renderOptions?: Agents24ChatRenderOptions\n) => (\n <DefaultChatPart\n key={part.id}\n part={part}\n message={message}\n renderOptions={renderOptions}\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 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 return (\n message.parts\n .slice()\n .reverse()\n .find((part) => part.kind === \"text\")?.id || null\n );\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\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 idRef = useRef(id);\n const shouldAnimateRef = useRef(isStreaming);\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 }, [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 shouldAnimateRef.current = isStreaming && initial !== text;\n displayedRef.current = initial;\n setDisplayedText(initial);\n\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n lastFrameAtRef.current = null;\n }, [cacheAdapter, id, isStreaming, text]);\n\n useEffect(() => {\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\n if (reduceMotion) {\n displayedRef.current = text;\n setDisplayedText(text);\n shouldAnimateRef.current = false;\n return;\n }\n\n const cachedText = cacheAdapter?.get(id);\n if (cachedText === text) {\n displayedRef.current = text;\n setDisplayedText(text);\n shouldAnimateRef.current = false;\n return;\n }\n\n if (isStreaming) {\n shouldAnimateRef.current = true;\n }\n\n if (!shouldAnimateRef.current) {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n if (!text.startsWith(displayedRef.current)) {\n displayedRef.current = \"\";\n setDisplayedText(\"\");\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 (current.length >= target.length) {\n shouldAnimateRef.current = false;\n rafRef.current = null;\n return;\n }\n\n const elapsedMs = Math.max(8, timestamp - previousTimestamp);\n const charsFromTime = Math.max(1, Math.floor((elapsedMs / 1000) * charsPerSecond));\n const gap = target.length - current.length;\n const catchupStep =\n gap > catchupThreshold ? Math.min(maxCatchupChars, Math.ceil(gap / 10)) : charsFromTime;\n const nextLength = Math.min(\n target.length,\n current.length + Math.max(charsFromTime, catchupStep)\n );\n\n const next = target.slice(0, nextLength);\n displayedRef.current = next;\n setDisplayedText(next);\n rafRef.current = window.requestAnimationFrame(tick);\n };\n\n if (rafRef.current === null && displayedRef.current.length < text.length) {\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 };\n }, [cacheAdapter, catchupThreshold, charsPerSecond, id, isStreaming, maxCatchupChars, text]);\n\n return {\n 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","import_jsx_runtime","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\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\nexport type LatestThreadScrollerProviderProps = MessageScrollerProviderProps;\n\nexport function LatestThreadScrollerProvider({\n autoScroll = true,\n defaultScrollPosition = \"last-anchor\",\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 );\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-8 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};\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}: 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 top-[46%] z-10 max-h-[min(18rem,calc(100%-10rem))] w-16 -translate-y-1/2 overflow-visible\",\n hasSideRoom ? \"hidden md:block\" : \"hidden\",\n railSide === \"left\" ? \"left-1\" : \"right-1\",\n className\n )}\n dir={dir}\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 barOpacity = isFocused ? 1 : isNear ? 0.78 : isNextNear ? 0.58 : 0.36;\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 bg-muted-foreground/55 transition-[width,background-color,opacity] duration-150 ease-out group-hover:bg-foreground group-focus-visible:bg-foreground group-data-[active=true]:bg-foreground\"\n style={{\n opacity: barOpacity,\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"]}
|