@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.
Files changed (132) hide show
  1. package/README.md +92 -18
  2. package/compatibility.json +10 -10
  3. package/dist/chunk-SSUO4EPD.js +189 -0
  4. package/dist/chunk-SSUO4EPD.js.map +1 -0
  5. package/dist/chunk-ZCNHLFRB.js +108 -0
  6. package/dist/chunk-ZCNHLFRB.js.map +1 -0
  7. package/dist/index.cjs +112 -95
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.ts +0 -1
  10. package/dist/index.js +362 -68
  11. package/dist/index.js.map +1 -1
  12. package/dist/mcp-oauth.d.ts +13 -0
  13. package/dist/runtime/index.cjs +594 -0
  14. package/dist/runtime/index.cjs.map +1 -0
  15. package/dist/runtime/index.d.ts +2 -0
  16. package/dist/runtime/index.js +458 -0
  17. package/dist/runtime/index.js.map +1 -0
  18. package/dist/runtime/input-contract.d.ts +20 -0
  19. package/dist/runtime/use-agent-chat-runtime.d.ts +83 -0
  20. package/dist/scaffold/app.d.ts +30 -0
  21. package/dist/scaffold/components/chat/chat-composer.d.ts +21 -0
  22. package/dist/scaffold/components/chat/chat-message.d.ts +21 -0
  23. package/dist/scaffold/components/chat/chat-shell.d.ts +8 -0
  24. package/dist/scaffold/components/chat/collapsible-user-message.d.ts +3 -0
  25. package/dist/scaffold/components/chat/external-link-dialog.d.ts +2 -0
  26. package/dist/scaffold/components/chat/identity-control.d.ts +4 -0
  27. package/dist/scaffold/components/chat/message-parts.d.ts +12 -0
  28. package/dist/scaffold/components/chat/theme-menu.d.ts +1 -0
  29. package/dist/scaffold/components/chat/thread-sidebar.d.ts +16 -0
  30. package/dist/scaffold/components/chat/timeline-loading.d.ts +7 -0
  31. package/dist/scaffold/components/chat/turn-outline.d.ts +4 -0
  32. package/dist/scaffold/components/theme-provider.d.ts +20 -0
  33. package/dist/scaffold/components/ui/attachment.d.ts +24 -0
  34. package/dist/scaffold/components/ui/bubble.d.ts +17 -0
  35. package/dist/scaffold/components/ui/button-group.d.ts +11 -0
  36. package/dist/scaffold/components/ui/button.d.ts +10 -0
  37. package/dist/scaffold/components/ui/dialog.d.ts +17 -0
  38. package/dist/scaffold/components/ui/dropdown-menu.d.ts +29 -0
  39. package/dist/scaffold/components/ui/input.d.ts +3 -0
  40. package/dist/scaffold/components/ui/marker.d.ts +11 -0
  41. package/dist/scaffold/components/ui/message-scroller.d.ts +10 -0
  42. package/dist/scaffold/components/ui/message.d.ts +10 -0
  43. package/dist/scaffold/components/ui/popover.d.ts +6 -0
  44. package/dist/scaffold/components/ui/select.d.ts +8 -0
  45. package/dist/scaffold/components/ui/separator.d.ts +4 -0
  46. package/dist/scaffold/components/ui/sheet.d.ts +14 -0
  47. package/dist/scaffold/components/ui/sidebar.d.ts +69 -0
  48. package/dist/scaffold/components/ui/skeleton.d.ts +2 -0
  49. package/dist/scaffold/components/ui/textarea.d.ts +3 -0
  50. package/dist/scaffold/components/ui/tooltip.d.ts +15 -0
  51. package/dist/scaffold/hooks/use-mobile.d.ts +1 -0
  52. package/dist/scaffold/identity.d.ts +10 -0
  53. package/dist/scaffold/index.cjs +2270 -0
  54. package/dist/scaffold/index.cjs.map +1 -0
  55. package/dist/scaffold/index.d.ts +14 -0
  56. package/dist/scaffold/index.js +2244 -0
  57. package/dist/scaffold/index.js.map +1 -0
  58. package/dist/scaffold/lib/utils.d.ts +2 -0
  59. package/dist/styles.css +143 -298
  60. package/dist/types.d.ts +3 -13
  61. package/dist/ui/adapters.d.ts +1 -1
  62. package/dist/ui/agent-chat-actions.d.ts +12 -5
  63. package/dist/ui/agent-chat-composer.d.ts +2 -1
  64. package/dist/ui/agent-chat-context-compression-row.d.ts +5 -0
  65. package/dist/ui/agent-chat-context-status.d.ts +13 -0
  66. package/dist/ui/agent-chat-message.d.ts +7 -5
  67. package/dist/ui/agent-response-timeline.d.ts +29 -7
  68. package/dist/ui/ask-user-interaction-state.d.ts +20 -0
  69. package/dist/ui/ask-user-interaction.d.ts +8 -0
  70. package/dist/ui/index.cjs +1392 -272
  71. package/dist/ui/index.cjs.map +1 -1
  72. package/dist/ui/index.d.ts +5 -0
  73. package/dist/ui/index.js +2380 -65
  74. package/dist/ui/index.js.map +1 -1
  75. package/dist/ui/tool-sessions.d.ts +70 -0
  76. package/dist/ui/use-audio-recorder.d.ts +8 -0
  77. package/package.json +27 -12
  78. package/scaffold/components.json +25 -0
  79. package/scaffold/manifest.json +28 -0
  80. package/scaffold/src/app.tsx +71 -0
  81. package/scaffold/src/chat.css +54 -0
  82. package/scaffold/src/components/chat/chat-composer.tsx +237 -0
  83. package/scaffold/src/components/chat/chat-message.tsx +76 -0
  84. package/scaffold/src/components/chat/chat-shell.tsx +257 -0
  85. package/scaffold/src/components/chat/collapsible-user-message.tsx +37 -0
  86. package/scaffold/src/components/chat/external-link-dialog.tsx +48 -0
  87. package/scaffold/src/components/chat/identity-control.tsx +69 -0
  88. package/scaffold/src/components/chat/message-parts.tsx +83 -0
  89. package/scaffold/src/components/chat/theme-menu.tsx +79 -0
  90. package/scaffold/src/components/chat/thread-sidebar.tsx +114 -0
  91. package/scaffold/src/components/chat/timeline-loading.ts +17 -0
  92. package/scaffold/src/components/chat/turn-outline.tsx +73 -0
  93. package/scaffold/src/components/theme-provider.tsx +91 -0
  94. package/scaffold/src/components/ui/attachment.tsx +204 -0
  95. package/scaffold/src/components/ui/bubble.tsx +125 -0
  96. package/scaffold/src/components/ui/button-group.tsx +83 -0
  97. package/scaffold/src/components/ui/button.tsx +65 -0
  98. package/scaffold/src/components/ui/dialog.tsx +171 -0
  99. package/scaffold/src/components/ui/dropdown-menu.tsx +271 -0
  100. package/scaffold/src/components/ui/input.tsx +19 -0
  101. package/scaffold/src/components/ui/marker.tsx +69 -0
  102. package/scaffold/src/components/ui/message-scroller.tsx +129 -0
  103. package/scaffold/src/components/ui/message.tsx +92 -0
  104. package/scaffold/src/components/ui/popover.tsx +40 -0
  105. package/scaffold/src/components/ui/select.tsx +92 -0
  106. package/scaffold/src/components/ui/separator.tsx +28 -0
  107. package/scaffold/src/components/ui/sheet.tsx +150 -0
  108. package/scaffold/src/components/ui/sidebar.tsx +677 -0
  109. package/scaffold/src/components/ui/skeleton.tsx +13 -0
  110. package/scaffold/src/components/ui/textarea.tsx +18 -0
  111. package/scaffold/src/components/ui/tooltip.tsx +56 -0
  112. package/scaffold/src/hooks/use-mobile.ts +24 -0
  113. package/scaffold/src/identity.ts +17 -0
  114. package/scaffold/src/index.css +222 -0
  115. package/scaffold/src/index.tsx +39 -0
  116. package/scaffold/src/lib/utils.ts +6 -0
  117. package/scaffold/styles.css +3 -0
  118. package/dist/chunk-CHAU7FNW.js +0 -140
  119. package/dist/chunk-CHAU7FNW.js.map +0 -1
  120. package/dist/chunk-LI67M74F.js +0 -445
  121. package/dist/chunk-LI67M74F.js.map +0 -1
  122. package/dist/chunk-NLEOWTZG.js +0 -1327
  123. package/dist/chunk-NLEOWTZG.js.map +0 -1
  124. package/dist/renderers.d.ts +0 -10
  125. package/dist/templates/agent-chat-app.d.ts +0 -18
  126. package/dist/templates/agent-chat-layout.d.ts +0 -69
  127. package/dist/templates/agent-chat-shell.d.ts +0 -37
  128. package/dist/templates/index.cjs +0 -2476
  129. package/dist/templates/index.cjs.map +0 -1
  130. package/dist/templates/index.d.ts +0 -3
  131. package/dist/templates/index.js +0 -723
  132. package/dist/templates/index.js.map +0 -1
