@agents24/chat-react 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +25 -12
  2. package/dist/chunk-E3TJ3I6G.js +358 -0
  3. package/dist/chunk-E3TJ3I6G.js.map +1 -0
  4. package/dist/chunk-EWZO4QJI.js +140 -0
  5. package/dist/chunk-EWZO4QJI.js.map +1 -0
  6. package/dist/chunk-UU7OXHL3.js +11 -0
  7. package/dist/chunk-UU7OXHL3.js.map +1 -0
  8. package/dist/context-window.d.ts +38 -0
  9. package/dist/controller.d.ts +22 -0
  10. package/dist/index.cjs +392 -314
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.ts +10 -530
  13. package/dist/index.js +41 -439
  14. package/dist/index.js.map +1 -1
  15. package/dist/latest-thread-scroller.d.ts +54 -0
  16. package/dist/model.d.ts +29 -0
  17. package/dist/renderers.d.ts +10 -0
  18. package/dist/sse.d.ts +3 -0
  19. package/dist/streaming-text.d.ts +24 -0
  20. package/dist/templates/agent-chat-shell.d.ts +25 -0
  21. package/dist/templates/index.cjs +523 -0
  22. package/dist/templates/index.cjs.map +1 -0
  23. package/dist/templates/index.d.ts +1 -0
  24. package/dist/templates/index.js +140 -0
  25. package/dist/templates/index.js.map +1 -0
  26. package/dist/transport.d.ts +29 -0
  27. package/dist/types.d.ts +312 -0
  28. package/dist/ui/adapters.d.ts +36 -0
  29. package/dist/ui/attachment.d.ts +23 -0
  30. package/dist/ui/bubble.d.ts +17 -0
  31. package/dist/ui/index.cjs +943 -0
  32. package/dist/ui/index.cjs.map +1 -0
  33. package/dist/ui/index.d.ts +7 -0
  34. package/dist/ui/index.js +734 -0
  35. package/dist/ui/index.js.map +1 -0
  36. package/dist/ui/marker.d.ts +11 -0
  37. package/dist/ui/message-response.d.ts +7 -0
  38. package/dist/ui/message.d.ts +10 -0
  39. package/dist/ui/utils.d.ts +2 -0
  40. package/dist/viewport.d.ts +2 -0
  41. package/package.json +22 -4
  42. package/dist/index.d.cts +0 -530
@@ -0,0 +1,943 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/ui/index.ts
31
+ var ui_exports = {};
32
+ __export(ui_exports, {
33
+ Attachment: () => Attachment,
34
+ AttachmentAction: () => AttachmentAction,
35
+ AttachmentActions: () => AttachmentActions,
36
+ AttachmentContent: () => AttachmentContent,
37
+ AttachmentDescription: () => AttachmentDescription,
38
+ AttachmentGroup: () => AttachmentGroup,
39
+ AttachmentMedia: () => AttachmentMedia,
40
+ AttachmentTitle: () => AttachmentTitle,
41
+ AttachmentTrigger: () => AttachmentTrigger,
42
+ Bubble: () => Bubble,
43
+ BubbleContent: () => BubbleContent,
44
+ BubbleGroup: () => BubbleGroup,
45
+ BubbleReactions: () => BubbleReactions,
46
+ ChatAttachment: () => ChatAttachment,
47
+ ChatAttachments: () => ChatAttachments,
48
+ ChatMessage: () => ChatMessage,
49
+ ChatMessageAction: () => ChatMessageAction,
50
+ ChatMessageActions: () => ChatMessageActions,
51
+ ChatMessageContent: () => ChatMessageContent,
52
+ Marker: () => Marker,
53
+ MarkerContent: () => MarkerContent,
54
+ MarkerIcon: () => MarkerIcon,
55
+ Message: () => ChatMessage,
56
+ MessageAction: () => ChatMessageAction,
57
+ MessageActions: () => ChatMessageActions,
58
+ MessageAttachment: () => ChatAttachment,
59
+ MessageAttachments: () => ChatAttachments,
60
+ MessageAvatar: () => MessageAvatar,
61
+ MessageContent: () => ChatMessageContent,
62
+ MessageFooter: () => MessageFooter,
63
+ MessageGroup: () => MessageGroup,
64
+ MessageHeader: () => MessageHeader,
65
+ MessageResponse: () => MessageResponse,
66
+ ShadcnMessage: () => Message,
67
+ ShadcnMessageContent: () => MessageContent,
68
+ attachmentMediaVariants: () => attachmentMediaVariants,
69
+ attachmentVariants: () => attachmentVariants,
70
+ bubbleVariants: () => bubbleVariants,
71
+ cn: () => cn,
72
+ markerVariants: () => markerVariants
73
+ });
74
+ module.exports = __toCommonJS(ui_exports);
75
+
76
+ // src/ui/adapters.ts
77
+ var React = __toESM(require("react"), 1);
78
+
79
+ // src/ui/attachment.tsx
80
+ var import_class_variance_authority = require("class-variance-authority");
81
+ var import_react_slot = require("@radix-ui/react-slot");
82
+
83
+ // src/ui/utils.ts
84
+ var import_clsx = require("clsx");
85
+ var import_tailwind_merge = require("tailwind-merge");
86
+ function cn(...values) {
87
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(values));
88
+ }
89
+
90
+ // src/ui/attachment.tsx
91
+ var import_jsx_runtime = require("react/jsx-runtime");
92
+ var attachmentVariants = (0, import_class_variance_authority.cva)(
93
+ "group/attachment relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border bg-card text-card-foreground transition-colors focus-within:ring-1 focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 data-[state=idle]:border-dashed",
94
+ {
95
+ variants: {
96
+ size: {
97
+ default: "gap-2 text-sm has-data-[slot=attachment-content]:px-2.5 has-data-[slot=attachment-content]:py-2 has-data-[slot=attachment-media]:p-2",
98
+ sm: "gap-2.5 text-xs has-data-[slot=attachment-content]:px-2 has-data-[slot=attachment-content]:py-1.5 has-data-[slot=attachment-media]:p-1.5",
99
+ xs: "gap-1.5 rounded-lg text-xs has-data-[slot=attachment-content]:px-1.5 has-data-[slot=attachment-content]:py-1 has-data-[slot=attachment-media]:p-1"
100
+ },
101
+ orientation: {
102
+ horizontal: "min-w-40 items-center",
103
+ vertical: "w-24 flex-col has-data-[slot=attachment-content]:w-30"
104
+ }
105
+ }
106
+ }
107
+ );
108
+ function Attachment({
109
+ className,
110
+ state = "done",
111
+ size = "default",
112
+ orientation = "horizontal",
113
+ ...props
114
+ }) {
115
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
116
+ "div",
117
+ {
118
+ "data-slot": "attachment",
119
+ "data-state": state,
120
+ "data-size": size,
121
+ "data-orientation": orientation,
122
+ className: cn(attachmentVariants({ size, orientation }), className),
123
+ ...props
124
+ }
125
+ );
126
+ }
127
+ var attachmentMediaVariants = (0, import_class_variance_authority.cva)(
128
+ "relative flex aspect-square w-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted text-foreground group-data-[orientation=vertical]/attachment:w-full group-data-[size=sm]/attachment:w-8 group-data-[size=xs]/attachment:w-7 group-data-[size=xs]/attachment:rounded-md group-data-[state=error]/attachment:bg-destructive/10 group-data-[state=error]/attachment:text-destructive group-data-[orientation=vertical]/attachment:*:data-[slot=spinner]:size-6! [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 group-data-[orientation=vertical]/attachment:[&_svg:not([class*='size-'])]:size-6 group-data-[size=xs]/attachment:[&_svg:not([class*='size-'])]:size-3.5",
129
+ {
130
+ variants: {
131
+ variant: {
132
+ icon: "",
133
+ image: "opacity-60 group-data-[state=done]/attachment:opacity-100 group-data-[state=idle]/attachment:opacity-100 *:[img]:aspect-square *:[img]:w-full *:[img]:object-cover"
134
+ }
135
+ },
136
+ defaultVariants: {
137
+ variant: "icon"
138
+ }
139
+ }
140
+ );
141
+ function AttachmentMedia({
142
+ className,
143
+ variant = "icon",
144
+ ...props
145
+ }) {
146
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
147
+ "div",
148
+ {
149
+ "data-slot": "attachment-media",
150
+ "data-variant": variant,
151
+ className: cn(attachmentMediaVariants({ variant }), className),
152
+ ...props
153
+ }
154
+ );
155
+ }
156
+ function AttachmentContent({
157
+ className,
158
+ ...props
159
+ }) {
160
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
161
+ "div",
162
+ {
163
+ "data-slot": "attachment-content",
164
+ className: cn(
165
+ "max-w-full min-w-0 flex-1 leading-tight group-data-[orientation=vertical]/attachment:px-1",
166
+ className
167
+ ),
168
+ ...props
169
+ }
170
+ );
171
+ }
172
+ function AttachmentTitle({
173
+ className,
174
+ ...props
175
+ }) {
176
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
177
+ "span",
178
+ {
179
+ "data-slot": "attachment-title",
180
+ className: cn(
181
+ "block max-w-full min-w-0 truncate font-medium group-data-[state=processing]/attachment:shimmer group-data-[state=uploading]/attachment:shimmer",
182
+ className
183
+ ),
184
+ ...props
185
+ }
186
+ );
187
+ }
188
+ function AttachmentDescription({
189
+ className,
190
+ ...props
191
+ }) {
192
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
193
+ "span",
194
+ {
195
+ "data-slot": "attachment-description",
196
+ className: cn(
197
+ "mt-0.5 block min-w-0 truncate text-xs text-muted-foreground group-data-[state=error]/attachment:text-destructive/80",
198
+ "max-w-full",
199
+ className
200
+ ),
201
+ ...props
202
+ }
203
+ );
204
+ }
205
+ function AttachmentActions({
206
+ className,
207
+ ...props
208
+ }) {
209
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
210
+ "div",
211
+ {
212
+ "data-slot": "attachment-actions",
213
+ className: cn(
214
+ "relative z-20 flex shrink-0 items-center group-data-[orientation=vertical]/attachment:absolute group-data-[orientation=vertical]/attachment:top-3 group-data-[orientation=vertical]/attachment:right-3 group-data-[orientation=vertical]/attachment:gap-1",
215
+ className
216
+ ),
217
+ ...props
218
+ }
219
+ );
220
+ }
221
+ function AttachmentAction({
222
+ className,
223
+ type = "button",
224
+ ...props
225
+ }) {
226
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
227
+ "button",
228
+ {
229
+ "data-slot": "attachment-action",
230
+ type,
231
+ className: cn(
232
+ "inline-flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
233
+ className
234
+ ),
235
+ ...props
236
+ }
237
+ );
238
+ }
239
+ function AttachmentTrigger({
240
+ className,
241
+ asChild = false,
242
+ type,
243
+ ...props
244
+ }) {
245
+ const Comp = asChild ? import_react_slot.Slot : "button";
246
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
247
+ Comp,
248
+ {
249
+ "data-slot": "attachment-trigger",
250
+ type: asChild ? void 0 : type ?? "button",
251
+ className: cn("absolute inset-0 z-10 outline-none", className),
252
+ ...props
253
+ }
254
+ );
255
+ }
256
+ function AttachmentGroup({ className, ...props }) {
257
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
258
+ "div",
259
+ {
260
+ "data-slot": "attachment-group",
261
+ className: cn(
262
+ "flex min-w-0 scroll-fade-x snap-x snap-mandatory scroll-px-1 scrollbar-none gap-3 overflow-x-auto overscroll-x-contain py-1 *:data-[slot=attachment]:flex-none *:data-[slot=attachment]:snap-start",
263
+ className
264
+ ),
265
+ ...props
266
+ }
267
+ );
268
+ }
269
+
270
+ // src/ui/bubble.tsx
271
+ var import_class_variance_authority2 = require("class-variance-authority");
272
+ var import_react_slot2 = require("@radix-ui/react-slot");
273
+ var import_jsx_runtime2 = require("react/jsx-runtime");
274
+ function BubbleGroup({ className, ...props }) {
275
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
276
+ "div",
277
+ {
278
+ "data-slot": "bubble-group",
279
+ className: cn("flex min-w-0 flex-col gap-2", className),
280
+ ...props
281
+ }
282
+ );
283
+ }
284
+ var bubbleVariants = (0, import_class_variance_authority2.cva)(
285
+ "group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
286
+ {
287
+ variants: {
288
+ variant: {
289
+ default: "*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80",
290
+ secondary: "*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]",
291
+ muted: "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]",
292
+ tinted: "*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]",
293
+ outline: "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30",
294
+ ghost: "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50",
295
+ destructive: "*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30"
296
+ }
297
+ },
298
+ defaultVariants: {
299
+ variant: "default"
300
+ }
301
+ }
302
+ );
303
+ function Bubble({
304
+ variant = "default",
305
+ align = "start",
306
+ className,
307
+ ...props
308
+ }) {
309
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
310
+ "div",
311
+ {
312
+ "data-slot": "bubble",
313
+ "data-variant": variant,
314
+ "data-align": align,
315
+ className: cn(bubbleVariants({ variant }), className),
316
+ ...props
317
+ }
318
+ );
319
+ }
320
+ function BubbleContent({
321
+ asChild = false,
322
+ className,
323
+ ...props
324
+ }) {
325
+ const Comp = asChild ? import_react_slot2.Slot : "div";
326
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
327
+ Comp,
328
+ {
329
+ "data-slot": "bubble-content",
330
+ className: cn(
331
+ "w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50",
332
+ className
333
+ ),
334
+ ...props
335
+ }
336
+ );
337
+ }
338
+ var bubbleReactionsVariants = (0, import_class_variance_authority2.cva)(
339
+ "absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0",
340
+ {
341
+ variants: {
342
+ side: {
343
+ top: "top-0 -translate-y-3/4",
344
+ bottom: "bottom-0 translate-y-3/4"
345
+ },
346
+ align: {
347
+ start: "left-3",
348
+ end: "right-3"
349
+ }
350
+ },
351
+ defaultVariants: {
352
+ side: "bottom",
353
+ align: "end"
354
+ }
355
+ }
356
+ );
357
+ function BubbleReactions({
358
+ side = "bottom",
359
+ align = "end",
360
+ className,
361
+ ...props
362
+ }) {
363
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
364
+ "div",
365
+ {
366
+ "data-slot": "bubble-reactions",
367
+ "data-align": align,
368
+ "data-side": side,
369
+ className: cn(bubbleReactionsVariants({ side, align }), className),
370
+ ...props
371
+ }
372
+ );
373
+ }
374
+
375
+ // src/ui/message.tsx
376
+ var import_jsx_runtime3 = require("react/jsx-runtime");
377
+ function MessageGroup({ className, ...props }) {
378
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
379
+ "div",
380
+ {
381
+ "data-slot": "message-group",
382
+ className: cn("flex min-w-0 flex-col gap-2", className),
383
+ ...props
384
+ }
385
+ );
386
+ }
387
+ function Message({
388
+ className,
389
+ align = "start",
390
+ ...props
391
+ }) {
392
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
393
+ "div",
394
+ {
395
+ "data-slot": "message",
396
+ "data-align": align,
397
+ className: cn(
398
+ "group/message relative flex w-full min-w-0 gap-2 text-sm data-[align=end]:flex-row-reverse",
399
+ className
400
+ ),
401
+ ...props
402
+ }
403
+ );
404
+ }
405
+ function MessageAvatar({ className, ...props }) {
406
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
407
+ "div",
408
+ {
409
+ "data-slot": "message-avatar",
410
+ className: cn(
411
+ "flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-data-[slot=message-footer]/message:-translate-y-8",
412
+ className
413
+ ),
414
+ ...props
415
+ }
416
+ );
417
+ }
418
+ function MessageContent({ className, ...props }) {
419
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
420
+ "div",
421
+ {
422
+ "data-slot": "message-content",
423
+ className: cn(
424
+ "flex w-full min-w-0 flex-col gap-2.5 wrap-break-word group-data-[align=end]/message:*:data-slot:self-end",
425
+ className
426
+ ),
427
+ ...props
428
+ }
429
+ );
430
+ }
431
+ function MessageHeader({ className, ...props }) {
432
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
433
+ "div",
434
+ {
435
+ "data-slot": "message-header",
436
+ className: cn(
437
+ "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0",
438
+ className
439
+ ),
440
+ ...props
441
+ }
442
+ );
443
+ }
444
+ function MessageFooter({ className, ...props }) {
445
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
446
+ "div",
447
+ {
448
+ "data-slot": "message-footer",
449
+ className: cn(
450
+ "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end",
451
+ className
452
+ ),
453
+ ...props
454
+ }
455
+ );
456
+ }
457
+
458
+ // src/ui/adapters.ts
459
+ function ChatMessage(input) {
460
+ const { className, from, align, ...props } = input;
461
+ const isUser = from === "user";
462
+ const isRtl = props.dir === "rtl";
463
+ const resolvedAlign = align || "start";
464
+ const messageProps = Object.assign({}, props);
465
+ messageProps.align = resolvedAlign;
466
+ messageProps.className = cn(
467
+ "group flex w-full flex-col gap-2 overflow-visible",
468
+ isUser ? cn("is-user max-w-[80%] justify-end", isRtl ? "mr-auto" : "ml-auto") : "is-assistant max-w-full",
469
+ className
470
+ );
471
+ return React.createElement(Message, messageProps);
472
+ }
473
+ function ChatMessageContent({
474
+ className,
475
+ ...props
476
+ }) {
477
+ return React.createElement(BubbleContent, {
478
+ className: cn(
479
+ "flex w-full max-w-full min-w-0 flex-col gap-2 text-sm",
480
+ "group-[.is-user]:w-fit group-[.is-user]:overflow-visible group-[.is-user]:rounded-lg group-[.is-user]:bg-secondary group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:text-foreground",
481
+ "group-[.is-assistant]:w-full group-[.is-assistant]:max-w-full group-[.is-assistant]:overflow-hidden group-[.is-assistant]:text-foreground",
482
+ props.dir === "rtl" ? "group-[.is-assistant]:pr-0" : "group-[.is-assistant]:pl-0",
483
+ props.dir === "rtl" ? "group-[.is-user]:mr-auto" : "group-[.is-user]:ml-auto",
484
+ className
485
+ ),
486
+ ...props
487
+ });
488
+ }
489
+ function ChatMessageActions({
490
+ className,
491
+ ...props
492
+ }) {
493
+ return React.createElement("div", {
494
+ className: cn("flex items-center gap-1", className),
495
+ "data-slot": "message-actions",
496
+ ...props
497
+ });
498
+ }
499
+ function ChatMessageAction({
500
+ children,
501
+ className,
502
+ label,
503
+ tooltip,
504
+ type = "button",
505
+ ...props
506
+ }) {
507
+ const tooltipLabel = typeof tooltip === "string" ? tooltip : void 0;
508
+ return React.createElement(
509
+ "button",
510
+ {
511
+ "aria-label": label || tooltipLabel,
512
+ className: cn(
513
+ "inline-flex size-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
514
+ className
515
+ ),
516
+ title: tooltipLabel,
517
+ type,
518
+ ...props
519
+ },
520
+ children,
521
+ React.createElement(
522
+ "span",
523
+ { className: "sr-only" },
524
+ label || tooltipLabel
525
+ )
526
+ );
527
+ }
528
+ function ChatAttachment({
529
+ data,
530
+ onRemove,
531
+ orientation,
532
+ ...props
533
+ }) {
534
+ const mediaType = data.mediaType || data.contentType || String(data.type || "application/octet-stream");
535
+ const filename = data.filename || data.name || "Attachment";
536
+ const isImage = mediaType.startsWith("image/") && Boolean(data.url);
537
+ return React.createElement(
538
+ Attachment,
539
+ {
540
+ orientation: orientation || (isImage ? "vertical" : "horizontal"),
541
+ ...props
542
+ },
543
+ React.createElement(
544
+ AttachmentMedia,
545
+ { variant: isImage ? "image" : "icon" },
546
+ isImage ? React.createElement("img", {
547
+ alt: filename,
548
+ className: "size-full object-cover",
549
+ src: data.url
550
+ }) : React.createElement(
551
+ "span",
552
+ { "aria-hidden": "true", className: "text-sm" },
553
+ filename.slice(0, 1).toUpperCase()
554
+ )
555
+ ),
556
+ React.createElement(
557
+ AttachmentContent,
558
+ null,
559
+ React.createElement(AttachmentTitle, null, filename),
560
+ React.createElement(AttachmentDescription, null, mediaType)
561
+ ),
562
+ onRemove ? React.createElement(
563
+ "button",
564
+ {
565
+ "aria-label": "Remove attachment",
566
+ className: "relative z-20 mr-1 inline-flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground",
567
+ onClick: (event) => {
568
+ event.stopPropagation();
569
+ onRemove();
570
+ },
571
+ type: "button"
572
+ },
573
+ React.createElement("span", { "aria-hidden": "true" }, "x")
574
+ ) : null
575
+ );
576
+ }
577
+ function ChatAttachments({
578
+ children,
579
+ className,
580
+ ...props
581
+ }) {
582
+ if (!children) return null;
583
+ return React.createElement(
584
+ AttachmentGroup,
585
+ {
586
+ className: cn(
587
+ props.dir === "rtl" ? "mr-auto" : "ml-auto",
588
+ "w-fit flex-wrap overflow-visible",
589
+ className
590
+ ),
591
+ ...props
592
+ },
593
+ children
594
+ );
595
+ }
596
+
597
+ // src/ui/marker.tsx
598
+ var import_class_variance_authority3 = require("class-variance-authority");
599
+ var import_react_slot3 = require("@radix-ui/react-slot");
600
+ var import_jsx_runtime4 = require("react/jsx-runtime");
601
+ var markerVariants = (0, import_class_variance_authority3.cva)(
602
+ "group/marker relative flex min-h-4 w-full items-center gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground",
603
+ {
604
+ variants: {
605
+ variant: {
606
+ default: "",
607
+ separator: "before:mr-1 before:h-px before:min-w-0 before:flex-1 before:bg-border after:ml-1 after:h-px after:min-w-0 after:flex-1 after:bg-border",
608
+ border: "border-b border-border pb-2"
609
+ }
610
+ }
611
+ }
612
+ );
613
+ function Marker({
614
+ className,
615
+ variant = "default",
616
+ asChild = false,
617
+ ...props
618
+ }) {
619
+ const Comp = asChild ? import_react_slot3.Slot : "div";
620
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
621
+ Comp,
622
+ {
623
+ "data-slot": "marker",
624
+ "data-variant": variant,
625
+ className: cn(markerVariants({ variant, className })),
626
+ ...props
627
+ }
628
+ );
629
+ }
630
+ function MarkerIcon({ className, ...props }) {
631
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
632
+ "span",
633
+ {
634
+ "data-slot": "marker-icon",
635
+ "aria-hidden": "true",
636
+ className: cn(
637
+ "size-4 shrink-0 [&_svg:not([class*='size-'])]:size-4",
638
+ className
639
+ ),
640
+ ...props
641
+ }
642
+ );
643
+ }
644
+ function MarkerContent({ className, ...props }) {
645
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
646
+ "span",
647
+ {
648
+ "data-slot": "marker-content",
649
+ className: cn(
650
+ "min-w-0 wrap-break-word group-data-[variant=separator]/marker:flex-none group-data-[variant=separator]/marker:text-center *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
651
+ className
652
+ ),
653
+ ...props
654
+ }
655
+ );
656
+ }
657
+
658
+ // src/ui/message-response.tsx
659
+ var React2 = __toESM(require("react"), 1);
660
+ var import_streamdown = require("streamdown");
661
+
662
+ // src/streaming-text.ts
663
+ var import_react = require("react");
664
+ var DEFAULT_COMPLETED_TEXT_CACHE_SIZE = 200;
665
+ var defaultCompletedTextCache = /* @__PURE__ */ new Map();
666
+ var defaultStreamingTextCache = {
667
+ get: (id) => defaultCompletedTextCache.get(id),
668
+ set: (id, text) => {
669
+ defaultCompletedTextCache.set(id, text);
670
+ if (defaultCompletedTextCache.size > DEFAULT_COMPLETED_TEXT_CACHE_SIZE) {
671
+ const firstKey = defaultCompletedTextCache.keys().next().value;
672
+ if (firstKey) defaultCompletedTextCache.delete(firstKey);
673
+ }
674
+ }
675
+ };
676
+ function useStreamingText({
677
+ id,
678
+ isStreaming,
679
+ text,
680
+ cache = defaultStreamingTextCache,
681
+ charsPerSecond = 72,
682
+ catchupThreshold = 40,
683
+ maxCatchupChars = 20
684
+ }) {
685
+ const cacheAdapter = cache === false ? null : cache;
686
+ const [displayedText, setDisplayedText] = (0, import_react.useState)(() => {
687
+ const cachedText = cacheAdapter?.get(id);
688
+ return isStreaming && cachedText !== text ? "" : text;
689
+ });
690
+ const targetRef = (0, import_react.useRef)(text);
691
+ const displayedRef = (0, import_react.useRef)(displayedText);
692
+ const rafRef = (0, import_react.useRef)(null);
693
+ const lastFrameAtRef = (0, import_react.useRef)(null);
694
+ const idRef = (0, import_react.useRef)(id);
695
+ const shouldAnimateRef = (0, import_react.useRef)(isStreaming);
696
+ (0, import_react.useEffect)(() => {
697
+ if (isStreaming || !text) return;
698
+ cacheAdapter?.set(id, text);
699
+ }, [cacheAdapter, id, isStreaming, text]);
700
+ (0, import_react.useEffect)(() => {
701
+ targetRef.current = text;
702
+ }, [text]);
703
+ (0, import_react.useEffect)(() => {
704
+ if (idRef.current === id) return;
705
+ idRef.current = id;
706
+ const cachedText = cacheAdapter?.get(id);
707
+ const initial = isStreaming && cachedText !== text ? "" : text;
708
+ shouldAnimateRef.current = isStreaming && initial !== text;
709
+ displayedRef.current = initial;
710
+ setDisplayedText(initial);
711
+ if (rafRef.current !== null) {
712
+ cancelAnimationFrame(rafRef.current);
713
+ rafRef.current = null;
714
+ }
715
+ lastFrameAtRef.current = null;
716
+ }, [cacheAdapter, id, isStreaming, text]);
717
+ (0, import_react.useEffect)(() => {
718
+ if (typeof window === "undefined") {
719
+ displayedRef.current = text;
720
+ setDisplayedText(text);
721
+ return;
722
+ }
723
+ const reduceMotion = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
724
+ if (reduceMotion) {
725
+ displayedRef.current = text;
726
+ setDisplayedText(text);
727
+ shouldAnimateRef.current = false;
728
+ return;
729
+ }
730
+ const cachedText = cacheAdapter?.get(id);
731
+ if (cachedText === text) {
732
+ displayedRef.current = text;
733
+ setDisplayedText(text);
734
+ shouldAnimateRef.current = false;
735
+ return;
736
+ }
737
+ if (isStreaming) {
738
+ shouldAnimateRef.current = true;
739
+ }
740
+ if (!shouldAnimateRef.current) {
741
+ displayedRef.current = text;
742
+ setDisplayedText(text);
743
+ return;
744
+ }
745
+ if (!text.startsWith(displayedRef.current)) {
746
+ displayedRef.current = "";
747
+ setDisplayedText("");
748
+ }
749
+ const tick = (timestamp) => {
750
+ const previousTimestamp = lastFrameAtRef.current ?? timestamp;
751
+ lastFrameAtRef.current = timestamp;
752
+ const target = targetRef.current;
753
+ const current = displayedRef.current;
754
+ if (current.length >= target.length) {
755
+ shouldAnimateRef.current = false;
756
+ rafRef.current = null;
757
+ return;
758
+ }
759
+ const elapsedMs = Math.max(8, timestamp - previousTimestamp);
760
+ const charsFromTime = Math.max(1, Math.floor(elapsedMs / 1e3 * charsPerSecond));
761
+ const gap = target.length - current.length;
762
+ const catchupStep = gap > catchupThreshold ? Math.min(maxCatchupChars, Math.ceil(gap / 10)) : charsFromTime;
763
+ const nextLength = Math.min(
764
+ target.length,
765
+ current.length + Math.max(charsFromTime, catchupStep)
766
+ );
767
+ const next = target.slice(0, nextLength);
768
+ displayedRef.current = next;
769
+ setDisplayedText(next);
770
+ rafRef.current = window.requestAnimationFrame(tick);
771
+ };
772
+ if (rafRef.current === null && displayedRef.current.length < text.length) {
773
+ rafRef.current = window.requestAnimationFrame(tick);
774
+ }
775
+ return () => {
776
+ if (rafRef.current !== null) {
777
+ cancelAnimationFrame(rafRef.current);
778
+ rafRef.current = null;
779
+ }
780
+ lastFrameAtRef.current = null;
781
+ };
782
+ }, [cacheAdapter, catchupThreshold, charsPerSecond, id, isStreaming, maxCatchupChars, text]);
783
+ return {
784
+ displayedText,
785
+ isAnimating: isStreaming,
786
+ mode: isStreaming ? "streaming" : "static",
787
+ parseIncompleteMarkdown: isStreaming
788
+ };
789
+ }
790
+
791
+ // src/ui/message-response.tsx
792
+ var import_jsx_runtime5 = require("react/jsx-runtime");
793
+ var BLOCK_MARKDOWN_TAGS = /* @__PURE__ */ new Set([
794
+ "blockquote",
795
+ "div",
796
+ "h1",
797
+ "h2",
798
+ "h3",
799
+ "h4",
800
+ "h5",
801
+ "h6",
802
+ "hr",
803
+ "ol",
804
+ "pre",
805
+ "table",
806
+ "ul"
807
+ ]);
808
+ function isMultilineCodeNode(node) {
809
+ return node?.tagName === "code" && node.position?.start?.line !== void 0 && node.position?.end?.line !== void 0 && node.position.start.line !== node.position.end.line;
810
+ }
811
+ function hasBlockMarkdownChild(child) {
812
+ if (!React2.isValidElement(child)) {
813
+ return false;
814
+ }
815
+ if (typeof child.type === "string" && BLOCK_MARKDOWN_TAGS.has(child.type)) {
816
+ return true;
817
+ }
818
+ const props = child.props;
819
+ if (BLOCK_MARKDOWN_TAGS.has(props.node?.tagName || "") || isMultilineCodeNode(props.node)) {
820
+ return true;
821
+ }
822
+ return React2.Children.toArray(props.children).some(hasBlockMarkdownChild);
823
+ }
824
+ function MessageMarkdownParagraph({
825
+ children,
826
+ ...props
827
+ }) {
828
+ const domProps = { ...props };
829
+ delete domProps.node;
830
+ const childArray = React2.Children.toArray(children).filter(
831
+ (child) => child !== null && child !== ""
832
+ );
833
+ const isImageOnly = childArray.length === 1 && React2.isValidElement(childArray[0]) && childArray[0].props.node?.tagName === "img";
834
+ if (isImageOnly) {
835
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
836
+ }
837
+ if (childArray.some(hasBlockMarkdownChild)) {
838
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ...domProps, children });
839
+ }
840
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { ...domProps, children });
841
+ }
842
+ var MESSAGE_RESPONSE_COMPONENTS = {
843
+ p: MessageMarkdownParagraph
844
+ };
845
+ var streamdownDefaultRehypePlugins = import_streamdown.defaultRehypePlugins || {};
846
+ var streamdownHardenPlugin = Array.isArray(
847
+ streamdownDefaultRehypePlugins.harden
848
+ ) ? streamdownDefaultRehypePlugins.harden[0] : streamdownDefaultRehypePlugins.harden;
849
+ var MESSAGE_RESPONSE_REHYPE_PLUGINS = [
850
+ ...Object.entries(streamdownDefaultRehypePlugins).filter(([key]) => key !== "harden").map(([, plugin]) => plugin),
851
+ ...streamdownHardenPlugin ? [
852
+ [
853
+ streamdownHardenPlugin,
854
+ {
855
+ allowDataImages: true,
856
+ allowedImagePrefixes: ["*"],
857
+ allowedLinkPrefixes: ["*"],
858
+ allowedProtocols: ["*", "reshet:", "source:"],
859
+ defaultOrigin: void 0
860
+ }
861
+ ]
862
+ ] : []
863
+ ];
864
+ var MessageResponse = React2.memo(
865
+ ({
866
+ children,
867
+ className,
868
+ components,
869
+ rehypePlugins,
870
+ streaming = false,
871
+ streamingId,
872
+ ...props
873
+ }) => {
874
+ const text = typeof children === "string" || typeof children === "number" ? String(children) : "";
875
+ const streamingText = useStreamingText({
876
+ charsPerSecond: 120,
877
+ id: streamingId || text,
878
+ isStreaming: streaming && text.length > 0,
879
+ maxCatchupChars: 32,
880
+ text
881
+ });
882
+ const streamdownComponents = React2.useMemo(
883
+ () => ({ ...MESSAGE_RESPONSE_COMPONENTS, ...components }),
884
+ [components]
885
+ );
886
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
887
+ import_streamdown.Streamdown,
888
+ {
889
+ className: cn("size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", className),
890
+ components: streamdownComponents,
891
+ rehypePlugins: rehypePlugins || MESSAGE_RESPONSE_REHYPE_PLUGINS,
892
+ ...props,
893
+ children: text ? streamingText.displayedText : children
894
+ }
895
+ );
896
+ },
897
+ (prevProps, nextProps) => prevProps.children === nextProps.children && prevProps.className === nextProps.className && prevProps.streaming === nextProps.streaming && prevProps.streamingId === nextProps.streamingId && prevProps.components === nextProps.components
898
+ );
899
+ MessageResponse.displayName = "MessageResponse";
900
+ // Annotate the CommonJS export names for ESM import in node:
901
+ 0 && (module.exports = {
902
+ Attachment,
903
+ AttachmentAction,
904
+ AttachmentActions,
905
+ AttachmentContent,
906
+ AttachmentDescription,
907
+ AttachmentGroup,
908
+ AttachmentMedia,
909
+ AttachmentTitle,
910
+ AttachmentTrigger,
911
+ Bubble,
912
+ BubbleContent,
913
+ BubbleGroup,
914
+ BubbleReactions,
915
+ ChatAttachment,
916
+ ChatAttachments,
917
+ ChatMessage,
918
+ ChatMessageAction,
919
+ ChatMessageActions,
920
+ ChatMessageContent,
921
+ Marker,
922
+ MarkerContent,
923
+ MarkerIcon,
924
+ Message,
925
+ MessageAction,
926
+ MessageActions,
927
+ MessageAttachment,
928
+ MessageAttachments,
929
+ MessageAvatar,
930
+ MessageContent,
931
+ MessageFooter,
932
+ MessageGroup,
933
+ MessageHeader,
934
+ MessageResponse,
935
+ ShadcnMessage,
936
+ ShadcnMessageContent,
937
+ attachmentMediaVariants,
938
+ attachmentVariants,
939
+ bubbleVariants,
940
+ cn,
941
+ markerVariants
942
+ });
943
+ //# sourceMappingURL=index.cjs.map