@@ -1,445 +0,0 @@
1
- // src/latest-thread-scroller.tsx
2
- import * as React from "react";
3
- import {
4
- MessageScroller,
5
- useMessageScroller,
6
- useMessageScrollerVisibility
7
- } from "@shadcn/react/message-scroller";
8
- import { jsx, jsxs } from "react/jsx-runtime";
9
- var cx = (...values) => values.filter(Boolean).join(" ");
10
- var LatestThreadScrollerLayoutContext = React.createContext(null);
11
- var useLatestThreadScrollerLayout = () => React.useContext(LatestThreadScrollerLayoutContext);
12
- function LatestThreadScrollerProvider({
13
- autoScroll = true,
14
- defaultScrollPosition = "last-anchor",
15
- scrollPreviousItemPeek = 64,
16
- ...props
17
- }) {
18
- return /* @__PURE__ */ jsx(
19
- MessageScroller.Provider,
20
- {
21
- autoScroll,
22
- defaultScrollPosition,
23
- scrollPreviousItemPeek,
24
- ...props
25
- }
26
- );
27
- }
28
- function LatestThreadScrollerRoot({
29
- className,
30
- ref,
31
- ...props
32
- }) {
33
- const [rootElement, setRootElement] = React.useState(null);
34
- const [contentElement, setContentElement] = React.useState(null);
35
- const layoutContext = React.useMemo(
36
- () => ({
37
- contentElement,
38
- rootElement,
39
- setContentElement,
40
- setRootElement
41
- }),
42
- [contentElement, rootElement]
43
- );
44
- const setRef = React.useCallback(
45
- (node) => {
46
- setRootElement(node);
47
- if (typeof ref === "function") {
48
- ref(node);
49
- } else if (ref) {
50
- ref.current = node;
51
- }
52
- },
53
- [ref]
54
- );
55
- return /* @__PURE__ */ jsx(LatestThreadScrollerLayoutContext.Provider, { value: layoutContext, children: /* @__PURE__ */ jsx(
56
- MessageScroller.Root,
57
- {
58
- ref: setRef,
59
- className: cx(
60
- "a24-scroller relative flex size-full min-h-0 flex-1 flex-col overflow-hidden",
61
- className
62
- ),
63
- ...props
64
- }
65
- ) });
66
- }
67
- function LatestThreadScrollerViewport({
68
- className,
69
- onViewportChange,
70
- preserveScrollOnPrepend = true,
71
- ref,
72
- ...props
73
- }) {
74
- const setRef = React.useCallback(
75
- (node) => {
76
- if (typeof ref === "function") {
77
- ref(node);
78
- } else if (ref) {
79
- ref.current = node;
80
- }
81
- onViewportChange?.(node);
82
- },
83
- [onViewportChange, ref]
84
- );
85
- return /* @__PURE__ */ jsx(
86
- MessageScroller.Viewport,
87
- {
88
- ref: setRef,
89
- className: cx(
90
- "a24-scroller__viewport size-full min-h-0 min-w-0 flex-1 overflow-y-auto overscroll-contain",
91
- className
92
- ),
93
- preserveScrollOnPrepend,
94
- ...props
95
- }
96
- );
97
- }
98
- function LatestThreadScrollerContent({
99
- className,
100
- ref,
101
- ...props
102
- }) {
103
- const layout = useLatestThreadScrollerLayout();
104
- const setRef = React.useCallback(
105
- (node) => {
106
- layout?.setContentElement(node);
107
- if (typeof ref === "function") {
108
- ref(node);
109
- } else if (ref) {
110
- ref.current = node;
111
- }
112
- },
113
- [layout, ref]
114
- );
115
- return /* @__PURE__ */ jsx(
116
- MessageScroller.Content,
117
- {
118
- ref: setRef,
119
- "data-agents24-latest-thread-content": "",
120
- className: cx("a24-scroller__content flex h-max min-h-full flex-col gap-8 p-4", className),
121
- ...props
122
- }
123
- );
124
- }
125
- function LatestThreadScrollerItem({
126
- className,
127
- messageId,
128
- ...props
129
- }) {
130
- return /* @__PURE__ */ jsx(
131
- MessageScroller.Item,
132
- {
133
- className: cx(
134
- "a24-scroller__item min-w-0 shrink-0 overflow-visible",
135
- className
136
- ),
137
- messageId,
138
- ...props
139
- }
140
- );
141
- }
142
- function LatestThreadScrollerButton({
143
- children,
144
- className,
145
- direction = "end",
146
- render,
147
- ...props
148
- }) {
149
- if (render) {
150
- return /* @__PURE__ */ jsx(
151
- MessageScroller.Button,
152
- {
153
- direction,
154
- render,
155
- ...props
156
- }
157
- );
158
- }
159
- return /* @__PURE__ */ jsx(
160
- MessageScroller.Button,
161
- {
162
- direction,
163
- render: (buttonProps) => /* @__PURE__ */ jsx(
164
- "button",
165
- {
166
- ...buttonProps,
167
- "aria-label": direction === "end" ? "Scroll to latest message" : "Scroll to first message",
168
- className: cx(
169
- "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",
170
- className
171
- ),
172
- type: "button",
173
- children: children ?? (direction === "end" ? "\u2193" : "\u2191")
174
- }
175
- ),
176
- ...props
177
- }
178
- );
179
- }
180
- function LatestThreadScrollerOutline({
181
- cardClassName,
182
- className,
183
- contentMaxWidth = 768,
184
- dir = "ltr",
185
- items,
186
- minContainerWidthForRail = 0,
187
- minSideGutterForRail = 48,
188
- side
189
- }) {
190
- const navRef = React.useRef(null);
191
- const layout = useLatestThreadScrollerLayout();
192
- const [hasSideRoom, setHasSideRoom] = React.useState(false);
193
- const [hoveredIndex, setHoveredIndex] = React.useState(null);
194
- const { scrollToMessage } = useMessageScroller();
195
- const { currentAnchorId, visibleMessageIds } = useMessageScrollerVisibility();
196
- const visibleMessageIdSet = React.useMemo(
197
- () => new Set(visibleMessageIds),
198
- [visibleMessageIds]
199
- );
200
- const focusIndex = hoveredIndex ?? -1;
201
- const railSide = side ?? (dir === "rtl" ? "right" : "left");
202
- React.useEffect(() => {
203
- const root = layout?.rootElement ?? navRef.current?.parentElement;
204
- if (!root) return;
205
- const updateSideRoom = () => {
206
- const rootRect = root.getBoundingClientRect();
207
- const rootWidth = rootRect.width;
208
- const content2 = layout?.contentElement;
209
- const sideGutter = content2 ? Math.max(
210
- 0,
211
- railSide === "left" ? content2.getBoundingClientRect().left - rootRect.left : rootRect.right - content2.getBoundingClientRect().right
212
- ) : Math.max(0, (rootWidth - contentMaxWidth) / 2);
213
- const nextHasSideRoom = rootWidth >= minContainerWidthForRail && sideGutter >= minSideGutterForRail;
214
- setHasSideRoom(
215
- (current) => current === nextHasSideRoom ? current : nextHasSideRoom
216
- );
217
- };
218
- updateSideRoom();
219
- if (typeof ResizeObserver === "undefined") return;
220
- const resizeObserver = new ResizeObserver(updateSideRoom);
221
- resizeObserver.observe(root);
222
- const content = layout?.contentElement;
223
- if (content) {
224
- resizeObserver.observe(content);
225
- }
226
- return () => resizeObserver.disconnect();
227
- }, [
228
- contentMaxWidth,
229
- layout?.contentElement,
230
- layout?.rootElement,
231
- minContainerWidthForRail,
232
- minSideGutterForRail,
233
- railSide
234
- ]);
235
- if (items.length < 2) {
236
- return null;
237
- }
238
- return /* @__PURE__ */ jsx(
239
- "nav",
240
- {
241
- ref: navRef,
242
- "aria-label": "Transcript outline",
243
- "data-side": railSide,
244
- "data-visible": hasSideRoom ? "" : void 0,
245
- className: cx(
246
- "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",
247
- hasSideRoom ? "hidden md:block" : "hidden",
248
- railSide === "left" ? "left-1" : "right-1",
249
- className
250
- ),
251
- dir,
252
- children: /* @__PURE__ */ jsx("div", { className: "a24-outline__rail pointer-events-auto flex flex-col gap-0 py-1", children: items.map((item, index) => {
253
- const itemMessageIds = item.messageIds && item.messageIds.length > 0 ? item.messageIds : [item.id];
254
- const active = itemMessageIds.some(
255
- (messageId) => visibleMessageIdSet.has(messageId) || messageId === currentAnchorId
256
- );
257
- const distance = focusIndex >= 0 ? Math.abs(index - focusIndex) : Number.POSITIVE_INFINITY;
258
- const isFocused = distance === 0;
259
- const isNear = distance === 1;
260
- const isNextNear = distance === 2;
261
- const barWidth = isFocused ? 50 : isNear ? 36 : isNextNear ? 23 : 10;
262
- const barOpacity = isFocused ? 1 : isNear ? 0.78 : isNextNear ? 0.58 : 0.36;
263
- const fallbackLabel = `Turn ${index + 1}`;
264
- const previewLabel = item.label && item.label !== fallbackLabel ? item.label : "";
265
- const responsePreview = (item.responsePreview || "").trim();
266
- return /* @__PURE__ */ jsxs(
267
- "button",
268
- {
269
- type: "button",
270
- "data-active": active,
271
- "data-side": railSide,
272
- dir: "ltr",
273
- className: cx(
274
- "a24-outline__button group relative flex h-2 w-16 items-center rounded-sm outline-none",
275
- railSide === "left" ? "justify-start" : "justify-end"
276
- ),
277
- "aria-label": `Jump to ${item.label || fallbackLabel}`,
278
- onBlur: () => setHoveredIndex(null),
279
- onFocus: () => setHoveredIndex(index),
280
- onMouseEnter: () => setHoveredIndex(index),
281
- onMouseLeave: () => setHoveredIndex(null),
282
- onClick: () => scrollToMessage(item.id, {
283
- align: "start",
284
- behavior: "smooth"
285
- }),
286
- children: [
287
- /* @__PURE__ */ jsx(
288
- "span",
289
- {
290
- 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",
291
- style: {
292
- opacity: barOpacity,
293
- width: barWidth
294
- }
295
- }
296
- ),
297
- previewLabel ? /* @__PURE__ */ jsxs(
298
- "span",
299
- {
300
- dir,
301
- className: cx(
302
- "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",
303
- railSide === "left" ? "left-full ml-2 -translate-x-1 group-hover:translate-x-0 group-focus-visible:translate-x-0" : "right-full mr-2 translate-x-1 group-hover:translate-x-0 group-focus-visible:translate-x-0",
304
- cardClassName
305
- ),
306
- children: [
307
- /* @__PURE__ */ jsx(
308
- "span",
309
- {
310
- className: "block overflow-hidden text-sm leading-5 text-foreground",
311
- style: {
312
- display: "-webkit-box",
313
- WebkitBoxOrient: "vertical",
314
- WebkitLineClamp: responsePreview ? 2 : 4
315
- },
316
- children: previewLabel
317
- }
318
- ),
319
- responsePreview ? /* @__PURE__ */ jsx(
320
- "span",
321
- {
322
- className: "mt-1 block overflow-hidden text-sm leading-5 text-muted-foreground",
323
- style: {
324
- display: "-webkit-box",
325
- WebkitBoxOrient: "vertical",
326
- WebkitLineClamp: 2
327
- },
328
- children: responsePreview
329
- }
330
- ) : null
331
- ]
332
- }
333
- ) : null
334
- ]
335
- },
336
- item.id
337
- );
338
- }) })
339
- }
340
- );
341
- }
342
- var LatestThreadScroller = {
343
- Provider: LatestThreadScrollerProvider,
344
- Root: LatestThreadScrollerRoot,
345
- Viewport: LatestThreadScrollerViewport,
346
- Content: LatestThreadScrollerContent,
347
- Item: LatestThreadScrollerItem,
348
- Button: LatestThreadScrollerButton,
349
- Outline: LatestThreadScrollerOutline
350
- };
351
-
352
- // src/mcp-oauth.ts
353
- 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;
354
- function isLoopback(hostname) {
355
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
356
- }
357
- function normalizedOrigin(value) {
358
- try {
359
- const url = new URL(value);
360
- if (url.protocol !== "https:" && !(url.protocol === "http:" && isLoopback(url.hostname))) {
361
- throw new Error("unsafe callback origin");
362
- }
363
- if (url.origin === "null") throw new Error("opaque callback origin");
364
- return url.origin;
365
- } catch {
366
- throw new Error("MCP authorization returned an invalid callback origin.");
367
- }
368
- }
369
- function validateMcpCallbackResult(result, expectedServerId) {
370
- const serverId = String(result.server_id || "").trim();
371
- const connectionId = String(result.connection_id || "").trim();
372
- if (!serverId || serverId !== expectedServerId) {
373
- throw new Error("MCP authorization completed for an unexpected server.");
374
- }
375
- if (!UUID_PATTERN.test(connectionId)) {
376
- throw new Error("MCP authorization returned an invalid connection identity.");
377
- }
378
- return result;
379
- }
380
- function waitForMcpOauthComplete({
381
- popup,
382
- callbackOrigin,
383
- popupNonce,
384
- requireConnectionId = false,
385
- serverId,
386
- timeoutMs = 12e4
387
- }) {
388
- if (!popup) return Promise.reject(new Error("Could not open the MCP authorization popup."));
389
- const expectedOrigin = normalizedOrigin(callbackOrigin);
390
- const expectedServerId = String(serverId || "").trim();
391
- const expectedPopupNonce = String(popupNonce || "").trim();
392
- if (!expectedServerId) return Promise.reject(new Error("MCP authorization is missing its server identity."));
393
- if (!expectedPopupNonce) return Promise.reject(new Error("MCP authorization is missing its popup binding."));
394
- const returnFocusTo = typeof document !== "undefined" ? document.activeElement : null;
395
- return new Promise((resolve, reject) => {
396
- let settled = false;
397
- const finish = (result) => {
398
- if (settled) return;
399
- settled = true;
400
- window.clearTimeout(timeout);
401
- window.clearInterval(closeTimer);
402
- window.removeEventListener("message", onMessage);
403
- returnFocusTo?.focus?.();
404
- if (result instanceof Error) reject(result);
405
- else resolve(result);
406
- };
407
- const onMessage = (event) => {
408
- if (event.source !== popup || event.origin !== expectedOrigin) return;
409
- const data = event.data;
410
- if (data?.type !== "agents24.mcp.callback" || data.server_id !== expectedServerId || data.popup_nonce !== expectedPopupNonce) return;
411
- const code = String(data.code || "").trim();
412
- if (!code || code.length > 2048) return;
413
- const connectionId = String(data.connection_id || "").trim();
414
- if ((requireConnectionId || connectionId) && !UUID_PATTERN.test(connectionId)) return;
415
- finish({
416
- code,
417
- ...connectionId ? { connectionId } : {},
418
- popupNonce: expectedPopupNonce,
419
- serverId: expectedServerId
420
- });
421
- };
422
- const timeout = window.setTimeout(
423
- () => finish(new Error("MCP authorization timed out.")),
424
- Math.max(1, timeoutMs)
425
- );
426
- const closeTimer = window.setInterval(() => {
427
- if (popup.closed) finish(new Error("MCP authorization window was closed before connecting."));
428
- }, 500);
429
- window.addEventListener("message", onMessage);
430
- });
431
- }
432
-
433
- export {
434
- LatestThreadScrollerProvider,
435
- LatestThreadScrollerRoot,
436
- LatestThreadScrollerViewport,
437
- LatestThreadScrollerContent,
438
- LatestThreadScrollerItem,
439
- LatestThreadScrollerButton,
440
- LatestThreadScrollerOutline,
441
- LatestThreadScroller,
442
- validateMcpCallbackResult,
443
- waitForMcpOauthComplete
444
- };
445
- //# sourceMappingURL=chunk-LI67M74F.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/latest-thread-scroller.tsx","../src/mcp-oauth.ts"],"sourcesContent":["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"],"mappings":"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","names":["content"]}