@tinkrapp/widget 1.0.0

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/dist/react.cjs ADDED
@@ -0,0 +1,4857 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var react = require('@assistant-ui/react');
5
+ var reactAiSdk = require('@assistant-ui/react-ai-sdk');
6
+ var react$2 = require('@emotion/react');
7
+ var assistantStream = require('assistant-stream');
8
+ var ReactMarkdown = require('react-markdown');
9
+ var remarkGfm = require('remark-gfm');
10
+ var lucideReact = require('lucide-react');
11
+ var clsx = require('clsx');
12
+ var tailwindMerge = require('tailwind-merge');
13
+ var reactSlot = require('@radix-ui/react-slot');
14
+ var TooltipPrimitive = require('@radix-ui/react-tooltip');
15
+ var jsxRuntime = require('react/jsx-runtime');
16
+ var classVarianceAuthority = require('class-variance-authority');
17
+ var styled = require('@emotion/styled');
18
+ var react$1 = require('motion/react');
19
+ var shallow = require('zustand/shallow');
20
+ var DialogPrimitive = require('@radix-ui/react-dialog');
21
+ var AvatarPrimitive = require('@radix-ui/react-avatar');
22
+ require('@assistant-ui/react-markdown/styles/dot.css');
23
+ var reactMarkdown = require('@assistant-ui/react-markdown');
24
+ var PopoverPrimitive = require('@radix-ui/react-popover');
25
+
26
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
27
+
28
+ function _interopNamespace(e) {
29
+ if (e && e.__esModule) return e;
30
+ var n = Object.create(null);
31
+ if (e) {
32
+ Object.keys(e).forEach(function (k) {
33
+ if (k !== 'default') {
34
+ var d = Object.getOwnPropertyDescriptor(e, k);
35
+ Object.defineProperty(n, k, d.get ? d : {
36
+ enumerable: true,
37
+ get: function () { return e[k]; }
38
+ });
39
+ }
40
+ });
41
+ }
42
+ n.default = e;
43
+ return Object.freeze(n);
44
+ }
45
+
46
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
47
+ var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
48
+ var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
49
+ var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
50
+ var styled__default = /*#__PURE__*/_interopDefault(styled);
51
+ var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
52
+ var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
53
+ var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
54
+
55
+ // src/react/provider.tsx
56
+
57
+ // src/core/events.ts
58
+ var TypedEventEmitter = class {
59
+ constructor() {
60
+ this.listeners = /* @__PURE__ */ new Map();
61
+ }
62
+ on(event, handler) {
63
+ if (!this.listeners.has(event)) {
64
+ this.listeners.set(event, /* @__PURE__ */ new Set());
65
+ }
66
+ this.listeners.get(event).add(handler);
67
+ return () => this.off(event, handler);
68
+ }
69
+ off(event, handler) {
70
+ this.listeners.get(event)?.delete(handler);
71
+ }
72
+ emit(event, payload) {
73
+ this.listeners.get(event)?.forEach((handler) => {
74
+ try {
75
+ handler(payload);
76
+ } catch (error) {
77
+ console.error(`Error in ${String(event)} handler:`, error);
78
+ }
79
+ });
80
+ }
81
+ clear() {
82
+ this.listeners.clear();
83
+ }
84
+ removeAllListeners(event) {
85
+ if (event) {
86
+ this.listeners.delete(event);
87
+ } else {
88
+ this.listeners.clear();
89
+ }
90
+ }
91
+ };
92
+
93
+ // src/core/api.ts
94
+ var WidgetAPI = class {
95
+ constructor(config) {
96
+ this.config = {
97
+ baseUrl: "http://localhost:3000",
98
+ userId: "",
99
+ debug: false,
100
+ assistantId: config.apiKey,
101
+ // Default to apiKey for backwards compatibility
102
+ ...config
103
+ };
104
+ }
105
+ async createSession() {
106
+ const response = await this.request("/sessions", {
107
+ method: "POST",
108
+ body: JSON.stringify({
109
+ // apiKey IS the assistantId
110
+ assistantId: this.config.apiKey,
111
+ userId: this.config.userId
112
+ })
113
+ });
114
+ return response;
115
+ }
116
+ async sendMessage(sessionId, content) {
117
+ const response = await this.request(`/sessions/${sessionId}/messages`, {
118
+ method: "POST",
119
+ body: JSON.stringify({ content })
120
+ });
121
+ return response;
122
+ }
123
+ async getHistory(sessionId) {
124
+ return this.request(`/sessions/${sessionId}/messages`);
125
+ }
126
+ async getSessions() {
127
+ return this.request("/sessions");
128
+ }
129
+ async getArtifacts() {
130
+ return this.request("/artifacts");
131
+ }
132
+ async getArtifact(id) {
133
+ return this.request(`/artifacts/${id}`);
134
+ }
135
+ async createArtifact(artifact) {
136
+ return this.request("/artifacts", {
137
+ method: "POST",
138
+ body: JSON.stringify(artifact)
139
+ });
140
+ }
141
+ async request(endpoint, options = {}) {
142
+ const url = `${this.config.baseUrl}${endpoint}`;
143
+ this.log("Request:", url, options);
144
+ const response = await fetch(url, {
145
+ ...options,
146
+ headers: {
147
+ "Content-Type": "application/json",
148
+ "Authorization": `Bearer ${this.config.apiKey}`,
149
+ ...options.headers
150
+ }
151
+ });
152
+ if (!response.ok) {
153
+ const error = await response.json().catch(() => ({}));
154
+ throw new Error(error.message || `HTTP ${response.status}`);
155
+ }
156
+ return response.json();
157
+ }
158
+ log(...args) {
159
+ if (this.config.debug) {
160
+ console.log("[CourseAI]", ...args);
161
+ }
162
+ }
163
+ };
164
+
165
+ // src/core/client.ts
166
+ var WidgetClient = class {
167
+ constructor(config) {
168
+ this.state = { status: "idle" };
169
+ this.events = new TypedEventEmitter();
170
+ this.config = config;
171
+ this.api = new WidgetAPI(config);
172
+ }
173
+ /**
174
+ * Initialize the widget and create a chat session
175
+ */
176
+ async initialize() {
177
+ if (this.state.status !== "idle") {
178
+ throw new Error("Widget already initialized");
179
+ }
180
+ this.setState({ status: "initializing" });
181
+ try {
182
+ const session = await this.api.createSession();
183
+ this.setState({ status: "ready", session });
184
+ this.events.emit("session:created", { session });
185
+ } catch (error) {
186
+ const widgetError = {
187
+ code: "INIT_FAILED",
188
+ message: error instanceof Error ? error.message : "Unknown error",
189
+ details: error
190
+ };
191
+ this.setState({ status: "error", error: widgetError });
192
+ this.events.emit("error", { error: widgetError });
193
+ throw error;
194
+ }
195
+ }
196
+ /**
197
+ * Send a message to the AI assistant
198
+ */
199
+ async sendMessage(content) {
200
+ if (this.state.status !== "ready") {
201
+ throw new Error("Widget not ready. Call initialize() first.");
202
+ }
203
+ const userMessage = {
204
+ id: crypto.randomUUID(),
205
+ role: "user",
206
+ content,
207
+ timestamp: Date.now()
208
+ };
209
+ const session = {
210
+ ...this.state.session,
211
+ messages: [...this.state.session.messages, userMessage]
212
+ };
213
+ this.setState({ status: "ready", session });
214
+ this.events.emit("message:sent", { message: userMessage });
215
+ this.setState({ status: "loading" });
216
+ try {
217
+ const assistantMessage = await this.api.sendMessage(
218
+ session.id,
219
+ content
220
+ );
221
+ const updatedSession = {
222
+ ...session,
223
+ messages: [...session.messages, assistantMessage]
224
+ };
225
+ this.setState({ status: "ready", session: updatedSession });
226
+ this.events.emit("message:received", { message: assistantMessage });
227
+ return assistantMessage;
228
+ } catch (error) {
229
+ const widgetError = {
230
+ code: "SEND_MESSAGE_FAILED",
231
+ message: error instanceof Error ? error.message : "Failed to send message",
232
+ details: error
233
+ };
234
+ this.setState({ status: "ready", session });
235
+ this.events.emit("error", { error: widgetError });
236
+ throw error;
237
+ }
238
+ }
239
+ /**
240
+ * Get current state
241
+ */
242
+ getState() {
243
+ return this.state;
244
+ }
245
+ /**
246
+ * Get the API instance for direct calls
247
+ */
248
+ getAPI() {
249
+ return this.api;
250
+ }
251
+ /**
252
+ * Get the widget configuration
253
+ */
254
+ getConfig() {
255
+ return this.config;
256
+ }
257
+ /**
258
+ * Subscribe to events
259
+ */
260
+ on(event, handler) {
261
+ return this.events.on(event, handler);
262
+ }
263
+ /**
264
+ * Unsubscribe from events
265
+ */
266
+ off(event, handler) {
267
+ this.events.off(event, handler);
268
+ }
269
+ /**
270
+ * Clean up resources
271
+ */
272
+ destroy() {
273
+ this.events.clear();
274
+ this.setState({ status: "idle" });
275
+ }
276
+ setState(newState) {
277
+ const previous = this.state;
278
+ this.state = newState;
279
+ this.events.emit("state:change", { previous, current: newState });
280
+ }
281
+ };
282
+ function cn(...inputs) {
283
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
284
+ }
285
+ function TooltipProvider({
286
+ delayDuration = 0,
287
+ ...props
288
+ }) {
289
+ return /* @__PURE__ */ jsxRuntime.jsx(
290
+ TooltipPrimitive__namespace.Provider,
291
+ {
292
+ "data-slot": "tooltip-provider",
293
+ delayDuration,
294
+ ...props
295
+ }
296
+ );
297
+ }
298
+ function Tooltip({
299
+ ...props
300
+ }) {
301
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Root, { "data-slot": "tooltip", ...props }) });
302
+ }
303
+ function TooltipTrigger({
304
+ ...props
305
+ }) {
306
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Trigger, { "data-slot": "tooltip-trigger", ...props });
307
+ }
308
+ function TooltipContent({
309
+ className,
310
+ sideOffset = 0,
311
+ children,
312
+ ...props
313
+ }) {
314
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
315
+ TooltipPrimitive__namespace.Content,
316
+ {
317
+ "data-slot": "tooltip-content",
318
+ sideOffset,
319
+ className: cn(
320
+ "bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
321
+ className
322
+ ),
323
+ ...props,
324
+ children: [
325
+ children,
326
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Arrow, { className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
327
+ ]
328
+ }
329
+ ) });
330
+ }
331
+ var buttonVariants = classVarianceAuthority.cva(
332
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
333
+ {
334
+ variants: {
335
+ variant: {
336
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
337
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
338
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
339
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
340
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
341
+ link: "text-primary underline-offset-4 hover:underline"
342
+ },
343
+ size: {
344
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
345
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
346
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
347
+ icon: "size-9",
348
+ "icon-sm": "size-8",
349
+ "icon-lg": "size-10"
350
+ }
351
+ },
352
+ defaultVariants: {
353
+ variant: "default",
354
+ size: "default"
355
+ }
356
+ }
357
+ );
358
+ var Button = React__namespace.forwardRef(({ className, variant = "default", size = "default", asChild = false, ...props }, ref) => {
359
+ const Comp = asChild ? reactSlot.Slot : "button";
360
+ return /* @__PURE__ */ jsxRuntime.jsx(
361
+ Comp,
362
+ {
363
+ ref,
364
+ "data-slot": "button",
365
+ "data-variant": variant,
366
+ "data-size": size,
367
+ className: cn(buttonVariants({ variant, size, className })),
368
+ ...props
369
+ }
370
+ );
371
+ });
372
+ Button.displayName = "Button";
373
+ var TooltipIconButton = React.forwardRef(({ children, tooltip, side = "bottom", className, ...rest }, ref) => {
374
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
375
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "icon-sm", ...rest, ref, children: [
376
+ /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slottable, { children }),
377
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "aui-sr-only sr-only", children: tooltip })
378
+ ] }) }),
379
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side, children: tooltip })
380
+ ] });
381
+ });
382
+ TooltipIconButton.displayName = "TooltipIconButton";
383
+ var ToolCard = ({
384
+ title,
385
+ subtitle,
386
+ isStreaming,
387
+ isError = false,
388
+ icon,
389
+ persistentContent,
390
+ children,
391
+ footer
392
+ }) => {
393
+ const [manualExpanded, setManualExpanded] = React.useState(null);
394
+ const prevStreamingRef = React.useRef(isStreaming);
395
+ const contentRef = React.useRef(null);
396
+ const isExpanded = manualExpanded ?? isStreaming;
397
+ React.useEffect(() => {
398
+ if (isStreaming && !prevStreamingRef.current) {
399
+ setManualExpanded(null);
400
+ }
401
+ prevStreamingRef.current = isStreaming;
402
+ }, [isStreaming]);
403
+ React.useEffect(() => {
404
+ if (isStreaming && contentRef.current) {
405
+ contentRef.current.scrollTop = contentRef.current.scrollHeight;
406
+ }
407
+ });
408
+ const renderIcon = () => {
409
+ if (icon) return icon;
410
+ const iconClass = cn("h-4 w-4", isStreaming && "animate-spin");
411
+ if (isStreaming) {
412
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2Icon, { className: iconClass });
413
+ }
414
+ if (isError) {
415
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircleIcon, { className: "h-4 w-4 text-red-400" });
416
+ }
417
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, { className: "h-4 w-4" });
418
+ };
419
+ const handleToggle = () => {
420
+ if (!isStreaming) {
421
+ setManualExpanded((prev2) => prev2 === null ? true : !prev2);
422
+ }
423
+ };
424
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "my-2 overflow-hidden rounded-xl border border-border shadow-sm", children: [
425
+ /* @__PURE__ */ jsxRuntime.jsxs(
426
+ "div",
427
+ {
428
+ className: cn(
429
+ "flex items-center gap-2 p-2 cursor-pointer transition-colors text-white bg-primary-foreground",
430
+ !isStreaming && "hover:opacity-90"
431
+ ),
432
+ onClick: handleToggle,
433
+ children: [
434
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: renderIcon() }),
435
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
436
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium opacity-80 leading-tight text-xs text-muted-foreground", children: subtitle }),
437
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "truncate font-semibold leading-tight text-sm text-muted-foreground", children: title })
438
+ ] }),
439
+ /* @__PURE__ */ jsxRuntime.jsx(
440
+ "button",
441
+ {
442
+ className: "p-1 rounded hover:bg-white/20 transition-colors",
443
+ "aria-label": isExpanded ? "Collapse" : "Expand",
444
+ onClick: (e) => {
445
+ e.stopPropagation();
446
+ handleToggle();
447
+ },
448
+ children: isExpanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUpIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: "h-4 w-4" })
449
+ }
450
+ )
451
+ ]
452
+ }
453
+ ),
454
+ persistentContent,
455
+ isExpanded && /* @__PURE__ */ jsxRuntime.jsx(
456
+ "div",
457
+ {
458
+ ref: contentRef,
459
+ className: "p-2 max-h-[400px] overflow-y-auto bg-secondary",
460
+ children
461
+ }
462
+ ),
463
+ isExpanded && footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-end gap-2 border-t border-white/10 p-2 bg-primary-foreground/80", children: footer })
464
+ ] });
465
+ };
466
+ var useCopyToClipboard = ({
467
+ copiedDuration = 3e3
468
+ } = {}) => {
469
+ const [isCopied, setIsCopied] = React.useState(false);
470
+ const copyToClipboard = (value) => {
471
+ if (!value) return;
472
+ navigator.clipboard.writeText(value).then(() => {
473
+ setIsCopied(true);
474
+ setTimeout(() => setIsCopied(false), copiedDuration);
475
+ });
476
+ };
477
+ return { isCopied, copyToClipboard };
478
+ };
479
+ var MarkdownContent = React.memo(({ content }) => {
480
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aui-md max-w-none text-white", children: /* @__PURE__ */ jsxRuntime.jsx(
481
+ ReactMarkdown__default.default,
482
+ {
483
+ remarkPlugins: [remarkGfm__default.default],
484
+ components: {
485
+ h1: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
486
+ "h1",
487
+ {
488
+ className: cn(
489
+ "mb-2 font-extrabold tracking-tight last:mb-0 text-white",
490
+ className
491
+ ),
492
+ style: { fontSize: "12px" },
493
+ ...props
494
+ }
495
+ ),
496
+ h2: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
497
+ "h2",
498
+ {
499
+ className: cn(
500
+ "mt-3 mb-1.5 font-semibold tracking-tight first:mt-0 last:mb-0 text-white",
501
+ className
502
+ ),
503
+ style: { fontSize: "10px" },
504
+ ...props
505
+ }
506
+ ),
507
+ h3: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
508
+ "h3",
509
+ {
510
+ className: cn(
511
+ "mt-2 mb-1 font-semibold tracking-tight first:mt-0 last:mb-0 text-white",
512
+ className
513
+ ),
514
+ style: { fontSize: "9px" },
515
+ ...props
516
+ }
517
+ ),
518
+ p: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
519
+ "p",
520
+ {
521
+ className: cn(
522
+ "mt-1.5 mb-1.5 leading-relaxed first:mt-0 last:mb-0 text-white/90",
523
+ className
524
+ ),
525
+ ...props
526
+ }
527
+ ),
528
+ ul: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
529
+ "ul",
530
+ {
531
+ className: cn(
532
+ "my-1.5 ml-3 list-disc [&>li]:mt-0.5 text-white/90",
533
+ className
534
+ ),
535
+ ...props
536
+ }
537
+ ),
538
+ ol: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
539
+ "ol",
540
+ {
541
+ className: cn(
542
+ "my-1.5 ml-3 list-decimal [&>li]:mt-0.5 text-white/90",
543
+ className
544
+ ),
545
+ ...props
546
+ }
547
+ ),
548
+ blockquote: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
549
+ "blockquote",
550
+ {
551
+ className: cn(
552
+ "border-l-2 border-white/30 pl-2 italic text-white/70",
553
+ className
554
+ ),
555
+ ...props
556
+ }
557
+ ),
558
+ pre: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
559
+ "pre",
560
+ {
561
+ className: cn(
562
+ "overflow-x-auto rounded bg-black/30 p-1.5 text-white/90 my-1.5",
563
+ className
564
+ ),
565
+ ...props
566
+ }
567
+ ),
568
+ code: ({ className, ...props }) => {
569
+ const isInline = !className?.includes("language-");
570
+ return /* @__PURE__ */ jsxRuntime.jsx(
571
+ "code",
572
+ {
573
+ className: cn(
574
+ isInline && "rounded bg-black/30 px-0.5 py-0.5 font-mono text-white/90",
575
+ className
576
+ ),
577
+ ...props
578
+ }
579
+ );
580
+ },
581
+ a: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
582
+ "a",
583
+ {
584
+ className: cn(
585
+ "font-medium text-blue-300 underline underline-offset-2",
586
+ className
587
+ ),
588
+ target: "_blank",
589
+ rel: "noopener noreferrer",
590
+ ...props
591
+ }
592
+ ),
593
+ hr: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
594
+ "hr",
595
+ {
596
+ className: cn("my-2 border-b border-white/20", className),
597
+ ...props
598
+ }
599
+ )
600
+ },
601
+ children: content
602
+ }
603
+ ) });
604
+ });
605
+ MarkdownContent.displayName = "MarkdownContent";
606
+ var DetailedAnswerToolUI = react.makeAssistantToolUI({
607
+ toolName: "generateDetailedAnswer",
608
+ render: function DetailedAnswerUI({ args, result, status }) {
609
+ const { isCopied, copyToClipboard } = useCopyToClipboard();
610
+ const isStreaming = status.type === "running";
611
+ const isError = status.type === "incomplete";
612
+ const title = result?.title || args.title || "Generating...";
613
+ const content = result?.content || args.content || "";
614
+ const summary = result?.summary || args.summary || "";
615
+ const handleCopy = () => {
616
+ if (content) {
617
+ copyToClipboard(content);
618
+ }
619
+ };
620
+ const handleOpenFullScreen = () => {
621
+ const newWindow = window.open("", "_blank");
622
+ if (newWindow) {
623
+ newWindow.document.write(`
624
+ <!DOCTYPE html>
625
+ <html>
626
+ <head>
627
+ <title>${title}</title>
628
+ <meta charset="utf-8">
629
+ <meta name="viewport" content="width=device-width, initial-scale=1">
630
+ <style>
631
+ body {
632
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
633
+ max-width: 800px;
634
+ margin: 0 auto;
635
+ padding: 2rem;
636
+ line-height: 1.6;
637
+ color: #1a1a1a;
638
+ }
639
+ h1 { border-bottom: 1px solid #eee; padding-bottom: 0.5rem; }
640
+ pre { background: #f5f5f5; padding: 1rem; overflow-x: auto; border-radius: 4px; }
641
+ code { background: #f5f5f5; padding: 0.2em 0.4em; border-radius: 3px; font-size: 0.9em; }
642
+ pre code { background: none; padding: 0; }
643
+ blockquote { border-left: 4px solid #ddd; margin: 0; padding-left: 1rem; color: #666; }
644
+ </style>
645
+ </head>
646
+ <body>
647
+ <h1>${title}</h1>
648
+ <div id="content">${content.replace(/</g, "&lt;").replace(/>/g, "&gt;")}</div>
649
+ <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
650
+ <script>
651
+ document.getElementById('content').innerHTML = marked.parse(${JSON.stringify(
652
+ content
653
+ )});
654
+ </script>
655
+ </body>
656
+ </html>
657
+ `);
658
+ newWindow.document.close();
659
+ }
660
+ };
661
+ const persistentSummary = summary ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 text-white/80 border-b border-white/10 bg-primary-foreground text-xs", children: summary }) : void 0;
662
+ const footerActions = content ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
663
+ /* @__PURE__ */ jsxRuntime.jsx(
664
+ TooltipIconButton,
665
+ {
666
+ tooltip: isCopied ? "Copied!" : "Copy markdown",
667
+ onClick: handleCopy,
668
+ className: "flex items-center justify-center rounded-md p-1.5 text-white/70 hover:bg-white/10 transition-colors",
669
+ children: isCopied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CopyIcon, { className: "h-3.5 w-3.5" })
670
+ }
671
+ ),
672
+ /* @__PURE__ */ jsxRuntime.jsx(
673
+ TooltipIconButton,
674
+ {
675
+ tooltip: "Open in new window",
676
+ onClick: handleOpenFullScreen,
677
+ className: "flex items-center justify-center rounded-md p-1.5 text-white/70 hover:bg-white/10 transition-colors",
678
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLinkIcon, { className: "h-3.5 w-3.5" })
679
+ }
680
+ )
681
+ ] }) : void 0;
682
+ return /* @__PURE__ */ jsxRuntime.jsx(
683
+ ToolCard,
684
+ {
685
+ title,
686
+ isStreaming,
687
+ isError,
688
+ icon: !isStreaming && !isError ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileTextIcon, { className: "h-4 w-4" }) : void 0,
689
+ persistentContent: persistentSummary,
690
+ footer: footerActions,
691
+ children: content ? /* @__PURE__ */ jsxRuntime.jsx(MarkdownContent, { content }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground italic", children: "Generating content..." })
692
+ }
693
+ );
694
+ }
695
+ });
696
+ var MessageContext = React.createContext(null);
697
+ function MessageContextProvider({ children }) {
698
+ const [selectedContext, setSelectedContext] = React.useState([]);
699
+ const addContextItem = React.useCallback((item) => {
700
+ console.log("[MessageContext] Adding context item:", item.id, item.title);
701
+ setSelectedContext((prev2) => {
702
+ if (prev2.some((i) => i.id === item.id)) {
703
+ console.log("[MessageContext] Item already exists, skipping");
704
+ return prev2;
705
+ }
706
+ console.log("[MessageContext] Context items count:", prev2.length + 1);
707
+ return [...prev2, item];
708
+ });
709
+ }, []);
710
+ const removeContextItem = React.useCallback((id) => {
711
+ setSelectedContext((prev2) => prev2.filter((item) => item.id !== id));
712
+ }, []);
713
+ const clearContext = React.useCallback(() => {
714
+ console.log("[MessageContext] Clearing context");
715
+ setSelectedContext([]);
716
+ }, []);
717
+ const setContext = React.useCallback((items) => {
718
+ setSelectedContext(items);
719
+ }, []);
720
+ const consumeContext = React.useCallback(() => {
721
+ const context = selectedContext;
722
+ console.log("[MessageContext] Consuming context:", context.length, "items");
723
+ return context;
724
+ }, [selectedContext]);
725
+ return /* @__PURE__ */ jsxRuntime.jsx(
726
+ MessageContext.Provider,
727
+ {
728
+ value: {
729
+ selectedContext,
730
+ addContextItem,
731
+ removeContextItem,
732
+ clearContext,
733
+ setContext,
734
+ consumeContext
735
+ },
736
+ children
737
+ }
738
+ );
739
+ }
740
+ function useMessageContext() {
741
+ const context = React.useContext(MessageContext);
742
+ if (!context) {
743
+ throw new Error(
744
+ "useMessageContext must be used within a MessageContextProvider"
745
+ );
746
+ }
747
+ return context;
748
+ }
749
+
750
+ // src/react/styles/theme.ts
751
+ var theme = {
752
+ colors: {
753
+ background: {
754
+ primary: "#1a1a1a",
755
+ secondary: "#2a2a2a",
756
+ tertiary: "#3a3a3a"
757
+ },
758
+ accent: {
759
+ primary: "#c9a227",
760
+ hover: "#d4af37",
761
+ muted: "rgba(201, 162, 39, 0.4)"
762
+ },
763
+ text: {
764
+ primary: "#ffffff",
765
+ secondary: "#888888",
766
+ tertiary: "#cccccc",
767
+ inverse: "#1a1a1a"
768
+ },
769
+ border: "#2a2a2a",
770
+ shadow: "rgba(0, 0, 0, 0.4)"
771
+ },
772
+ spacing: {
773
+ xs: "0.25rem",
774
+ sm: "0.5rem",
775
+ md: "1rem",
776
+ lg: "1.5rem",
777
+ xl: "2rem",
778
+ "2xl": "3rem"
779
+ },
780
+ radii: {
781
+ sm: "0.5rem",
782
+ md: "0.75rem",
783
+ lg: "1rem",
784
+ xl: "1.5rem",
785
+ full: "50%"
786
+ },
787
+ typography: {
788
+ fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
789
+ fontSize: {
790
+ xs: "0.75rem",
791
+ sm: "0.875rem",
792
+ md: "1rem",
793
+ lg: "1.125rem",
794
+ xl: "1.25rem",
795
+ "2xl": "1.5rem"
796
+ },
797
+ fontWeight: {
798
+ normal: 400,
799
+ medium: 500,
800
+ semibold: 600,
801
+ bold: 700
802
+ },
803
+ lineHeight: {
804
+ tight: 1.25,
805
+ normal: 1.5,
806
+ relaxed: 1.7
807
+ }
808
+ },
809
+ zIndex: {
810
+ widget: 9999,
811
+ overlay: 9998
812
+ },
813
+ shadows: {
814
+ sm: "0 2px 8px rgba(0, 0, 0, 0.2)",
815
+ md: "0 4px 16px rgba(0, 0, 0, 0.3)",
816
+ lg: "0 8px 32px rgba(0, 0, 0, 0.4)",
817
+ accent: "0 4px 16px rgba(201, 162, 39, 0.4)",
818
+ accentHover: "0 6px 20px rgba(201, 162, 39, 0.5)"
819
+ },
820
+ transitions: {
821
+ fast: "0.15s ease",
822
+ normal: "0.2s ease",
823
+ slow: "0.3s ease"
824
+ }
825
+ };
826
+ function sheetForTag(tag) {
827
+ if (tag.sheet) {
828
+ return tag.sheet;
829
+ }
830
+ for (var i = 0; i < document.styleSheets.length; i++) {
831
+ if (document.styleSheets[i].ownerNode === tag) {
832
+ return document.styleSheets[i];
833
+ }
834
+ }
835
+ return void 0;
836
+ }
837
+ function createStyleElement(options) {
838
+ var tag = document.createElement("style");
839
+ tag.setAttribute("data-emotion", options.key);
840
+ if (options.nonce !== void 0) {
841
+ tag.setAttribute("nonce", options.nonce);
842
+ }
843
+ tag.appendChild(document.createTextNode(""));
844
+ tag.setAttribute("data-s", "");
845
+ return tag;
846
+ }
847
+ var StyleSheet = /* @__PURE__ */ (function() {
848
+ function StyleSheet2(options) {
849
+ var _this = this;
850
+ this._insertTag = function(tag) {
851
+ var before;
852
+ if (_this.tags.length === 0) {
853
+ if (_this.insertionPoint) {
854
+ before = _this.insertionPoint.nextSibling;
855
+ } else if (_this.prepend) {
856
+ before = _this.container.firstChild;
857
+ } else {
858
+ before = _this.before;
859
+ }
860
+ } else {
861
+ before = _this.tags[_this.tags.length - 1].nextSibling;
862
+ }
863
+ _this.container.insertBefore(tag, before);
864
+ _this.tags.push(tag);
865
+ };
866
+ this.isSpeedy = options.speedy === void 0 ? true : options.speedy;
867
+ this.tags = [];
868
+ this.ctr = 0;
869
+ this.nonce = options.nonce;
870
+ this.key = options.key;
871
+ this.container = options.container;
872
+ this.prepend = options.prepend;
873
+ this.insertionPoint = options.insertionPoint;
874
+ this.before = null;
875
+ }
876
+ var _proto = StyleSheet2.prototype;
877
+ _proto.hydrate = function hydrate(nodes) {
878
+ nodes.forEach(this._insertTag);
879
+ };
880
+ _proto.insert = function insert(rule) {
881
+ if (this.ctr % (this.isSpeedy ? 65e3 : 1) === 0) {
882
+ this._insertTag(createStyleElement(this));
883
+ }
884
+ var tag = this.tags[this.tags.length - 1];
885
+ if (this.isSpeedy) {
886
+ var sheet = sheetForTag(tag);
887
+ try {
888
+ sheet.insertRule(rule, sheet.cssRules.length);
889
+ } catch (e) {
890
+ }
891
+ } else {
892
+ tag.appendChild(document.createTextNode(rule));
893
+ }
894
+ this.ctr++;
895
+ };
896
+ _proto.flush = function flush() {
897
+ this.tags.forEach(function(tag) {
898
+ var _tag$parentNode;
899
+ return (_tag$parentNode = tag.parentNode) == null ? void 0 : _tag$parentNode.removeChild(tag);
900
+ });
901
+ this.tags = [];
902
+ this.ctr = 0;
903
+ };
904
+ return StyleSheet2;
905
+ })();
906
+
907
+ // ../../node_modules/stylis/src/Enum.js
908
+ var MS = "-ms-";
909
+ var MOZ = "-moz-";
910
+ var WEBKIT = "-webkit-";
911
+ var COMMENT = "comm";
912
+ var RULESET = "rule";
913
+ var DECLARATION = "decl";
914
+ var IMPORT = "@import";
915
+ var KEYFRAMES = "@keyframes";
916
+ var LAYER = "@layer";
917
+
918
+ // ../../node_modules/stylis/src/Utility.js
919
+ var abs = Math.abs;
920
+ var from = String.fromCharCode;
921
+ var assign = Object.assign;
922
+ function hash(value, length2) {
923
+ return charat(value, 0) ^ 45 ? (((length2 << 2 ^ charat(value, 0)) << 2 ^ charat(value, 1)) << 2 ^ charat(value, 2)) << 2 ^ charat(value, 3) : 0;
924
+ }
925
+ function trim(value) {
926
+ return value.trim();
927
+ }
928
+ function match(value, pattern) {
929
+ return (value = pattern.exec(value)) ? value[0] : value;
930
+ }
931
+ function replace(value, pattern, replacement) {
932
+ return value.replace(pattern, replacement);
933
+ }
934
+ function indexof(value, search) {
935
+ return value.indexOf(search);
936
+ }
937
+ function charat(value, index) {
938
+ return value.charCodeAt(index) | 0;
939
+ }
940
+ function substr(value, begin, end) {
941
+ return value.slice(begin, end);
942
+ }
943
+ function strlen(value) {
944
+ return value.length;
945
+ }
946
+ function sizeof(value) {
947
+ return value.length;
948
+ }
949
+ function append(value, array) {
950
+ return array.push(value), value;
951
+ }
952
+ function combine(array, callback) {
953
+ return array.map(callback).join("");
954
+ }
955
+
956
+ // ../../node_modules/stylis/src/Tokenizer.js
957
+ var line = 1;
958
+ var column = 1;
959
+ var length = 0;
960
+ var position = 0;
961
+ var character = 0;
962
+ var characters = "";
963
+ function node(value, root, parent, type, props, children, length2) {
964
+ return { value, root, parent, type, props, children, line, column, length: length2, return: "" };
965
+ }
966
+ function copy(root, props) {
967
+ return assign(node("", null, null, "", null, null, 0), root, { length: -root.length }, props);
968
+ }
969
+ function char() {
970
+ return character;
971
+ }
972
+ function prev() {
973
+ character = position > 0 ? charat(characters, --position) : 0;
974
+ if (column--, character === 10)
975
+ column = 1, line--;
976
+ return character;
977
+ }
978
+ function next() {
979
+ character = position < length ? charat(characters, position++) : 0;
980
+ if (column++, character === 10)
981
+ column = 1, line++;
982
+ return character;
983
+ }
984
+ function peek() {
985
+ return charat(characters, position);
986
+ }
987
+ function caret() {
988
+ return position;
989
+ }
990
+ function slice(begin, end) {
991
+ return substr(characters, begin, end);
992
+ }
993
+ function token(type) {
994
+ switch (type) {
995
+ // \0 \t \n \r \s whitespace token
996
+ case 0:
997
+ case 9:
998
+ case 10:
999
+ case 13:
1000
+ case 32:
1001
+ return 5;
1002
+ // ! + , / > @ ~ isolate token
1003
+ case 33:
1004
+ case 43:
1005
+ case 44:
1006
+ case 47:
1007
+ case 62:
1008
+ case 64:
1009
+ case 126:
1010
+ // ; { } breakpoint token
1011
+ case 59:
1012
+ case 123:
1013
+ case 125:
1014
+ return 4;
1015
+ // : accompanied token
1016
+ case 58:
1017
+ return 3;
1018
+ // " ' ( [ opening delimit token
1019
+ case 34:
1020
+ case 39:
1021
+ case 40:
1022
+ case 91:
1023
+ return 2;
1024
+ // ) ] closing delimit token
1025
+ case 41:
1026
+ case 93:
1027
+ return 1;
1028
+ }
1029
+ return 0;
1030
+ }
1031
+ function alloc(value) {
1032
+ return line = column = 1, length = strlen(characters = value), position = 0, [];
1033
+ }
1034
+ function dealloc(value) {
1035
+ return characters = "", value;
1036
+ }
1037
+ function delimit(type) {
1038
+ return trim(slice(position - 1, delimiter(type === 91 ? type + 2 : type === 40 ? type + 1 : type)));
1039
+ }
1040
+ function whitespace(type) {
1041
+ while (character = peek())
1042
+ if (character < 33)
1043
+ next();
1044
+ else
1045
+ break;
1046
+ return token(type) > 2 || token(character) > 3 ? "" : " ";
1047
+ }
1048
+ function escaping(index, count) {
1049
+ while (--count && next())
1050
+ if (character < 48 || character > 102 || character > 57 && character < 65 || character > 70 && character < 97)
1051
+ break;
1052
+ return slice(index, caret() + (count < 6 && peek() == 32 && next() == 32));
1053
+ }
1054
+ function delimiter(type) {
1055
+ while (next())
1056
+ switch (character) {
1057
+ // ] ) " '
1058
+ case type:
1059
+ return position;
1060
+ // " '
1061
+ case 34:
1062
+ case 39:
1063
+ if (type !== 34 && type !== 39)
1064
+ delimiter(character);
1065
+ break;
1066
+ // (
1067
+ case 40:
1068
+ if (type === 41)
1069
+ delimiter(type);
1070
+ break;
1071
+ // \
1072
+ case 92:
1073
+ next();
1074
+ break;
1075
+ }
1076
+ return position;
1077
+ }
1078
+ function commenter(type, index) {
1079
+ while (next())
1080
+ if (type + character === 47 + 10)
1081
+ break;
1082
+ else if (type + character === 42 + 42 && peek() === 47)
1083
+ break;
1084
+ return "/*" + slice(index, position - 1) + "*" + from(type === 47 ? type : next());
1085
+ }
1086
+ function identifier(index) {
1087
+ while (!token(peek()))
1088
+ next();
1089
+ return slice(index, position);
1090
+ }
1091
+
1092
+ // ../../node_modules/stylis/src/Parser.js
1093
+ function compile(value) {
1094
+ return dealloc(parse("", null, null, null, [""], value = alloc(value), 0, [0], value));
1095
+ }
1096
+ function parse(value, root, parent, rule, rules, rulesets, pseudo, points, declarations) {
1097
+ var index = 0;
1098
+ var offset = 0;
1099
+ var length2 = pseudo;
1100
+ var atrule = 0;
1101
+ var property = 0;
1102
+ var previous = 0;
1103
+ var variable = 1;
1104
+ var scanning = 1;
1105
+ var ampersand = 1;
1106
+ var character2 = 0;
1107
+ var type = "";
1108
+ var props = rules;
1109
+ var children = rulesets;
1110
+ var reference = rule;
1111
+ var characters2 = type;
1112
+ while (scanning)
1113
+ switch (previous = character2, character2 = next()) {
1114
+ // (
1115
+ case 40:
1116
+ if (previous != 108 && charat(characters2, length2 - 1) == 58) {
1117
+ if (indexof(characters2 += replace(delimit(character2), "&", "&\f"), "&\f") != -1)
1118
+ ampersand = -1;
1119
+ break;
1120
+ }
1121
+ // " ' [
1122
+ case 34:
1123
+ case 39:
1124
+ case 91:
1125
+ characters2 += delimit(character2);
1126
+ break;
1127
+ // \t \n \r \s
1128
+ case 9:
1129
+ case 10:
1130
+ case 13:
1131
+ case 32:
1132
+ characters2 += whitespace(previous);
1133
+ break;
1134
+ // \
1135
+ case 92:
1136
+ characters2 += escaping(caret() - 1, 7);
1137
+ continue;
1138
+ // /
1139
+ case 47:
1140
+ switch (peek()) {
1141
+ case 42:
1142
+ case 47:
1143
+ append(comment(commenter(next(), caret()), root, parent), declarations);
1144
+ break;
1145
+ default:
1146
+ characters2 += "/";
1147
+ }
1148
+ break;
1149
+ // {
1150
+ case 123 * variable:
1151
+ points[index++] = strlen(characters2) * ampersand;
1152
+ // } ; \0
1153
+ case 125 * variable:
1154
+ case 59:
1155
+ case 0:
1156
+ switch (character2) {
1157
+ // \0 }
1158
+ case 0:
1159
+ case 125:
1160
+ scanning = 0;
1161
+ // ;
1162
+ case 59 + offset:
1163
+ if (ampersand == -1) characters2 = replace(characters2, /\f/g, "");
1164
+ if (property > 0 && strlen(characters2) - length2)
1165
+ append(property > 32 ? declaration(characters2 + ";", rule, parent, length2 - 1) : declaration(replace(characters2, " ", "") + ";", rule, parent, length2 - 2), declarations);
1166
+ break;
1167
+ // @ ;
1168
+ case 59:
1169
+ characters2 += ";";
1170
+ // { rule/at-rule
1171
+ default:
1172
+ append(reference = ruleset(characters2, root, parent, index, offset, rules, points, type, props = [], children = [], length2), rulesets);
1173
+ if (character2 === 123)
1174
+ if (offset === 0)
1175
+ parse(characters2, root, reference, reference, props, rulesets, length2, points, children);
1176
+ else
1177
+ switch (atrule === 99 && charat(characters2, 3) === 110 ? 100 : atrule) {
1178
+ // d l m s
1179
+ case 100:
1180
+ case 108:
1181
+ case 109:
1182
+ case 115:
1183
+ parse(value, reference, reference, rule && append(ruleset(value, reference, reference, 0, 0, rules, points, type, rules, props = [], length2), children), rules, children, length2, points, rule ? props : children);
1184
+ break;
1185
+ default:
1186
+ parse(characters2, reference, reference, reference, [""], children, 0, points, children);
1187
+ }
1188
+ }
1189
+ index = offset = property = 0, variable = ampersand = 1, type = characters2 = "", length2 = pseudo;
1190
+ break;
1191
+ // :
1192
+ case 58:
1193
+ length2 = 1 + strlen(characters2), property = previous;
1194
+ default:
1195
+ if (variable < 1) {
1196
+ if (character2 == 123)
1197
+ --variable;
1198
+ else if (character2 == 125 && variable++ == 0 && prev() == 125)
1199
+ continue;
1200
+ }
1201
+ switch (characters2 += from(character2), character2 * variable) {
1202
+ // &
1203
+ case 38:
1204
+ ampersand = offset > 0 ? 1 : (characters2 += "\f", -1);
1205
+ break;
1206
+ // ,
1207
+ case 44:
1208
+ points[index++] = (strlen(characters2) - 1) * ampersand, ampersand = 1;
1209
+ break;
1210
+ // @
1211
+ case 64:
1212
+ if (peek() === 45)
1213
+ characters2 += delimit(next());
1214
+ atrule = peek(), offset = length2 = strlen(type = characters2 += identifier(caret())), character2++;
1215
+ break;
1216
+ // -
1217
+ case 45:
1218
+ if (previous === 45 && strlen(characters2) == 2)
1219
+ variable = 0;
1220
+ }
1221
+ }
1222
+ return rulesets;
1223
+ }
1224
+ function ruleset(value, root, parent, index, offset, rules, points, type, props, children, length2) {
1225
+ var post = offset - 1;
1226
+ var rule = offset === 0 ? rules : [""];
1227
+ var size = sizeof(rule);
1228
+ for (var i = 0, j = 0, k = 0; i < index; ++i)
1229
+ for (var x = 0, y = substr(value, post + 1, post = abs(j = points[i])), z = value; x < size; ++x)
1230
+ if (z = trim(j > 0 ? rule[x] + " " + y : replace(y, /&\f/g, rule[x])))
1231
+ props[k++] = z;
1232
+ return node(value, root, parent, offset === 0 ? RULESET : type, props, children, length2);
1233
+ }
1234
+ function comment(value, root, parent) {
1235
+ return node(value, root, parent, COMMENT, from(char()), substr(value, 2, -2), 0);
1236
+ }
1237
+ function declaration(value, root, parent, length2) {
1238
+ return node(value, root, parent, DECLARATION, substr(value, 0, length2), substr(value, length2 + 1, -1), length2);
1239
+ }
1240
+
1241
+ // ../../node_modules/stylis/src/Serializer.js
1242
+ function serialize(children, callback) {
1243
+ var output = "";
1244
+ var length2 = sizeof(children);
1245
+ for (var i = 0; i < length2; i++)
1246
+ output += callback(children[i], i, children, callback) || "";
1247
+ return output;
1248
+ }
1249
+ function stringify(element, index, children, callback) {
1250
+ switch (element.type) {
1251
+ case LAYER:
1252
+ if (element.children.length) break;
1253
+ case IMPORT:
1254
+ case DECLARATION:
1255
+ return element.return = element.return || element.value;
1256
+ case COMMENT:
1257
+ return "";
1258
+ case KEYFRAMES:
1259
+ return element.return = element.value + "{" + serialize(element.children, callback) + "}";
1260
+ case RULESET:
1261
+ element.value = element.props.join(",");
1262
+ }
1263
+ return strlen(children = serialize(element.children, callback)) ? element.return = element.value + "{" + children + "}" : "";
1264
+ }
1265
+
1266
+ // ../../node_modules/stylis/src/Middleware.js
1267
+ function middleware(collection) {
1268
+ var length2 = sizeof(collection);
1269
+ return function(element, index, children, callback) {
1270
+ var output = "";
1271
+ for (var i = 0; i < length2; i++)
1272
+ output += collection[i](element, index, children, callback) || "";
1273
+ return output;
1274
+ };
1275
+ }
1276
+ function rulesheet(callback) {
1277
+ return function(element) {
1278
+ if (!element.root) {
1279
+ if (element = element.return)
1280
+ callback(element);
1281
+ }
1282
+ };
1283
+ }
1284
+
1285
+ // ../../node_modules/@emotion/weak-memoize/dist/emotion-weak-memoize.esm.js
1286
+ var weakMemoize = function weakMemoize2(func) {
1287
+ var cache = /* @__PURE__ */ new WeakMap();
1288
+ return function(arg) {
1289
+ if (cache.has(arg)) {
1290
+ return cache.get(arg);
1291
+ }
1292
+ var ret = func(arg);
1293
+ cache.set(arg, ret);
1294
+ return ret;
1295
+ };
1296
+ };
1297
+
1298
+ // ../../node_modules/@emotion/memoize/dist/emotion-memoize.esm.js
1299
+ function memoize(fn) {
1300
+ var cache = /* @__PURE__ */ Object.create(null);
1301
+ return function(arg) {
1302
+ if (cache[arg] === void 0) cache[arg] = fn(arg);
1303
+ return cache[arg];
1304
+ };
1305
+ }
1306
+
1307
+ // ../../node_modules/@emotion/cache/dist/emotion-cache.esm.js
1308
+ var isBrowser = typeof document !== "undefined";
1309
+ var identifierWithPointTracking = function identifierWithPointTracking2(begin, points, index) {
1310
+ var previous = 0;
1311
+ var character2 = 0;
1312
+ while (true) {
1313
+ previous = character2;
1314
+ character2 = peek();
1315
+ if (previous === 38 && character2 === 12) {
1316
+ points[index] = 1;
1317
+ }
1318
+ if (token(character2)) {
1319
+ break;
1320
+ }
1321
+ next();
1322
+ }
1323
+ return slice(begin, position);
1324
+ };
1325
+ var toRules = function toRules2(parsed, points) {
1326
+ var index = -1;
1327
+ var character2 = 44;
1328
+ do {
1329
+ switch (token(character2)) {
1330
+ case 0:
1331
+ if (character2 === 38 && peek() === 12) {
1332
+ points[index] = 1;
1333
+ }
1334
+ parsed[index] += identifierWithPointTracking(position - 1, points, index);
1335
+ break;
1336
+ case 2:
1337
+ parsed[index] += delimit(character2);
1338
+ break;
1339
+ case 4:
1340
+ if (character2 === 44) {
1341
+ parsed[++index] = peek() === 58 ? "&\f" : "";
1342
+ points[index] = parsed[index].length;
1343
+ break;
1344
+ }
1345
+ // fallthrough
1346
+ default:
1347
+ parsed[index] += from(character2);
1348
+ }
1349
+ } while (character2 = next());
1350
+ return parsed;
1351
+ };
1352
+ var getRules = function getRules2(value, points) {
1353
+ return dealloc(toRules(alloc(value), points));
1354
+ };
1355
+ var fixedElements = /* @__PURE__ */ new WeakMap();
1356
+ var compat = function compat2(element) {
1357
+ if (element.type !== "rule" || !element.parent || // positive .length indicates that this rule contains pseudo
1358
+ // negative .length indicates that this rule has been already prefixed
1359
+ element.length < 1) {
1360
+ return;
1361
+ }
1362
+ var value = element.value;
1363
+ var parent = element.parent;
1364
+ var isImplicitRule = element.column === parent.column && element.line === parent.line;
1365
+ while (parent.type !== "rule") {
1366
+ parent = parent.parent;
1367
+ if (!parent) return;
1368
+ }
1369
+ if (element.props.length === 1 && value.charCodeAt(0) !== 58 && !fixedElements.get(parent)) {
1370
+ return;
1371
+ }
1372
+ if (isImplicitRule) {
1373
+ return;
1374
+ }
1375
+ fixedElements.set(element, true);
1376
+ var points = [];
1377
+ var rules = getRules(value, points);
1378
+ var parentRules = parent.props;
1379
+ for (var i = 0, k = 0; i < rules.length; i++) {
1380
+ for (var j = 0; j < parentRules.length; j++, k++) {
1381
+ element.props[k] = points[i] ? rules[i].replace(/&\f/g, parentRules[j]) : parentRules[j] + " " + rules[i];
1382
+ }
1383
+ }
1384
+ };
1385
+ var removeLabel = function removeLabel2(element) {
1386
+ if (element.type === "decl") {
1387
+ var value = element.value;
1388
+ if (
1389
+ // charcode for l
1390
+ value.charCodeAt(0) === 108 && // charcode for b
1391
+ value.charCodeAt(2) === 98
1392
+ ) {
1393
+ element["return"] = "";
1394
+ element.value = "";
1395
+ }
1396
+ }
1397
+ };
1398
+ function prefix(value, length2) {
1399
+ switch (hash(value, length2)) {
1400
+ // color-adjust
1401
+ case 5103:
1402
+ return WEBKIT + "print-" + value + value;
1403
+ // animation, animation-(delay|direction|duration|fill-mode|iteration-count|name|play-state|timing-function)
1404
+ case 5737:
1405
+ case 4201:
1406
+ case 3177:
1407
+ case 3433:
1408
+ case 1641:
1409
+ case 4457:
1410
+ case 2921:
1411
+ // text-decoration, filter, clip-path, backface-visibility, column, box-decoration-break
1412
+ case 5572:
1413
+ case 6356:
1414
+ case 5844:
1415
+ case 3191:
1416
+ case 6645:
1417
+ case 3005:
1418
+ // mask, mask-image, mask-(mode|clip|size), mask-(repeat|origin), mask-position, mask-composite,
1419
+ case 6391:
1420
+ case 5879:
1421
+ case 5623:
1422
+ case 6135:
1423
+ case 4599:
1424
+ case 4855:
1425
+ // background-clip, columns, column-(count|fill|gap|rule|rule-color|rule-style|rule-width|span|width)
1426
+ case 4215:
1427
+ case 6389:
1428
+ case 5109:
1429
+ case 5365:
1430
+ case 5621:
1431
+ case 3829:
1432
+ return WEBKIT + value + value;
1433
+ // appearance, user-select, transform, hyphens, text-size-adjust
1434
+ case 5349:
1435
+ case 4246:
1436
+ case 4810:
1437
+ case 6968:
1438
+ case 2756:
1439
+ return WEBKIT + value + MOZ + value + MS + value + value;
1440
+ // flex, flex-direction
1441
+ case 6828:
1442
+ case 4268:
1443
+ return WEBKIT + value + MS + value + value;
1444
+ // order
1445
+ case 6165:
1446
+ return WEBKIT + value + MS + "flex-" + value + value;
1447
+ // align-items
1448
+ case 5187:
1449
+ return WEBKIT + value + replace(value, /(\w+).+(:[^]+)/, WEBKIT + "box-$1$2" + MS + "flex-$1$2") + value;
1450
+ // align-self
1451
+ case 5443:
1452
+ return WEBKIT + value + MS + "flex-item-" + replace(value, /flex-|-self/, "") + value;
1453
+ // align-content
1454
+ case 4675:
1455
+ return WEBKIT + value + MS + "flex-line-pack" + replace(value, /align-content|flex-|-self/, "") + value;
1456
+ // flex-shrink
1457
+ case 5548:
1458
+ return WEBKIT + value + MS + replace(value, "shrink", "negative") + value;
1459
+ // flex-basis
1460
+ case 5292:
1461
+ return WEBKIT + value + MS + replace(value, "basis", "preferred-size") + value;
1462
+ // flex-grow
1463
+ case 6060:
1464
+ return WEBKIT + "box-" + replace(value, "-grow", "") + WEBKIT + value + MS + replace(value, "grow", "positive") + value;
1465
+ // transition
1466
+ case 4554:
1467
+ return WEBKIT + replace(value, /([^-])(transform)/g, "$1" + WEBKIT + "$2") + value;
1468
+ // cursor
1469
+ case 6187:
1470
+ return replace(replace(replace(value, /(zoom-|grab)/, WEBKIT + "$1"), /(image-set)/, WEBKIT + "$1"), value, "") + value;
1471
+ // background, background-image
1472
+ case 5495:
1473
+ case 3959:
1474
+ return replace(value, /(image-set\([^]*)/, WEBKIT + "$1$`$1");
1475
+ // justify-content
1476
+ case 4968:
1477
+ return replace(replace(value, /(.+:)(flex-)?(.*)/, WEBKIT + "box-pack:$3" + MS + "flex-pack:$3"), /s.+-b[^;]+/, "justify") + WEBKIT + value + value;
1478
+ // (margin|padding)-inline-(start|end)
1479
+ case 4095:
1480
+ case 3583:
1481
+ case 4068:
1482
+ case 2532:
1483
+ return replace(value, /(.+)-inline(.+)/, WEBKIT + "$1$2") + value;
1484
+ // (min|max)?(width|height|inline-size|block-size)
1485
+ case 8116:
1486
+ case 7059:
1487
+ case 5753:
1488
+ case 5535:
1489
+ case 5445:
1490
+ case 5701:
1491
+ case 4933:
1492
+ case 4677:
1493
+ case 5533:
1494
+ case 5789:
1495
+ case 5021:
1496
+ case 4765:
1497
+ if (strlen(value) - 1 - length2 > 6) switch (charat(value, length2 + 1)) {
1498
+ // (m)ax-content, (m)in-content
1499
+ case 109:
1500
+ if (charat(value, length2 + 4) !== 45) break;
1501
+ // (f)ill-available, (f)it-content
1502
+ case 102:
1503
+ return replace(value, /(.+:)(.+)-([^]+)/, "$1" + WEBKIT + "$2-$3$1" + MOZ + (charat(value, length2 + 3) == 108 ? "$3" : "$2-$3")) + value;
1504
+ // (s)tretch
1505
+ case 115:
1506
+ return ~indexof(value, "stretch") ? prefix(replace(value, "stretch", "fill-available"), length2) + value : value;
1507
+ }
1508
+ break;
1509
+ // position: sticky
1510
+ case 4949:
1511
+ if (charat(value, length2 + 1) !== 115) break;
1512
+ // display: (flex|inline-flex)
1513
+ case 6444:
1514
+ switch (charat(value, strlen(value) - 3 - (~indexof(value, "!important") && 10))) {
1515
+ // stic(k)y
1516
+ case 107:
1517
+ return replace(value, ":", ":" + WEBKIT) + value;
1518
+ // (inline-)?fl(e)x
1519
+ case 101:
1520
+ return replace(value, /(.+:)([^;!]+)(;|!.+)?/, "$1" + WEBKIT + (charat(value, 14) === 45 ? "inline-" : "") + "box$3$1" + WEBKIT + "$2$3$1" + MS + "$2box$3") + value;
1521
+ }
1522
+ break;
1523
+ // writing-mode
1524
+ case 5936:
1525
+ switch (charat(value, length2 + 11)) {
1526
+ // vertical-l(r)
1527
+ case 114:
1528
+ return WEBKIT + value + MS + replace(value, /[svh]\w+-[tblr]{2}/, "tb") + value;
1529
+ // vertical-r(l)
1530
+ case 108:
1531
+ return WEBKIT + value + MS + replace(value, /[svh]\w+-[tblr]{2}/, "tb-rl") + value;
1532
+ // horizontal(-)tb
1533
+ case 45:
1534
+ return WEBKIT + value + MS + replace(value, /[svh]\w+-[tblr]{2}/, "lr") + value;
1535
+ }
1536
+ return WEBKIT + value + MS + value + value;
1537
+ }
1538
+ return value;
1539
+ }
1540
+ var prefixer = function prefixer2(element, index, children, callback) {
1541
+ if (element.length > -1) {
1542
+ if (!element["return"]) switch (element.type) {
1543
+ case DECLARATION:
1544
+ element["return"] = prefix(element.value, element.length);
1545
+ break;
1546
+ case KEYFRAMES:
1547
+ return serialize([copy(element, {
1548
+ value: replace(element.value, "@", "@" + WEBKIT)
1549
+ })], callback);
1550
+ case RULESET:
1551
+ if (element.length) return combine(element.props, function(value) {
1552
+ switch (match(value, /(::plac\w+|:read-\w+)/)) {
1553
+ // :read-(only|write)
1554
+ case ":read-only":
1555
+ case ":read-write":
1556
+ return serialize([copy(element, {
1557
+ props: [replace(value, /:(read-\w+)/, ":" + MOZ + "$1")]
1558
+ })], callback);
1559
+ // :placeholder
1560
+ case "::placeholder":
1561
+ return serialize([copy(element, {
1562
+ props: [replace(value, /:(plac\w+)/, ":" + WEBKIT + "input-$1")]
1563
+ }), copy(element, {
1564
+ props: [replace(value, /:(plac\w+)/, ":" + MOZ + "$1")]
1565
+ }), copy(element, {
1566
+ props: [replace(value, /:(plac\w+)/, MS + "input-$1")]
1567
+ })], callback);
1568
+ }
1569
+ return "";
1570
+ });
1571
+ }
1572
+ }
1573
+ };
1574
+ var getServerStylisCache = isBrowser ? void 0 : weakMemoize(function() {
1575
+ return memoize(function() {
1576
+ return {};
1577
+ });
1578
+ });
1579
+ var defaultStylisPlugins = [prefixer];
1580
+ var createCache = function createCache2(options) {
1581
+ var key = options.key;
1582
+ if (isBrowser && key === "css") {
1583
+ var ssrStyles = document.querySelectorAll("style[data-emotion]:not([data-s])");
1584
+ Array.prototype.forEach.call(ssrStyles, function(node2) {
1585
+ var dataEmotionAttribute = node2.getAttribute("data-emotion");
1586
+ if (dataEmotionAttribute.indexOf(" ") === -1) {
1587
+ return;
1588
+ }
1589
+ document.head.appendChild(node2);
1590
+ node2.setAttribute("data-s", "");
1591
+ });
1592
+ }
1593
+ var stylisPlugins = options.stylisPlugins || defaultStylisPlugins;
1594
+ var inserted = {};
1595
+ var container;
1596
+ var nodesToHydrate = [];
1597
+ if (isBrowser) {
1598
+ container = options.container || document.head;
1599
+ Array.prototype.forEach.call(
1600
+ // this means we will ignore elements which don't have a space in them which
1601
+ // means that the style elements we're looking at are only Emotion 11 server-rendered style elements
1602
+ document.querySelectorAll('style[data-emotion^="' + key + ' "]'),
1603
+ function(node2) {
1604
+ var attrib = node2.getAttribute("data-emotion").split(" ");
1605
+ for (var i = 1; i < attrib.length; i++) {
1606
+ inserted[attrib[i]] = true;
1607
+ }
1608
+ nodesToHydrate.push(node2);
1609
+ }
1610
+ );
1611
+ }
1612
+ var _insert;
1613
+ var omnipresentPlugins = [compat, removeLabel];
1614
+ if (!getServerStylisCache) {
1615
+ var currentSheet;
1616
+ var finalizingPlugins = [stringify, rulesheet(function(rule) {
1617
+ currentSheet.insert(rule);
1618
+ })];
1619
+ var serializer = middleware(omnipresentPlugins.concat(stylisPlugins, finalizingPlugins));
1620
+ var stylis = function stylis2(styles) {
1621
+ return serialize(compile(styles), serializer);
1622
+ };
1623
+ _insert = function insert(selector, serialized, sheet, shouldCache) {
1624
+ currentSheet = sheet;
1625
+ stylis(selector ? selector + "{" + serialized.styles + "}" : serialized.styles);
1626
+ if (shouldCache) {
1627
+ cache.inserted[serialized.name] = true;
1628
+ }
1629
+ };
1630
+ } else {
1631
+ var _finalizingPlugins = [stringify];
1632
+ var _serializer = middleware(omnipresentPlugins.concat(stylisPlugins, _finalizingPlugins));
1633
+ var _stylis = function _stylis2(styles) {
1634
+ return serialize(compile(styles), _serializer);
1635
+ };
1636
+ var serverStylisCache = getServerStylisCache(stylisPlugins)(key);
1637
+ var getRules3 = function getRules4(selector, serialized) {
1638
+ var name = serialized.name;
1639
+ if (serverStylisCache[name] === void 0) {
1640
+ serverStylisCache[name] = _stylis(selector ? selector + "{" + serialized.styles + "}" : serialized.styles);
1641
+ }
1642
+ return serverStylisCache[name];
1643
+ };
1644
+ _insert = function _insert2(selector, serialized, sheet, shouldCache) {
1645
+ var name = serialized.name;
1646
+ var rules = getRules3(selector, serialized);
1647
+ if (cache.compat === void 0) {
1648
+ if (shouldCache) {
1649
+ cache.inserted[name] = true;
1650
+ }
1651
+ return rules;
1652
+ } else {
1653
+ if (shouldCache) {
1654
+ cache.inserted[name] = rules;
1655
+ } else {
1656
+ return rules;
1657
+ }
1658
+ }
1659
+ };
1660
+ }
1661
+ var cache = {
1662
+ key,
1663
+ sheet: new StyleSheet({
1664
+ key,
1665
+ container,
1666
+ nonce: options.nonce,
1667
+ speedy: options.speedy,
1668
+ prepend: options.prepend,
1669
+ insertionPoint: options.insertionPoint
1670
+ }),
1671
+ nonce: options.nonce,
1672
+ inserted,
1673
+ registered: {},
1674
+ insert: _insert
1675
+ };
1676
+ cache.sheet.hydrate(nodesToHydrate);
1677
+ return cache;
1678
+ };
1679
+
1680
+ // src/react/styles/cache.ts
1681
+ var createWidgetCache = (container) => {
1682
+ return createCache({
1683
+ key: "la-widget",
1684
+ container,
1685
+ prepend: true
1686
+ });
1687
+ };
1688
+ var widgetCache = createCache({
1689
+ key: "la-widget",
1690
+ prepend: true
1691
+ });
1692
+ styled__default.default.div`
1693
+ display: flex;
1694
+ flex-direction: column;
1695
+ height: 100%;
1696
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.primary};
1697
+ color: ${({ theme: theme2 }) => theme2.colors.text.primary};
1698
+ font-family: ${({ theme: theme2 }) => theme2.typography.fontFamily};
1699
+ `;
1700
+ styled__default.default.div`
1701
+ flex: 1;
1702
+ overflow-y: auto;
1703
+ padding: ${({ theme: theme2 }) => theme2.spacing.md};
1704
+
1705
+ &::-webkit-scrollbar {
1706
+ width: 6px;
1707
+ }
1708
+
1709
+ &::-webkit-scrollbar-track {
1710
+ background: transparent;
1711
+ }
1712
+
1713
+ &::-webkit-scrollbar-thumb {
1714
+ background: ${({ theme: theme2 }) => theme2.colors.background.tertiary};
1715
+ border-radius: ${({ theme: theme2 }) => theme2.radii.full};
1716
+ }
1717
+ `;
1718
+ var Flex = styled__default.default.div`
1719
+ display: flex;
1720
+ flex-direction: ${({ direction = "row" }) => direction};
1721
+ align-items: ${({ align = "stretch" }) => align};
1722
+ justify-content: ${({ justify = "flex-start" }) => justify};
1723
+ gap: ${({ theme: theme2, gap }) => gap ? theme2.spacing[gap] : 0};
1724
+ flex-wrap: ${({ wrap }) => wrap ? "wrap" : "nowrap"};
1725
+ `;
1726
+ styled__default.default.div`
1727
+ display: grid;
1728
+ grid-template-columns: ${({ columns = 1 }) => typeof columns === "number" ? `repeat(${columns}, 1fr)` : columns};
1729
+ gap: ${({ theme: theme2, gap = "md" }) => theme2.spacing[gap]};
1730
+ `;
1731
+ styled__default.default.div`
1732
+ display: flex;
1733
+ align-items: center;
1734
+ justify-content: space-between;
1735
+ padding: ${({ theme: theme2 }) => theme2.spacing.md};
1736
+ border-bottom: 1px solid ${({ theme: theme2 }) => theme2.colors.border};
1737
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.primary};
1738
+ `;
1739
+ styled__default.default.h2`
1740
+ margin: 0;
1741
+ font-size: ${({ theme: theme2 }) => theme2.typography.fontSize.md};
1742
+ font-weight: ${({ theme: theme2 }) => theme2.typography.fontWeight.medium};
1743
+ color: ${({ theme: theme2 }) => theme2.colors.text.primary};
1744
+ `;
1745
+ styled__default.default.button`
1746
+ display: inline-flex;
1747
+ align-items: center;
1748
+ justify-content: center;
1749
+ gap: ${({ theme: theme2 }) => theme2.spacing.sm};
1750
+ padding: ${({ theme: theme2, size = "md" }) => {
1751
+ const sizes = {
1752
+ sm: `${theme2.spacing.sm} ${theme2.spacing.md}`,
1753
+ md: `${theme2.spacing.md} ${theme2.spacing.lg}`,
1754
+ lg: `${theme2.spacing.lg} ${theme2.spacing.xl}`
1755
+ };
1756
+ return sizes[size];
1757
+ }};
1758
+ width: ${({ fullWidth }) => fullWidth ? "100%" : "auto"};
1759
+ font-family: ${({ theme: theme2 }) => theme2.typography.fontFamily};
1760
+ font-size: ${({ theme: theme2 }) => theme2.typography.fontSize.sm};
1761
+ font-weight: ${({ theme: theme2 }) => theme2.typography.fontWeight.medium};
1762
+ border-radius: ${({ theme: theme2 }) => theme2.radii.sm};
1763
+ border: none;
1764
+ cursor: pointer;
1765
+ transition: all ${({ theme: theme2 }) => theme2.transitions.fast};
1766
+
1767
+ ${({ theme: theme2, variant = "primary" }) => {
1768
+ switch (variant) {
1769
+ case "primary":
1770
+ return `
1771
+ background-color: ${theme2.colors.accent.primary};
1772
+ color: ${theme2.colors.text.inverse};
1773
+ &:hover:not(:disabled) {
1774
+ background-color: ${theme2.colors.accent.hover};
1775
+ }
1776
+ `;
1777
+ case "secondary":
1778
+ return `
1779
+ background-color: ${theme2.colors.background.secondary};
1780
+ color: ${theme2.colors.text.primary};
1781
+ &:hover:not(:disabled) {
1782
+ background-color: ${theme2.colors.background.tertiary};
1783
+ }
1784
+ `;
1785
+ case "ghost":
1786
+ return `
1787
+ background: none;
1788
+ color: ${theme2.colors.text.secondary};
1789
+ &:hover:not(:disabled) {
1790
+ color: ${theme2.colors.text.primary};
1791
+ background-color: ${theme2.colors.background.secondary};
1792
+ }
1793
+ `;
1794
+ }
1795
+ }}
1796
+
1797
+ &:disabled {
1798
+ opacity: 0.5;
1799
+ cursor: not-allowed;
1800
+ }
1801
+ `;
1802
+ var IconButton = styled__default.default.button`
1803
+ display: inline-flex;
1804
+ align-items: center;
1805
+ justify-content: center;
1806
+ padding: ${({ theme: theme2 }) => theme2.spacing.xs};
1807
+ background: none;
1808
+ border: none;
1809
+ color: ${({ theme: theme2 }) => theme2.colors.text.primary};
1810
+ font-size: ${({ size = "md" }) => {
1811
+ const sizes = { sm: "1rem", md: "1.25rem", lg: "1.5rem" };
1812
+ return sizes[size];
1813
+ }};
1814
+ cursor: pointer;
1815
+ transition: color ${({ theme: theme2 }) => theme2.transitions.fast};
1816
+ line-height: 1;
1817
+
1818
+ &:hover {
1819
+ color: ${({ theme: theme2 }) => theme2.colors.text.secondary};
1820
+ }
1821
+ `;
1822
+ var FAB = styled__default.default(react$1.motion.button)`
1823
+ width: 48px;
1824
+ height: 48px;
1825
+ border-radius: 50%;
1826
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.primary};
1827
+ border: none;
1828
+ box-shadow: ${({ theme: theme2 }) => theme2.shadows.sm};
1829
+ cursor: pointer;
1830
+ display: flex;
1831
+ align-items: center;
1832
+ justify-content: center;
1833
+ font-size: 1.25rem;
1834
+ color: white;
1835
+ transition: box-shadow ${({ theme: theme2 }) => theme2.transitions.fast};
1836
+ position: relative;
1837
+ overflow: hidden;
1838
+
1839
+ &:hover {
1840
+ box-shadow: ${({ theme: theme2 }) => theme2.shadows.md};
1841
+ }
1842
+ `;
1843
+ styled__default.default.input`
1844
+ width: 100%;
1845
+ padding: ${({ theme: theme2 }) => `${theme2.spacing.md} ${theme2.spacing.md}`};
1846
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.secondary};
1847
+ border: none;
1848
+ border-radius: ${({ theme: theme2 }) => theme2.radii.sm};
1849
+ color: ${({ theme: theme2 }) => theme2.colors.text.primary};
1850
+ font-family: ${({ theme: theme2 }) => theme2.typography.fontFamily};
1851
+ font-size: ${({ theme: theme2 }) => theme2.typography.fontSize.sm};
1852
+ outline: none;
1853
+ transition: background-color ${({ theme: theme2 }) => theme2.transitions.fast};
1854
+
1855
+ &::placeholder {
1856
+ color: ${({ theme: theme2 }) => theme2.colors.text.secondary};
1857
+ }
1858
+
1859
+ &:focus {
1860
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.tertiary};
1861
+ }
1862
+
1863
+ &:disabled {
1864
+ opacity: 0.5;
1865
+ cursor: not-allowed;
1866
+ }
1867
+ `;
1868
+ styled__default.default.textarea`
1869
+ width: 100%;
1870
+ min-height: 150px;
1871
+ padding: ${({ theme: theme2 }) => theme2.spacing.md};
1872
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.secondary};
1873
+ border: none;
1874
+ border-radius: ${({ theme: theme2 }) => theme2.radii.sm};
1875
+ color: ${({ theme: theme2 }) => theme2.colors.text.primary};
1876
+ font-family: ${({ theme: theme2 }) => theme2.typography.fontFamily};
1877
+ font-size: ${({ theme: theme2 }) => theme2.typography.fontSize.sm};
1878
+ line-height: ${({ theme: theme2 }) => theme2.typography.lineHeight.normal};
1879
+ resize: vertical;
1880
+ outline: none;
1881
+
1882
+ &::placeholder {
1883
+ color: ${({ theme: theme2 }) => theme2.colors.text.secondary};
1884
+ }
1885
+
1886
+ &:focus {
1887
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.tertiary};
1888
+ }
1889
+ `;
1890
+ styled__default.default.button`
1891
+ display: flex;
1892
+ align-items: center;
1893
+ gap: ${({ theme: theme2 }) => theme2.spacing.md};
1894
+ width: 100%;
1895
+ padding: ${({ theme: theme2 }) => theme2.spacing.md};
1896
+ background-color: ${({ theme: theme2, selected }) => selected ? theme2.colors.background.tertiary : theme2.colors.background.secondary};
1897
+ border: 2px solid
1898
+ ${({ theme: theme2, selected }) => selected ? theme2.colors.accent.primary : "transparent"};
1899
+ border-radius: ${({ theme: theme2 }) => theme2.radii.sm};
1900
+ color: ${({ theme: theme2 }) => theme2.colors.text.primary};
1901
+ font-family: ${({ theme: theme2 }) => theme2.typography.fontFamily};
1902
+ text-align: left;
1903
+ cursor: ${({ interactive = true }) => interactive ? "pointer" : "default"};
1904
+ transition: all ${({ theme: theme2 }) => theme2.transitions.fast};
1905
+
1906
+ &:hover {
1907
+ background-color: ${({ theme: theme2, interactive = true }) => interactive ? theme2.colors.background.tertiary : theme2.colors.background.secondary};
1908
+ }
1909
+ `;
1910
+ styled__default.default.div`
1911
+ flex: 1;
1912
+ min-width: 0;
1913
+ `;
1914
+ styled__default.default.div`
1915
+ font-weight: ${({ theme: theme2 }) => theme2.typography.fontWeight.medium};
1916
+ margin-bottom: ${({ theme: theme2 }) => theme2.spacing.xs};
1917
+ white-space: nowrap;
1918
+ overflow: hidden;
1919
+ text-overflow: ellipsis;
1920
+ `;
1921
+ styled__default.default.div`
1922
+ color: ${({ theme: theme2 }) => theme2.colors.text.secondary};
1923
+ font-size: ${({ theme: theme2 }) => theme2.typography.fontSize.xs};
1924
+ `;
1925
+ styled__default.default.button`
1926
+ display: flex;
1927
+ flex-direction: column;
1928
+ align-items: center;
1929
+ justify-content: center;
1930
+ padding: ${({ theme: theme2 }) => theme2.spacing.md};
1931
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.secondary};
1932
+ border: none;
1933
+ border-radius: ${({ theme: theme2 }) => theme2.radii.sm};
1934
+ color: ${({ theme: theme2 }) => theme2.colors.text.primary};
1935
+ font-family: ${({ theme: theme2 }) => theme2.typography.fontFamily};
1936
+ font-size: ${({ theme: theme2 }) => theme2.typography.fontSize.xs};
1937
+ gap: ${({ theme: theme2 }) => theme2.spacing.xs};
1938
+ cursor: pointer;
1939
+ transition: background-color ${({ theme: theme2 }) => theme2.transitions.fast};
1940
+
1941
+ &:hover {
1942
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.tertiary};
1943
+ }
1944
+ `;
1945
+ styled__default.default.span`
1946
+ font-size: 1.25rem;
1947
+ `;
1948
+ styled__default.default.div`
1949
+ width: ${({ size = "md" }) => {
1950
+ const sizes = { sm: "40px", md: "64px", lg: "80px" };
1951
+ return sizes[size];
1952
+ }};
1953
+ height: ${({ size = "md" }) => {
1954
+ const sizes = { sm: "40px", md: "64px", lg: "80px" };
1955
+ return sizes[size];
1956
+ }};
1957
+ border-radius: ${({ theme: theme2 }) => theme2.radii.full};
1958
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.secondary};
1959
+ display: flex;
1960
+ align-items: center;
1961
+ justify-content: center;
1962
+ font-size: ${({ size = "md" }) => {
1963
+ const sizes = { sm: "1rem", md: "1.5rem", lg: "2rem" };
1964
+ return sizes[size];
1965
+ }};
1966
+ `;
1967
+ styled__default.default.h1`
1968
+ margin: 0;
1969
+ font-size: ${({ theme: theme2, size = "md" }) => {
1970
+ const sizes = {
1971
+ sm: theme2.typography.fontSize.lg,
1972
+ md: theme2.typography.fontSize.xl,
1973
+ lg: theme2.typography.fontSize["2xl"]
1974
+ };
1975
+ return sizes[size];
1976
+ }};
1977
+ font-weight: ${({ theme: theme2 }) => theme2.typography.fontWeight.medium};
1978
+ color: ${({ theme: theme2 }) => theme2.colors.text.primary};
1979
+ `;
1980
+ var Text = styled__default.default.p`
1981
+ margin: 0;
1982
+ font-size: ${({ theme: theme2, size = "md" }) => theme2.typography.fontSize[size]};
1983
+ color: ${({ theme: theme2, color = "primary" }) => {
1984
+ if (color === "accent") return theme2.colors.accent.primary;
1985
+ return theme2.colors.text[color];
1986
+ }};
1987
+ line-height: ${({ theme: theme2 }) => theme2.typography.lineHeight.normal};
1988
+ `;
1989
+ styled__default.default.button`
1990
+ background: none;
1991
+ border: none;
1992
+ color: ${({ theme: theme2 }) => theme2.colors.text.secondary};
1993
+ font-family: ${({ theme: theme2 }) => theme2.typography.fontFamily};
1994
+ font-size: ${({ theme: theme2 }) => theme2.typography.fontSize.sm};
1995
+ text-decoration: underline;
1996
+ cursor: pointer;
1997
+ padding: 0;
1998
+
1999
+ &:hover {
2000
+ color: ${({ theme: theme2 }) => theme2.colors.text.primary};
2001
+ }
2002
+ `;
2003
+ styled__default.default.div`
2004
+ width: 100%;
2005
+ height: 1px;
2006
+ background-color: ${({ theme: theme2 }) => theme2.colors.border};
2007
+ `;
2008
+ styled__default.default.button`
2009
+ display: flex;
2010
+ flex-direction: column;
2011
+ width: 100%;
2012
+ padding: ${({ theme: theme2 }) => theme2.spacing.md};
2013
+ background: transparent;
2014
+ border: none;
2015
+ border-bottom: 1px solid ${({ theme: theme2 }) => theme2.colors.border};
2016
+ color: ${({ theme: theme2 }) => theme2.colors.text.primary};
2017
+ font-family: ${({ theme: theme2 }) => theme2.typography.fontFamily};
2018
+ text-align: left;
2019
+ cursor: pointer;
2020
+ transition: background-color ${({ theme: theme2 }) => theme2.transitions.fast};
2021
+
2022
+ &:hover {
2023
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.secondary};
2024
+ }
2025
+ `;
2026
+ var WidgetRoot = styled__default.default.div`
2027
+ position: fixed;
2028
+ bottom: 20px;
2029
+ ${({ position: position2 }) => position2 === "bottom-right" ? "right: 20px;" : "left: 20px;"}
2030
+ z-index: ${({ theme: theme2 }) => theme2.zIndex.widget};
2031
+ font-family: ${({ theme: theme2 }) => theme2.typography.fontFamily};
2032
+ `;
2033
+ var WidgetPanel = styled__default.default(react$1.motion.div)`
2034
+ width: 400px;
2035
+ height: 700px;
2036
+ border-radius: ${({ theme: theme2 }) => theme2.radii.xl};
2037
+ overflow: hidden;
2038
+ box-shadow: ${({ theme: theme2 }) => theme2.shadows.lg};
2039
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.primary};
2040
+ display: flex;
2041
+ flex-direction: column;
2042
+ `;
2043
+ var WidgetHeader = styled__default.default.div`
2044
+ display: flex;
2045
+ align-items: center;
2046
+ justify-content: space-between;
2047
+ padding: ${({ theme: theme2 }) => `${theme2.spacing.sm} ${theme2.spacing.md}`};
2048
+ background-color: ${({ theme: theme2 }) => theme2.colors.background.primary};
2049
+ border-bottom: 1px solid ${({ theme: theme2 }) => theme2.colors.border};
2050
+ flex-shrink: 0;
2051
+ min-width: 0;
2052
+ gap: ${({ theme: theme2 }) => theme2.spacing.sm};
2053
+ `;
2054
+ var WidgetContent = styled__default.default.div`
2055
+ flex: 1;
2056
+ overflow: hidden;
2057
+ display: flex;
2058
+ flex-direction: column;
2059
+ `;
2060
+ styled__default.default.div`
2061
+ max-width: 80%;
2062
+ padding: ${({ theme: theme2 }) => `${theme2.spacing.md} ${theme2.spacing.md}`};
2063
+ border-radius: ${({ theme: theme2 }) => theme2.radii.md};
2064
+ background-color: ${({ theme: theme2, isUser }) => isUser ? theme2.colors.accent.primary : theme2.colors.background.secondary};
2065
+ color: ${({ theme: theme2, isUser }) => isUser ? theme2.colors.text.inverse : theme2.colors.text.primary};
2066
+ `;
2067
+ styled__default.default.span`
2068
+ font-size: ${({ theme: theme2 }) => theme2.typography.fontSize.xs};
2069
+ color: ${({ theme: theme2 }) => theme2.colors.text.secondary};
2070
+ margin-top: ${({ theme: theme2 }) => theme2.spacing.xs};
2071
+ `;
2072
+ styled__default.default.form`
2073
+ display: flex;
2074
+ gap: ${({ theme: theme2 }) => theme2.spacing.sm};
2075
+ padding: ${({ theme: theme2 }) => theme2.spacing.md};
2076
+ border-top: 1px solid ${({ theme: theme2 }) => theme2.colors.border};
2077
+ `;
2078
+ styled__default.default.div`
2079
+ display: flex;
2080
+ align-items: center;
2081
+ justify-content: center;
2082
+ height: 100%;
2083
+ color: ${({ theme: theme2 }) => theme2.colors.text.secondary};
2084
+ text-align: center;
2085
+ padding: ${({ theme: theme2 }) => theme2.spacing.xl};
2086
+ `;
2087
+ var WidgetContext = React.createContext(null);
2088
+ function generateUserId() {
2089
+ return crypto.randomUUID();
2090
+ }
2091
+ function createApiHeaders(userId, assistantId) {
2092
+ return {
2093
+ "Content-Type": "application/json",
2094
+ "X-User-Id": userId,
2095
+ "X-Assistant-Id": assistantId
2096
+ };
2097
+ }
2098
+ function createThreadListAdapter(baseUrl, userId, assistantId) {
2099
+ const headers = createApiHeaders(userId, assistantId);
2100
+ return {
2101
+ // List all threads for this user
2102
+ async list() {
2103
+ try {
2104
+ const response = await fetch(`${baseUrl}/api/widget/threads`, {
2105
+ headers
2106
+ });
2107
+ if (!response.ok) {
2108
+ console.error("[Threads] List failed:", response.status);
2109
+ return { threads: [] };
2110
+ }
2111
+ const data = await response.json();
2112
+ return { threads: data.threads || [] };
2113
+ } catch (error) {
2114
+ console.error("[Threads] List error:", error);
2115
+ return { threads: [] };
2116
+ }
2117
+ },
2118
+ // Fetch a single thread's details
2119
+ async fetch(remoteId) {
2120
+ const response = await fetch(
2121
+ `${baseUrl}/api/widget/threads/${remoteId}`,
2122
+ {
2123
+ headers
2124
+ }
2125
+ );
2126
+ if (!response.ok) {
2127
+ throw new Error(`Failed to fetch thread: ${response.status}`);
2128
+ }
2129
+ const data = await response.json();
2130
+ return {
2131
+ remoteId: data.remoteId,
2132
+ status: data.status,
2133
+ title: data.title
2134
+ };
2135
+ },
2136
+ // Initialize a new thread
2137
+ async initialize(localId) {
2138
+ try {
2139
+ const response = await fetch(`${baseUrl}/api/widget/threads`, {
2140
+ method: "POST",
2141
+ headers,
2142
+ body: JSON.stringify({ localId })
2143
+ });
2144
+ if (!response.ok) {
2145
+ throw new Error(`Failed to create thread: ${response.status}`);
2146
+ }
2147
+ const data = await response.json();
2148
+ return { remoteId: data.remoteId, externalId: data.externalId };
2149
+ } catch (error) {
2150
+ console.error("[Threads] Initialize error:", error);
2151
+ throw error;
2152
+ }
2153
+ },
2154
+ // Rename a thread
2155
+ async rename(remoteId, newTitle) {
2156
+ try {
2157
+ await fetch(`${baseUrl}/api/widget/threads/${remoteId}`, {
2158
+ method: "PATCH",
2159
+ headers,
2160
+ body: JSON.stringify({ title: newTitle })
2161
+ });
2162
+ } catch (error) {
2163
+ console.error("[Threads] Rename error:", error);
2164
+ }
2165
+ },
2166
+ // Archive a thread
2167
+ async archive(remoteId) {
2168
+ try {
2169
+ await fetch(`${baseUrl}/api/widget/threads/${remoteId}/archive`, {
2170
+ method: "POST",
2171
+ headers
2172
+ });
2173
+ } catch (error) {
2174
+ console.error("[Threads] Archive error:", error);
2175
+ }
2176
+ },
2177
+ // Unarchive a thread
2178
+ async unarchive(remoteId) {
2179
+ try {
2180
+ await fetch(`${baseUrl}/api/widget/threads/${remoteId}/unarchive`, {
2181
+ method: "POST",
2182
+ headers
2183
+ });
2184
+ } catch (error) {
2185
+ console.error("[Threads] Unarchive error:", error);
2186
+ }
2187
+ },
2188
+ // Delete a thread
2189
+ async delete(remoteId) {
2190
+ try {
2191
+ await fetch(`${baseUrl}/api/widget/threads/${remoteId}`, {
2192
+ method: "DELETE",
2193
+ headers
2194
+ });
2195
+ } catch (error) {
2196
+ console.error("[Threads] Delete error:", error);
2197
+ }
2198
+ },
2199
+ // Generate a title from messages
2200
+ async generateTitle(remoteId, messages) {
2201
+ return assistantStream.createAssistantStream(async (controller) => {
2202
+ try {
2203
+ const response = await fetch(
2204
+ `${baseUrl}/api/widget/threads/${remoteId}/title`,
2205
+ {
2206
+ method: "POST",
2207
+ headers,
2208
+ body: JSON.stringify({ messages })
2209
+ }
2210
+ );
2211
+ if (!response.ok) {
2212
+ throw new Error(`Title generation failed: ${response.status}`);
2213
+ }
2214
+ const data = await response.json();
2215
+ controller.appendText(data.title);
2216
+ controller.close();
2217
+ } catch (error) {
2218
+ console.error("[Threads] Title generation error:", error);
2219
+ controller.appendText("New Chat");
2220
+ controller.close();
2221
+ }
2222
+ });
2223
+ }
2224
+ };
2225
+ }
2226
+ async function saveMessages(baseUrl, userId, assistantId, threadId, messages) {
2227
+ try {
2228
+ const response = await fetch(
2229
+ `${baseUrl}/api/widget/threads/${threadId}/messages/sync`,
2230
+ {
2231
+ method: "POST",
2232
+ headers: createApiHeaders(userId, assistantId),
2233
+ body: JSON.stringify({ messages })
2234
+ }
2235
+ );
2236
+ if (!response.ok) {
2237
+ console.error("[Messages] Sync failed:", response.status);
2238
+ }
2239
+ } catch (error) {
2240
+ console.error("[Messages] Sync error:", error);
2241
+ }
2242
+ }
2243
+ function createHistoryAdapter(baseUrl, userId, assistantId, remoteId) {
2244
+ const headers = createApiHeaders(userId, assistantId);
2245
+ return {
2246
+ async load() {
2247
+ console.log("[History] load() called, remoteId:", remoteId);
2248
+ if (!remoteId) return { headId: null, messages: [] };
2249
+ try {
2250
+ const response = await fetch(
2251
+ `${baseUrl}/api/widget/threads/${remoteId}/messages`,
2252
+ { headers }
2253
+ );
2254
+ if (!response.ok) {
2255
+ console.error("[History] Failed to load messages:", response.status);
2256
+ return { headId: null, messages: [] };
2257
+ }
2258
+ const { messages } = await response.json();
2259
+ console.log("[History] Loaded messages:", messages.length);
2260
+ const formattedMessages = messages.map(
2261
+ (m, index) => ({
2262
+ parentId: index > 0 ? messages[index - 1].id : null,
2263
+ message: {
2264
+ id: m.id,
2265
+ role: m.role,
2266
+ parts: m.content,
2267
+ metadata: m.metadata,
2268
+ createdAt: new Date(m.createdAt)
2269
+ }
2270
+ })
2271
+ );
2272
+ console.log("[History] Formatted messages:", formattedMessages.length);
2273
+ return {
2274
+ headId: messages.length > 0 ? messages[messages.length - 1].id : null,
2275
+ messages: formattedMessages
2276
+ };
2277
+ } catch (error) {
2278
+ console.error("[History] Load error:", error);
2279
+ return { headId: null, messages: [] };
2280
+ }
2281
+ },
2282
+ async append(message) {
2283
+ console.log("[History] append() called");
2284
+ },
2285
+ // Required by useExternalHistory in @assistant-ui/react-ai-sdk
2286
+ withFormat(_formatAdapter) {
2287
+ console.log("[History.withFormat] called, remoteId:", remoteId);
2288
+ return {
2289
+ async load() {
2290
+ if (!remoteId) return { headId: null, messages: [] };
2291
+ try {
2292
+ const response = await fetch(
2293
+ `${baseUrl}/api/widget/threads/${remoteId}/messages`,
2294
+ { headers }
2295
+ );
2296
+ if (!response.ok) {
2297
+ console.error("[History.withFormat] Failed:", response.status);
2298
+ return { headId: null, messages: [] };
2299
+ }
2300
+ const { messages } = await response.json();
2301
+ console.log("[History.withFormat] Loaded:", messages.length);
2302
+ const formattedMessages = messages.map(
2303
+ (m, index) => ({
2304
+ parentId: index > 0 ? messages[index - 1].id : null,
2305
+ message: {
2306
+ id: m.id,
2307
+ role: m.role,
2308
+ parts: m.content,
2309
+ metadata: m.metadata,
2310
+ createdAt: new Date(m.createdAt)
2311
+ }
2312
+ })
2313
+ );
2314
+ return {
2315
+ headId: messages.length > 0 ? messages[messages.length - 1].id : null,
2316
+ messages: formattedMessages
2317
+ };
2318
+ } catch (error) {
2319
+ console.error("[History.withFormat] Error:", error);
2320
+ return { headId: null, messages: [] };
2321
+ }
2322
+ },
2323
+ async append(_item) {
2324
+ }
2325
+ };
2326
+ }
2327
+ };
2328
+ }
2329
+ function AssistantRuntimeWrapper({
2330
+ config,
2331
+ userId,
2332
+ children
2333
+ }) {
2334
+ const baseUrl = config.baseUrl || "http://localhost:3000";
2335
+ const assistantId = config.apiKey;
2336
+ const { consumeContext, clearContext } = useMessageContext();
2337
+ const contextRef = React.useRef(consumeContext);
2338
+ contextRef.current = consumeContext;
2339
+ const clearContextRef = React.useRef(clearContext);
2340
+ clearContextRef.current = clearContext;
2341
+ const threadListAdapter = React.useMemo(
2342
+ () => createThreadListAdapter(baseUrl, userId, assistantId),
2343
+ [baseUrl, userId, assistantId]
2344
+ );
2345
+ const runtime = react.unstable_useRemoteThreadListRuntime({
2346
+ runtimeHook: function useChatThreadRuntime() {
2347
+ const threadId = react.useAssistantState(
2348
+ ({ threadListItem }) => threadListItem?.remoteId ?? void 0
2349
+ );
2350
+ const threadIdRef = React.useRef(threadId);
2351
+ threadIdRef.current = threadId;
2352
+ const history = React.useMemo(
2353
+ () => createHistoryAdapter(baseUrl, userId, assistantId, threadId),
2354
+ [threadId]
2355
+ );
2356
+ const transport = React.useMemo(() => {
2357
+ console.log("[Widget] Creating transport for threadId:", threadId);
2358
+ return new reactAiSdk.AssistantChatTransport({
2359
+ api: `${baseUrl}/api/widget/chat`,
2360
+ headers: {
2361
+ "X-User-Id": userId,
2362
+ "X-Assistant-Id": assistantId
2363
+ },
2364
+ // Use body as a function to dynamically include context
2365
+ body: () => {
2366
+ const currentContext = contextRef.current();
2367
+ const contextIds = currentContext.map((item) => item.id);
2368
+ const contextMetadata = currentContext.map((item) => ({
2369
+ id: item.id,
2370
+ type: item.type,
2371
+ title: item.title
2372
+ }));
2373
+ console.log("[Widget] Transport body - contextIds:", contextIds.length, "threadId:", threadId);
2374
+ if (contextIds.length > 0) {
2375
+ setTimeout(() => clearContextRef.current(), 0);
2376
+ }
2377
+ return {
2378
+ assistantId,
2379
+ threadId,
2380
+ ...contextIds.length > 0 && { contextIds, contextMetadata }
2381
+ };
2382
+ }
2383
+ });
2384
+ }, [threadId]);
2385
+ const runtime2 = reactAiSdk.useChatRuntime({
2386
+ transport,
2387
+ adapters: { history },
2388
+ onFinish: ({ message, messages }) => {
2389
+ const currentThreadId = threadIdRef.current;
2390
+ console.log(
2391
+ "[Widget] onFinish - threadId:",
2392
+ currentThreadId,
2393
+ "messages:",
2394
+ messages.length
2395
+ );
2396
+ if (currentThreadId && messages.length > 0) {
2397
+ saveMessages(
2398
+ baseUrl,
2399
+ userId,
2400
+ assistantId,
2401
+ currentThreadId,
2402
+ messages
2403
+ );
2404
+ }
2405
+ }
2406
+ });
2407
+ return runtime2;
2408
+ },
2409
+ adapter: threadListAdapter
2410
+ });
2411
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.AssistantRuntimeProvider, { runtime, children: [
2412
+ /* @__PURE__ */ jsxRuntime.jsx(DetailedAnswerToolUI, {}),
2413
+ children
2414
+ ] });
2415
+ }
2416
+ function WidgetProvider({
2417
+ config,
2418
+ children,
2419
+ autoInitialize = true
2420
+ }) {
2421
+ const [userId] = React.useState(() => config.userId || generateUserId());
2422
+ const [client] = React.useState(() => new WidgetClient(config));
2423
+ const [state, setState] = React.useState(client.getState());
2424
+ React.useEffect(() => {
2425
+ const unsubscribe = client.on("state:change", ({ current }) => {
2426
+ setState(current);
2427
+ });
2428
+ if (autoInitialize && state.status === "idle") {
2429
+ client.initialize().catch(console.error);
2430
+ }
2431
+ return () => {
2432
+ unsubscribe();
2433
+ client.destroy();
2434
+ };
2435
+ }, [client, autoInitialize, state.status]);
2436
+ const contextValue = React.useMemo(
2437
+ () => ({ client, state, userId }),
2438
+ [client, state, userId]
2439
+ );
2440
+ return /* @__PURE__ */ jsxRuntime.jsx(react$2.CacheProvider, { value: widgetCache, children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ThemeProvider, { theme, children: /* @__PURE__ */ jsxRuntime.jsx(WidgetContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(MessageContextProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(AssistantRuntimeWrapper, { config, userId, children }) }) }) }) });
2441
+ }
2442
+ function useWidget() {
2443
+ const context = React.useContext(WidgetContext);
2444
+ if (!context) {
2445
+ throw new Error("useWidget must be used within a WidgetProvider");
2446
+ }
2447
+ const { client, state } = context;
2448
+ const initialize = React.useCallback(async () => {
2449
+ if (state.status === "idle") {
2450
+ await client.initialize();
2451
+ }
2452
+ }, [client, state.status]);
2453
+ const sendMessage = React.useCallback(
2454
+ async (content) => {
2455
+ return client.sendMessage(content);
2456
+ },
2457
+ [client]
2458
+ );
2459
+ return {
2460
+ state,
2461
+ client,
2462
+ isIdle: state.status === "idle",
2463
+ isInitializing: state.status === "initializing",
2464
+ isReady: state.status === "ready",
2465
+ isLoading: state.status === "loading",
2466
+ isError: state.status === "error",
2467
+ messages: state.status === "ready" ? state.session.messages : [],
2468
+ error: state.status === "error" ? state.error : null,
2469
+ initialize,
2470
+ sendMessage
2471
+ };
2472
+ }
2473
+ function useChat() {
2474
+ const { sendMessage, messages, isLoading, isReady } = useWidget();
2475
+ const [input, setInput] = React.useState("");
2476
+ const handleSubmit = React.useCallback(
2477
+ async (e) => {
2478
+ e?.preventDefault();
2479
+ if (!input.trim() || !isReady || isLoading) {
2480
+ return;
2481
+ }
2482
+ const message = input.trim();
2483
+ setInput("");
2484
+ try {
2485
+ await sendMessage(message);
2486
+ } catch (error) {
2487
+ console.error("Failed to send message:", error);
2488
+ setInput(message);
2489
+ }
2490
+ },
2491
+ [input, isReady, isLoading, sendMessage]
2492
+ );
2493
+ return {
2494
+ input,
2495
+ setInput,
2496
+ handleSubmit,
2497
+ messages,
2498
+ isLoading,
2499
+ canSubmit: isReady && !isLoading && input.trim().length > 0
2500
+ };
2501
+ }
2502
+ function Dialog({
2503
+ ...props
2504
+ }) {
2505
+ return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Root, { "data-slot": "dialog", ...props });
2506
+ }
2507
+ function DialogTrigger({
2508
+ ...props
2509
+ }) {
2510
+ return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Trigger, { "data-slot": "dialog-trigger", ...props });
2511
+ }
2512
+ function DialogPortal({
2513
+ ...props
2514
+ }) {
2515
+ return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Portal, { "data-slot": "dialog-portal", ...props });
2516
+ }
2517
+ function DialogOverlay({
2518
+ className,
2519
+ ...props
2520
+ }) {
2521
+ return /* @__PURE__ */ jsxRuntime.jsx(
2522
+ DialogPrimitive__namespace.Overlay,
2523
+ {
2524
+ "data-slot": "dialog-overlay",
2525
+ className: cn(
2526
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
2527
+ className
2528
+ ),
2529
+ ...props
2530
+ }
2531
+ );
2532
+ }
2533
+ function DialogContent({
2534
+ className,
2535
+ children,
2536
+ showCloseButton = true,
2537
+ ...props
2538
+ }) {
2539
+ return /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [
2540
+ /* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
2541
+ /* @__PURE__ */ jsxRuntime.jsxs(
2542
+ DialogPrimitive__namespace.Content,
2543
+ {
2544
+ "data-slot": "dialog-content",
2545
+ className: cn(
2546
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg",
2547
+ className
2548
+ ),
2549
+ ...props,
2550
+ children: [
2551
+ children,
2552
+ showCloseButton && /* @__PURE__ */ jsxRuntime.jsxs(
2553
+ DialogPrimitive__namespace.Close,
2554
+ {
2555
+ "data-slot": "dialog-close",
2556
+ className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
2557
+ children: [
2558
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {}),
2559
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
2560
+ ]
2561
+ }
2562
+ )
2563
+ ]
2564
+ }
2565
+ )
2566
+ ] });
2567
+ }
2568
+ function DialogTitle({
2569
+ className,
2570
+ ...props
2571
+ }) {
2572
+ return /* @__PURE__ */ jsxRuntime.jsx(
2573
+ DialogPrimitive__namespace.Title,
2574
+ {
2575
+ "data-slot": "dialog-title",
2576
+ className: cn("text-lg leading-none font-semibold", className),
2577
+ ...props
2578
+ }
2579
+ );
2580
+ }
2581
+ function Avatar2({
2582
+ className,
2583
+ ...props
2584
+ }) {
2585
+ return /* @__PURE__ */ jsxRuntime.jsx(
2586
+ AvatarPrimitive__namespace.Root,
2587
+ {
2588
+ "data-slot": "avatar",
2589
+ className: cn(
2590
+ "relative flex size-8 shrink-0 overflow-hidden rounded-full",
2591
+ className
2592
+ ),
2593
+ ...props
2594
+ }
2595
+ );
2596
+ }
2597
+ function AvatarImage({
2598
+ className,
2599
+ ...props
2600
+ }) {
2601
+ return /* @__PURE__ */ jsxRuntime.jsx(
2602
+ AvatarPrimitive__namespace.Image,
2603
+ {
2604
+ "data-slot": "avatar-image",
2605
+ className: cn("aspect-square size-full", className),
2606
+ ...props
2607
+ }
2608
+ );
2609
+ }
2610
+ function AvatarFallback({
2611
+ className,
2612
+ ...props
2613
+ }) {
2614
+ return /* @__PURE__ */ jsxRuntime.jsx(
2615
+ AvatarPrimitive__namespace.Fallback,
2616
+ {
2617
+ "data-slot": "avatar-fallback",
2618
+ className: cn(
2619
+ "bg-muted flex size-full items-center justify-center rounded-full",
2620
+ className
2621
+ ),
2622
+ ...props
2623
+ }
2624
+ );
2625
+ }
2626
+ var useFileSrc = (file) => {
2627
+ const [src, setSrc] = React.useState(void 0);
2628
+ React.useEffect(() => {
2629
+ if (!file) {
2630
+ setSrc(void 0);
2631
+ return;
2632
+ }
2633
+ const objectUrl = URL.createObjectURL(file);
2634
+ setSrc(objectUrl);
2635
+ return () => {
2636
+ URL.revokeObjectURL(objectUrl);
2637
+ };
2638
+ }, [file]);
2639
+ return src;
2640
+ };
2641
+ var useAttachmentSrc = () => {
2642
+ const { file, src } = react.useAssistantState(
2643
+ shallow.useShallow(({ attachment }) => {
2644
+ if (attachment.type !== "image") return {};
2645
+ if (attachment.file) return { file: attachment.file };
2646
+ const src2 = attachment.content?.filter((c) => c.type === "image")[0]?.image;
2647
+ if (!src2) return {};
2648
+ return { src: src2 };
2649
+ })
2650
+ );
2651
+ return useFileSrc(file) ?? src;
2652
+ };
2653
+ var AttachmentPreview = ({ src }) => {
2654
+ return /* @__PURE__ */ jsxRuntime.jsx(
2655
+ "img",
2656
+ {
2657
+ src,
2658
+ alt: "Image Preview",
2659
+ className: "aui-attachment-preview-image-loaded block h-auto max-h-[80vh] w-auto max-w-full object-contain"
2660
+ }
2661
+ );
2662
+ };
2663
+ var AttachmentPreviewDialog = ({ children }) => {
2664
+ const src = useAttachmentSrc();
2665
+ if (!src) return children;
2666
+ return /* @__PURE__ */ jsxRuntime.jsxs(Dialog, { children: [
2667
+ /* @__PURE__ */ jsxRuntime.jsx(
2668
+ DialogTrigger,
2669
+ {
2670
+ className: "aui-attachment-preview-trigger cursor-pointer transition-colors hover:bg-accent/50",
2671
+ asChild: true,
2672
+ children
2673
+ }
2674
+ ),
2675
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "aui-attachment-preview-dialog-content p-2 sm:max-w-3xl [&>button]:rounded-full [&>button]:bg-foreground/60 [&>button]:p-1 [&>button]:opacity-100 [&>button]:ring-0! [&_svg]:text-background [&>button]:hover:[&_svg]:text-destructive", children: [
2676
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "aui-sr-only sr-only", children: "Image Attachment Preview" }),
2677
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aui-attachment-preview relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden bg-background", children: /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreview, { src }) })
2678
+ ] })
2679
+ ] });
2680
+ };
2681
+ var AttachmentThumb = () => {
2682
+ const isImage = react.useAssistantState(
2683
+ ({ attachment }) => attachment.type === "image"
2684
+ );
2685
+ const src = useAttachmentSrc();
2686
+ return /* @__PURE__ */ jsxRuntime.jsxs(Avatar2, { className: "aui-attachment-tile-avatar h-full w-full rounded-none", children: [
2687
+ /* @__PURE__ */ jsxRuntime.jsx(
2688
+ AvatarImage,
2689
+ {
2690
+ src,
2691
+ alt: "Attachment preview",
2692
+ className: "aui-attachment-tile-image object-cover"
2693
+ }
2694
+ ),
2695
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { delayMs: isImage ? 200 : 0, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "aui-attachment-tile-fallback-icon size-8 text-muted-foreground" }) })
2696
+ ] });
2697
+ };
2698
+ var AttachmentUI = () => {
2699
+ const api = react.useAssistantApi();
2700
+ const isComposer = api.attachment.source === "composer";
2701
+ const isImage = react.useAssistantState(
2702
+ ({ attachment }) => attachment.type === "image"
2703
+ );
2704
+ const typeLabel = react.useAssistantState(({ attachment }) => {
2705
+ const type = attachment.type;
2706
+ switch (type) {
2707
+ case "image":
2708
+ return "Image";
2709
+ case "document":
2710
+ return "Document";
2711
+ case "file":
2712
+ return "File";
2713
+ default:
2714
+ return "File";
2715
+ }
2716
+ });
2717
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
2718
+ /* @__PURE__ */ jsxRuntime.jsxs(
2719
+ react.AttachmentPrimitive.Root,
2720
+ {
2721
+ className: cn(
2722
+ "aui-attachment-root relative",
2723
+ isImage && "aui-attachment-root-composer only:[&>#attachment-tile]:size-24"
2724
+ ),
2725
+ children: [
2726
+ /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreviewDialog, { children: /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
2727
+ "div",
2728
+ {
2729
+ className: cn(
2730
+ "aui-attachment-tile size-14 cursor-pointer overflow-hidden rounded-[14px] border bg-muted transition-opacity hover:opacity-75",
2731
+ isComposer && "aui-attachment-tile-composer border-foreground/20"
2732
+ ),
2733
+ role: "button",
2734
+ id: "attachment-tile",
2735
+ "aria-label": `${typeLabel} attachment`,
2736
+ children: /* @__PURE__ */ jsxRuntime.jsx(AttachmentThumb, {})
2737
+ }
2738
+ ) }) }),
2739
+ isComposer && /* @__PURE__ */ jsxRuntime.jsx(AttachmentRemove, {})
2740
+ ]
2741
+ }
2742
+ ),
2743
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: /* @__PURE__ */ jsxRuntime.jsx(react.AttachmentPrimitive.Name, {}) })
2744
+ ] });
2745
+ };
2746
+ var AttachmentRemove = () => {
2747
+ return /* @__PURE__ */ jsxRuntime.jsx(react.AttachmentPrimitive.Remove, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
2748
+ TooltipIconButton,
2749
+ {
2750
+ tooltip: "Remove file",
2751
+ className: "aui-attachment-tile-remove absolute top-1.5 right-1.5 size-3.5 rounded-full bg-white text-muted-foreground opacity-100 shadow-sm hover:bg-white! [&_svg]:text-black hover:[&_svg]:text-destructive",
2752
+ side: "top",
2753
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, { className: "aui-attachment-remove-icon size-3 dark:stroke-[2.5px]" })
2754
+ }
2755
+ ) });
2756
+ };
2757
+ var UserMessageAttachments = () => {
2758
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aui-user-message-attachments-end col-span-full col-start-1 row-start-1 flex w-full flex-row justify-end gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(react.MessagePrimitive.Attachments, { components: { Attachment: AttachmentUI } }) });
2759
+ };
2760
+ var ComposerAttachments = () => {
2761
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aui-composer-attachments mb-2 flex w-full flex-row items-center gap-2 overflow-x-auto px-1.5 pt-0.5 pb-1 empty:hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
2762
+ react.ComposerPrimitive.Attachments,
2763
+ {
2764
+ components: { Attachment: AttachmentUI }
2765
+ }
2766
+ ) });
2767
+ };
2768
+ var ComposerAddAttachment = () => {
2769
+ return /* @__PURE__ */ jsxRuntime.jsx(react.ComposerPrimitive.AddAttachment, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
2770
+ TooltipIconButton,
2771
+ {
2772
+ tooltip: "Add Attachment",
2773
+ side: "bottom",
2774
+ variant: "ghost",
2775
+ size: "icon",
2776
+ className: "aui-composer-add-attachment size-[34px] rounded-full p-1 font-semibold text-xs hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30",
2777
+ "aria-label": "Add Attachment",
2778
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PaperclipIcon, { className: "aui-attachment-add-icon size-5 stroke-[1.5px]" })
2779
+ }
2780
+ ) });
2781
+ };
2782
+ var MarkdownTextImpl = () => {
2783
+ return /* @__PURE__ */ jsxRuntime.jsx(
2784
+ reactMarkdown.MarkdownTextPrimitive,
2785
+ {
2786
+ remarkPlugins: [remarkGfm__default.default],
2787
+ className: "aui-md",
2788
+ components: defaultComponents
2789
+ }
2790
+ );
2791
+ };
2792
+ var MarkdownText = React.memo(MarkdownTextImpl);
2793
+ var CodeHeader = ({ language, code }) => {
2794
+ const { isCopied, copyToClipboard } = useCopyToClipboard2();
2795
+ const onCopy = () => {
2796
+ if (!code || isCopied) return;
2797
+ copyToClipboard(code);
2798
+ };
2799
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-code-header-root mt-4 flex items-center justify-between gap-4 rounded-t-lg bg-muted-foreground/15 px-4 py-2 font-semibold text-foreground text-sm dark:bg-muted-foreground/20", children: [
2800
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "aui-code-header-language lowercase [&>span]:text-xs", children: language }),
2801
+ /* @__PURE__ */ jsxRuntime.jsxs(TooltipIconButton, { tooltip: "Copy", onClick: onCopy, children: [
2802
+ !isCopied && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CopyIcon, {}),
2803
+ isCopied && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, {})
2804
+ ] })
2805
+ ] });
2806
+ };
2807
+ var useCopyToClipboard2 = ({
2808
+ copiedDuration = 3e3
2809
+ } = {}) => {
2810
+ const [isCopied, setIsCopied] = React.useState(false);
2811
+ const copyToClipboard = (value) => {
2812
+ if (!value) return;
2813
+ navigator.clipboard.writeText(value).then(() => {
2814
+ setIsCopied(true);
2815
+ setTimeout(() => setIsCopied(false), copiedDuration);
2816
+ });
2817
+ };
2818
+ return { isCopied, copyToClipboard };
2819
+ };
2820
+ var defaultComponents = reactMarkdown.unstable_memoizeMarkdownComponents({
2821
+ h1: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2822
+ "h1",
2823
+ {
2824
+ className: cn(
2825
+ "aui-md-h1 mb-8 scroll-m-20 font-extrabold text-4xl tracking-tight last:mb-0",
2826
+ className
2827
+ ),
2828
+ ...props
2829
+ }
2830
+ ),
2831
+ h2: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2832
+ "h2",
2833
+ {
2834
+ className: cn(
2835
+ "aui-md-h2 mt-8 mb-4 scroll-m-20 font-semibold text-3xl tracking-tight first:mt-0 last:mb-0",
2836
+ className
2837
+ ),
2838
+ ...props
2839
+ }
2840
+ ),
2841
+ h3: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2842
+ "h3",
2843
+ {
2844
+ className: cn(
2845
+ "aui-md-h3 mt-6 mb-4 scroll-m-20 font-semibold text-2xl tracking-tight first:mt-0 last:mb-0",
2846
+ className
2847
+ ),
2848
+ ...props
2849
+ }
2850
+ ),
2851
+ h4: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2852
+ "h4",
2853
+ {
2854
+ className: cn(
2855
+ "aui-md-h4 mt-6 mb-4 scroll-m-20 font-semibold text-xl tracking-tight first:mt-0 last:mb-0",
2856
+ className
2857
+ ),
2858
+ ...props
2859
+ }
2860
+ ),
2861
+ h5: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2862
+ "h5",
2863
+ {
2864
+ className: cn(
2865
+ "aui-md-h5 my-4 font-semibold text-lg first:mt-0 last:mb-0",
2866
+ className
2867
+ ),
2868
+ ...props
2869
+ }
2870
+ ),
2871
+ h6: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2872
+ "h6",
2873
+ {
2874
+ className: cn(
2875
+ "aui-md-h6 my-4 font-semibold first:mt-0 last:mb-0",
2876
+ className
2877
+ ),
2878
+ ...props
2879
+ }
2880
+ ),
2881
+ p: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2882
+ "p",
2883
+ {
2884
+ className: cn(
2885
+ "aui-md-p mt-5 mb-5 leading-7 first:mt-0 last:mb-0",
2886
+ className
2887
+ ),
2888
+ ...props
2889
+ }
2890
+ ),
2891
+ a: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2892
+ "a",
2893
+ {
2894
+ className: cn(
2895
+ "aui-md-a font-medium text-primary underline underline-offset-4",
2896
+ className
2897
+ ),
2898
+ ...props
2899
+ }
2900
+ ),
2901
+ blockquote: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2902
+ "blockquote",
2903
+ {
2904
+ className: cn("aui-md-blockquote border-l-2 pl-6 italic", className),
2905
+ ...props
2906
+ }
2907
+ ),
2908
+ ul: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2909
+ "ul",
2910
+ {
2911
+ className: cn("aui-md-ul my-5 ml-6 list-disc [&>li]:mt-2", className),
2912
+ ...props
2913
+ }
2914
+ ),
2915
+ ol: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2916
+ "ol",
2917
+ {
2918
+ className: cn("aui-md-ol my-5 ml-6 list-decimal [&>li]:mt-2", className),
2919
+ ...props
2920
+ }
2921
+ ),
2922
+ hr: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("hr", { className: cn("aui-md-hr my-5 border-b", className), ...props }),
2923
+ table: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2924
+ "table",
2925
+ {
2926
+ className: cn(
2927
+ "aui-md-table my-5 w-full border-separate border-spacing-0 overflow-y-auto",
2928
+ className
2929
+ ),
2930
+ ...props
2931
+ }
2932
+ ),
2933
+ th: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2934
+ "th",
2935
+ {
2936
+ className: cn(
2937
+ "aui-md-th bg-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [[align=center]]:text-center [[align=right]]:text-right",
2938
+ className
2939
+ ),
2940
+ ...props
2941
+ }
2942
+ ),
2943
+ td: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2944
+ "td",
2945
+ {
2946
+ className: cn(
2947
+ "aui-md-td border-b border-l px-4 py-2 text-left last:border-r [[align=center]]:text-center [[align=right]]:text-right",
2948
+ className
2949
+ ),
2950
+ ...props
2951
+ }
2952
+ ),
2953
+ tr: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2954
+ "tr",
2955
+ {
2956
+ className: cn(
2957
+ "aui-md-tr m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg",
2958
+ className
2959
+ ),
2960
+ ...props
2961
+ }
2962
+ ),
2963
+ sup: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2964
+ "sup",
2965
+ {
2966
+ className: cn("aui-md-sup [&>a]:text-xs [&>a]:no-underline", className),
2967
+ ...props
2968
+ }
2969
+ ),
2970
+ pre: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2971
+ "pre",
2972
+ {
2973
+ className: cn(
2974
+ "aui-md-pre overflow-x-auto rounded-t-none! rounded-b-lg bg-black p-4 text-white",
2975
+ className
2976
+ ),
2977
+ ...props
2978
+ }
2979
+ ),
2980
+ code: function Code({ className, ...props }) {
2981
+ const isCodeBlock = reactMarkdown.useIsMarkdownCodeBlock();
2982
+ return /* @__PURE__ */ jsxRuntime.jsx(
2983
+ "code",
2984
+ {
2985
+ className: cn(
2986
+ !isCodeBlock && "aui-md-inline-code rounded border bg-muted font-semibold",
2987
+ className
2988
+ ),
2989
+ ...props
2990
+ }
2991
+ );
2992
+ },
2993
+ CodeHeader
2994
+ });
2995
+ var ToolFallback = ({
2996
+ toolName,
2997
+ argsText,
2998
+ result,
2999
+ status
3000
+ }) => {
3001
+ const isStreaming = status?.type === "running";
3002
+ const isError = status?.type === "incomplete";
3003
+ const isCancelled = status?.type === "incomplete" && status.reason === "cancelled";
3004
+ const cancelledReason = isCancelled && status.error ? typeof status.error === "string" ? status.error : JSON.stringify(status.error) : null;
3005
+ const titlePrefix = isCancelled ? "Cancelled: " : isStreaming ? "Running: " : "";
3006
+ return /* @__PURE__ */ jsxRuntime.jsx(
3007
+ ToolCard,
3008
+ {
3009
+ title: `${titlePrefix}${toolName}`,
3010
+ isStreaming,
3011
+ isError,
3012
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 text-white", children: [
3013
+ cancelledReason && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3014
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold text-white/70 mb-0.5", children: "Cancelled reason:" }),
3015
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-white/60", children: cancelledReason })
3016
+ ] }),
3017
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(isCancelled && "opacity-60"), children: [
3018
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold text-white/70 mb-0.5", children: "Arguments:" }),
3019
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "whitespace-pre-wrap bg-black/20 p-1.5 rounded text-white/80", children: argsText })
3020
+ ] }),
3021
+ !isCancelled && result !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-white/10 pt-2", children: [
3022
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold text-white/70 mb-0.5", children: "Result:" }),
3023
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "whitespace-pre-wrap bg-black/20 p-1.5 rounded text-white/80", children: typeof result === "string" ? result : JSON.stringify(result, null, 2) })
3024
+ ] })
3025
+ ] })
3026
+ }
3027
+ );
3028
+ };
3029
+ var ContextPill = ({
3030
+ label,
3031
+ onRemove,
3032
+ readonly = false,
3033
+ className
3034
+ }) => {
3035
+ const showRemoveButton = !readonly && onRemove;
3036
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
3037
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
3038
+ "div",
3039
+ {
3040
+ className: cn(
3041
+ "group flex items-center gap-1 rounded-md border border-muted-foreground py-1 px-1.5 text-xs",
3042
+ "max-w-[200px] cursor-default",
3043
+ className
3044
+ ),
3045
+ children: [
3046
+ showRemoveButton && /* @__PURE__ */ jsxRuntime.jsx(
3047
+ "button",
3048
+ {
3049
+ onClick: onRemove,
3050
+ "aria-label": `Remove ${label}`,
3051
+ className: "shrink-0 hover:text-destructive transition-colors",
3052
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, { className: "size-3" })
3053
+ }
3054
+ ),
3055
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: label })
3056
+ ]
3057
+ }
3058
+ ) }),
3059
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", sideOffset: 4, children: label })
3060
+ ] });
3061
+ };
3062
+ function Popover({
3063
+ modal = false,
3064
+ ...props
3065
+ }) {
3066
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Root, { modal, ...props });
3067
+ }
3068
+ function PopoverTrigger({
3069
+ ...props
3070
+ }) {
3071
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Trigger, { ...props });
3072
+ }
3073
+ function PopoverContent({
3074
+ className,
3075
+ align = "start",
3076
+ sideOffset = 4,
3077
+ ...props
3078
+ }) {
3079
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
3080
+ PopoverPrimitive__namespace.Content,
3081
+ {
3082
+ align,
3083
+ sideOffset,
3084
+ className: cn(
3085
+ "z-[10000] w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
3086
+ className
3087
+ ),
3088
+ style: {
3089
+ zIndex: 1e4,
3090
+ borderColor: theme.colors.border,
3091
+ ...props.style
3092
+ },
3093
+ ...props
3094
+ }
3095
+ ) });
3096
+ }
3097
+ var TYPE_ICONS = {
3098
+ attachment: lucideReact.FileIcon,
3099
+ description: lucideReact.FileTextIcon,
3100
+ caption: lucideReact.VideoIcon,
3101
+ link: lucideReact.LinkIcon
3102
+ };
3103
+ var ContextMentionPopover = ({
3104
+ isOpen,
3105
+ onOpenChange,
3106
+ categories,
3107
+ isLoading,
3108
+ activeIndex,
3109
+ flattenedItems,
3110
+ onSelectItem,
3111
+ onActiveIndexChange,
3112
+ getCategoryLabel,
3113
+ trigger,
3114
+ searchTerm
3115
+ }) => {
3116
+ const activeItemRef = React.useRef(null);
3117
+ React.useEffect(() => {
3118
+ if (isOpen && activeItemRef.current) {
3119
+ activeItemRef.current.scrollIntoView({
3120
+ block: "nearest",
3121
+ behavior: "smooth"
3122
+ });
3123
+ }
3124
+ }, [activeIndex, isOpen]);
3125
+ const getFlattenedIndex = (categoryIndex, itemIndex) => {
3126
+ let index = 0;
3127
+ for (let i = 0; i < categoryIndex; i++) {
3128
+ index += categories[i].items.length;
3129
+ }
3130
+ return index + itemIndex;
3131
+ };
3132
+ const hasNoResults = !isLoading && flattenedItems.length === 0;
3133
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: isOpen, onOpenChange, modal: false, children: [
3134
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: trigger }),
3135
+ /* @__PURE__ */ jsxRuntime.jsx(
3136
+ PopoverContent,
3137
+ {
3138
+ className: "w-72 max-h-80 overflow-y-auto p-0",
3139
+ align: "start",
3140
+ side: "top",
3141
+ sideOffset: 8,
3142
+ onOpenAutoFocus: (e) => e.preventDefault(),
3143
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
3144
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-0 z-10 border-b border-border bg-popover px-3 py-2", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium text-muted-foreground", children: searchTerm ? `Searching for "${searchTerm}"` : "Select context to focus on" }) }),
3145
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LoaderIcon, { className: "size-5 animate-spin text-muted-foreground" }) }),
3146
+ hasNoResults && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-8 text-center text-sm text-muted-foreground", children: [
3147
+ "No context items found",
3148
+ searchTerm && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-xs mt-1", children: "Try a different search term" })
3149
+ ] }),
3150
+ !isLoading && categories.map((category, categoryIndex) => {
3151
+ if (category.items.length === 0) return null;
3152
+ const Icon = TYPE_ICONS[category.type] || lucideReact.FileIcon;
3153
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-1", children: [
3154
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-1.5", children: [
3155
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "size-3.5 text-muted-foreground" }),
3156
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-muted-foreground", children: getCategoryLabel(category.type) }),
3157
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground/60", children: [
3158
+ "(",
3159
+ category.items.length,
3160
+ ")"
3161
+ ] })
3162
+ ] }),
3163
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col", children: category.items.map((item, itemIndex) => {
3164
+ const flatIndex = getFlattenedIndex(
3165
+ categoryIndex,
3166
+ itemIndex
3167
+ );
3168
+ const isActive = flatIndex === activeIndex;
3169
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3170
+ "button",
3171
+ {
3172
+ ref: isActive ? activeItemRef : null,
3173
+ type: "button",
3174
+ className: cn(
3175
+ "flex flex-col items-start px-3 py-2 text-left text-sm transition-colors",
3176
+ "hover:bg-accent/10",
3177
+ isActive && "bg-accent/20"
3178
+ ),
3179
+ onClick: () => onSelectItem(item),
3180
+ onMouseEnter: () => onActiveIndexChange(flatIndex),
3181
+ children: [
3182
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate w-full font-medium text-foreground", children: item.title }),
3183
+ (item.lessonTitle || item.chapterTitle) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate w-full text-xs text-muted-foreground", children: item.chapterTitle && item.lessonTitle ? `${item.chapterTitle} > ${item.lessonTitle}` : item.lessonTitle || item.chapterTitle })
3184
+ ]
3185
+ },
3186
+ item.id
3187
+ );
3188
+ }) })
3189
+ ] }, category.type);
3190
+ })
3191
+ ] })
3192
+ }
3193
+ )
3194
+ ] });
3195
+ };
3196
+ var TYPE_ICON_SVGS = {
3197
+ attachment: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></svg>',
3198
+ description: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg>',
3199
+ caption: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5"/><rect x="2" y="6" width="14" height="12" rx="2"/></svg>',
3200
+ link: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>'
3201
+ };
3202
+ function getTypeIconSvg(type) {
3203
+ return TYPE_ICON_SVGS[type] || TYPE_ICON_SVGS.attachment;
3204
+ }
3205
+ var ZERO_WIDTH_SPACE = "\u200B";
3206
+ var MentionComposerInput = React.forwardRef(
3207
+ ({
3208
+ placeholder = "Ask, search, or make anything...",
3209
+ className,
3210
+ autoFocus = false,
3211
+ onInput,
3212
+ onKeyDown,
3213
+ onMentionRemove,
3214
+ onTriggerDetected,
3215
+ onTriggerDismissed,
3216
+ onSubmit
3217
+ }, ref) => {
3218
+ const editorRef = React.useRef(null);
3219
+ const composerRuntime = react.useComposerRuntime();
3220
+ const [isEmpty, setIsEmpty] = React.useState(true);
3221
+ const [inlineMentions, setInlineMentions] = React.useState([]);
3222
+ const triggerPositionRef = React.useRef(null);
3223
+ const getPlainText = React.useCallback(() => {
3224
+ const editor = editorRef.current;
3225
+ if (!editor) return "";
3226
+ let text = "";
3227
+ const walkNodes = (node2) => {
3228
+ if (node2.nodeType === Node.TEXT_NODE) {
3229
+ const nodeText = node2.textContent || "";
3230
+ text += nodeText.replace(/\u200B/g, "");
3231
+ } else if (node2.nodeType === Node.ELEMENT_NODE) {
3232
+ const element = node2;
3233
+ if (element.dataset.mentionId) {
3234
+ const title = element.dataset.mentionTitle || "";
3235
+ text += `[${title}]`;
3236
+ } else if (element.tagName === "BR") {
3237
+ text += "\n";
3238
+ } else {
3239
+ node2.childNodes.forEach(walkNodes);
3240
+ }
3241
+ }
3242
+ };
3243
+ editor.childNodes.forEach(walkNodes);
3244
+ return text.trim();
3245
+ }, []);
3246
+ const getCursorPosition = React.useCallback(() => {
3247
+ const selection = window.getSelection();
3248
+ if (!selection || !selection.rangeCount) return 0;
3249
+ const range = selection.getRangeAt(0);
3250
+ const preCaretRange = range.cloneRange();
3251
+ preCaretRange.selectNodeContents(editorRef.current);
3252
+ preCaretRange.setEnd(range.endContainer, range.endOffset);
3253
+ let position2 = 0;
3254
+ const walkNodes = (node2) => {
3255
+ if (node2 === range.endContainer) {
3256
+ if (node2.nodeType === Node.TEXT_NODE) {
3257
+ position2 += range.endOffset;
3258
+ }
3259
+ return true;
3260
+ }
3261
+ if (node2.nodeType === Node.TEXT_NODE) {
3262
+ const text = (node2.textContent || "").replace(/\u200B/g, "");
3263
+ position2 += text.length;
3264
+ } else if (node2.nodeType === Node.ELEMENT_NODE) {
3265
+ const element = node2;
3266
+ if (element.dataset.mentionId) {
3267
+ const title = element.dataset.mentionTitle || "";
3268
+ position2 += title.length + 2;
3269
+ } else if (element.tagName === "BR") {
3270
+ position2 += 1;
3271
+ } else {
3272
+ for (const child of Array.from(node2.childNodes)) {
3273
+ if (walkNodes(child)) return true;
3274
+ }
3275
+ }
3276
+ }
3277
+ return false;
3278
+ };
3279
+ if (editorRef.current) {
3280
+ for (const child of Array.from(editorRef.current.childNodes)) {
3281
+ if (walkNodes(child)) break;
3282
+ }
3283
+ }
3284
+ return position2;
3285
+ }, []);
3286
+ const syncToRuntime = React.useCallback(() => {
3287
+ const text = getPlainText();
3288
+ composerRuntime.setText(text);
3289
+ setIsEmpty(text.length === 0);
3290
+ }, [composerRuntime, getPlainText]);
3291
+ const handleInput = React.useCallback(() => {
3292
+ syncToRuntime();
3293
+ const text = getPlainText();
3294
+ const cursorPos = getCursorPosition();
3295
+ onInput?.({ text, cursorPosition: cursorPos });
3296
+ const editor = editorRef.current;
3297
+ if (!editor) return;
3298
+ const selection = window.getSelection();
3299
+ if (!selection || !selection.rangeCount) return;
3300
+ const range = selection.getRangeAt(0);
3301
+ let textBeforeCursor = "";
3302
+ let charCount = 0;
3303
+ const walkForText = (node2) => {
3304
+ if (node2 === range.endContainer) {
3305
+ if (node2.nodeType === Node.TEXT_NODE) {
3306
+ textBeforeCursor += (node2.textContent || "").slice(0, range.endOffset);
3307
+ }
3308
+ return true;
3309
+ }
3310
+ if (node2.nodeType === Node.TEXT_NODE) {
3311
+ textBeforeCursor += node2.textContent || "";
3312
+ charCount += (node2.textContent || "").length;
3313
+ } else if (node2.nodeType === Node.ELEMENT_NODE) {
3314
+ const element = node2;
3315
+ if (element.dataset.mentionId) {
3316
+ textBeforeCursor += " ";
3317
+ charCount += 1;
3318
+ } else {
3319
+ for (const child of Array.from(node2.childNodes)) {
3320
+ if (walkForText(child)) return true;
3321
+ }
3322
+ }
3323
+ }
3324
+ return false;
3325
+ };
3326
+ for (const child of Array.from(editor.childNodes)) {
3327
+ if (walkForText(child)) break;
3328
+ }
3329
+ const lastAtIndex = textBeforeCursor.lastIndexOf("@");
3330
+ if (lastAtIndex !== -1) {
3331
+ const charBeforeAt = lastAtIndex > 0 ? textBeforeCursor[lastAtIndex - 1] : " ";
3332
+ if (charBeforeAt === " " || charBeforeAt === "\n" || charBeforeAt === ZERO_WIDTH_SPACE || lastAtIndex === 0) {
3333
+ const searchText = textBeforeCursor.slice(lastAtIndex + 1);
3334
+ if (!searchText.includes(" ")) {
3335
+ triggerPositionRef.current = lastAtIndex;
3336
+ onTriggerDetected?.(searchText, lastAtIndex);
3337
+ return;
3338
+ }
3339
+ }
3340
+ }
3341
+ if (triggerPositionRef.current !== null) {
3342
+ triggerPositionRef.current = null;
3343
+ onTriggerDismissed?.();
3344
+ }
3345
+ }, [syncToRuntime, getPlainText, getCursorPosition, onInput, onTriggerDetected, onTriggerDismissed]);
3346
+ const handleKeyDown = React.useCallback(
3347
+ (e) => {
3348
+ if (e.key === "Enter" && !e.shiftKey) {
3349
+ if (onKeyDown) {
3350
+ onKeyDown(e);
3351
+ if (e.defaultPrevented) {
3352
+ return;
3353
+ }
3354
+ }
3355
+ e.preventDefault();
3356
+ const text = getPlainText();
3357
+ if (text.trim()) {
3358
+ onSubmit?.();
3359
+ }
3360
+ return;
3361
+ }
3362
+ if (e.key === "Backspace") {
3363
+ const selection = window.getSelection();
3364
+ if (!selection || !selection.rangeCount) return;
3365
+ const range = selection.getRangeAt(0);
3366
+ if (range.collapsed) {
3367
+ const container = range.startContainer;
3368
+ const offset = range.startOffset;
3369
+ if (container.nodeType === Node.TEXT_NODE && offset === 0) {
3370
+ let prevSibling = container.previousSibling;
3371
+ if (!prevSibling && container.parentElement !== editorRef.current) {
3372
+ prevSibling = container.parentElement?.previousSibling || null;
3373
+ }
3374
+ if (prevSibling && prevSibling.dataset?.mentionId) {
3375
+ e.preventDefault();
3376
+ const mentionId = prevSibling.dataset.mentionId;
3377
+ prevSibling.parentNode?.removeChild(prevSibling);
3378
+ setInlineMentions((prev2) => prev2.filter((m) => m.id !== mentionId));
3379
+ onMentionRemove?.(mentionId);
3380
+ syncToRuntime();
3381
+ return;
3382
+ }
3383
+ }
3384
+ if (container.nodeType === Node.ELEMENT_NODE) {
3385
+ const element = container;
3386
+ const childAtOffset = element.childNodes[offset - 1];
3387
+ if (childAtOffset && childAtOffset.dataset?.mentionId) {
3388
+ e.preventDefault();
3389
+ const mentionId = childAtOffset.dataset.mentionId;
3390
+ childAtOffset.parentNode?.removeChild(childAtOffset);
3391
+ setInlineMentions((prev2) => prev2.filter((m) => m.id !== mentionId));
3392
+ onMentionRemove?.(mentionId);
3393
+ syncToRuntime();
3394
+ return;
3395
+ }
3396
+ }
3397
+ }
3398
+ }
3399
+ onKeyDown?.(e);
3400
+ },
3401
+ [onKeyDown, onMentionRemove, syncToRuntime, onSubmit, getPlainText]
3402
+ );
3403
+ const insertMention = React.useCallback(
3404
+ (mention) => {
3405
+ const editor = editorRef.current;
3406
+ if (!editor) return;
3407
+ const selection = window.getSelection();
3408
+ if (!selection || !selection.rangeCount) return;
3409
+ const range = selection.getRangeAt(0);
3410
+ if (triggerPositionRef.current !== null) {
3411
+ let currentPos = 0;
3412
+ let foundNode = null;
3413
+ let foundOffset = 0;
3414
+ const findAtPosition = (node2) => {
3415
+ if (node2.nodeType === Node.TEXT_NODE) {
3416
+ const text = node2.textContent || "";
3417
+ const targetPosInNode = triggerPositionRef.current - currentPos;
3418
+ if (targetPosInNode >= 0 && targetPosInNode < text.length) {
3419
+ foundNode = node2;
3420
+ foundOffset = targetPosInNode;
3421
+ return true;
3422
+ }
3423
+ currentPos += text.length;
3424
+ } else if (node2.nodeType === Node.ELEMENT_NODE) {
3425
+ const element = node2;
3426
+ if (element.dataset.mentionId) {
3427
+ currentPos += 1;
3428
+ } else {
3429
+ for (const child of Array.from(node2.childNodes)) {
3430
+ if (findAtPosition(child)) return true;
3431
+ }
3432
+ }
3433
+ }
3434
+ return false;
3435
+ };
3436
+ for (const child of Array.from(editor.childNodes)) {
3437
+ if (findAtPosition(child)) break;
3438
+ }
3439
+ if (foundNode) {
3440
+ const deleteRange = document.createRange();
3441
+ deleteRange.setStart(foundNode, foundOffset);
3442
+ deleteRange.setEnd(range.endContainer, range.endOffset);
3443
+ deleteRange.deleteContents();
3444
+ }
3445
+ }
3446
+ const mentionEl = document.createElement("span");
3447
+ mentionEl.className = "inline-flex items-center gap-1 rounded-md border border-muted-foreground py-0.5 px-1.5 text-xs mx-0.5 cursor-default select-none bg-muted/50 max-w-[350px]";
3448
+ mentionEl.contentEditable = "false";
3449
+ mentionEl.dataset.mentionId = mention.id;
3450
+ mentionEl.dataset.mentionTitle = mention.title;
3451
+ if (mention.icon) {
3452
+ const iconImg = document.createElement("img");
3453
+ iconImg.src = mention.icon;
3454
+ iconImg.className = "size-3.5 rounded-sm shrink-0";
3455
+ iconImg.alt = "";
3456
+ mentionEl.appendChild(iconImg);
3457
+ } else if (mention.type) {
3458
+ const iconSpan = document.createElement("span");
3459
+ iconSpan.className = "size-3.5 shrink-0 flex items-center justify-center";
3460
+ iconSpan.innerHTML = getTypeIconSvg(mention.type);
3461
+ mentionEl.appendChild(iconSpan);
3462
+ }
3463
+ const titleSpan = document.createElement("span");
3464
+ titleSpan.className = "truncate";
3465
+ titleSpan.textContent = mention.title;
3466
+ mentionEl.appendChild(titleSpan);
3467
+ const insertRange = selection.getRangeAt(0);
3468
+ insertRange.insertNode(mentionEl);
3469
+ const spaceNode = document.createTextNode(" ");
3470
+ mentionEl.after(spaceNode);
3471
+ const newRange = document.createRange();
3472
+ newRange.setStartAfter(spaceNode);
3473
+ newRange.collapse(true);
3474
+ selection.removeAllRanges();
3475
+ selection.addRange(newRange);
3476
+ setInlineMentions((prev2) => [...prev2, mention]);
3477
+ triggerPositionRef.current = null;
3478
+ syncToRuntime();
3479
+ setTimeout(() => {
3480
+ editorRef.current?.focus();
3481
+ }, 10);
3482
+ },
3483
+ [syncToRuntime]
3484
+ );
3485
+ React.useImperativeHandle(
3486
+ ref,
3487
+ () => ({
3488
+ focus: () => editorRef.current?.focus(),
3489
+ getValue: getPlainText,
3490
+ insertMention,
3491
+ getInlineMentions: () => inlineMentions
3492
+ }),
3493
+ [getPlainText, insertMention, inlineMentions]
3494
+ );
3495
+ React.useEffect(() => {
3496
+ if (autoFocus) {
3497
+ editorRef.current?.focus();
3498
+ }
3499
+ }, [autoFocus]);
3500
+ React.useEffect(() => {
3501
+ const unsubscribe = composerRuntime.subscribe(() => {
3502
+ const composerState = composerRuntime.getState();
3503
+ if (composerState.text === "" && editorRef.current) {
3504
+ editorRef.current.innerHTML = "";
3505
+ setInlineMentions([]);
3506
+ setIsEmpty(true);
3507
+ }
3508
+ });
3509
+ return unsubscribe;
3510
+ }, [composerRuntime]);
3511
+ const handlePaste = React.useCallback((e) => {
3512
+ e.preventDefault();
3513
+ const text = e.clipboardData.getData("text/plain");
3514
+ document.execCommand("insertText", false, text);
3515
+ }, []);
3516
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: /* @__PURE__ */ jsxRuntime.jsx(
3517
+ "div",
3518
+ {
3519
+ ref: editorRef,
3520
+ contentEditable: true,
3521
+ role: "textbox",
3522
+ "aria-label": "Message input",
3523
+ "data-placeholder": placeholder,
3524
+ className: cn(
3525
+ "aui-composer-input mb-1 max-h-32 min-h-14 w-full resize-none bg-transparent px-4 pt-2 pb-3 text-sm outline-none",
3526
+ "overflow-y-auto whitespace-pre-wrap wrap-break-word",
3527
+ "focus:outline-none focus-visible:ring-0",
3528
+ // Placeholder styling using data attribute
3529
+ "empty:before:content-[attr(data-placeholder)] empty:before:text-muted-foreground empty:before:pointer-events-none",
3530
+ className
3531
+ ),
3532
+ onInput: handleInput,
3533
+ onKeyDown: handleKeyDown,
3534
+ onPaste: handlePaste,
3535
+ suppressContentEditableWarning: true
3536
+ }
3537
+ ) });
3538
+ }
3539
+ );
3540
+ MentionComposerInput.displayName = "MentionComposerInput";
3541
+ var TYPE_ICONS2 = {
3542
+ attachment: lucideReact.FileIcon,
3543
+ description: lucideReact.FileTextIcon,
3544
+ caption: lucideReact.VideoIcon,
3545
+ link: lucideReact.LinkIcon
3546
+ };
3547
+ var InlineContextPill = ({
3548
+ title,
3549
+ type = "attachment",
3550
+ className
3551
+ }) => {
3552
+ const Icon = TYPE_ICONS2[type] || lucideReact.FileIcon;
3553
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
3554
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
3555
+ "span",
3556
+ {
3557
+ className: cn(
3558
+ "inline-flex items-center gap-1 rounded-md border border-muted-foreground/50 py-0.5 px-1.5 text-xs mx-0.5",
3559
+ "max-w-[350px] cursor-default bg-muted/30 align-middle",
3560
+ className
3561
+ ),
3562
+ children: [
3563
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "size-3 shrink-0" }),
3564
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: title })
3565
+ ]
3566
+ }
3567
+ ) }),
3568
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", sideOffset: 4, children: title })
3569
+ ] });
3570
+ };
3571
+ function parseMessageContent(text) {
3572
+ const parts = [];
3573
+ const regex = /\[([^\]]+)\]/g;
3574
+ let lastIndex = 0;
3575
+ let match2;
3576
+ while ((match2 = regex.exec(text)) !== null) {
3577
+ if (match2.index > lastIndex) {
3578
+ parts.push({
3579
+ type: "text",
3580
+ content: text.slice(lastIndex, match2.index)
3581
+ });
3582
+ }
3583
+ parts.push({
3584
+ type: "context",
3585
+ content: match2[1]
3586
+ // The title inside brackets
3587
+ });
3588
+ lastIndex = match2.index + match2[0].length;
3589
+ }
3590
+ if (lastIndex < text.length) {
3591
+ parts.push({
3592
+ type: "text",
3593
+ content: text.slice(lastIndex)
3594
+ });
3595
+ }
3596
+ return parts;
3597
+ }
3598
+ var UserMessageContent = () => {
3599
+ const message = react.useMessage();
3600
+ const renderedContent = React.useMemo(() => {
3601
+ const textParts = message.content?.filter(
3602
+ (part) => part.type === "text"
3603
+ );
3604
+ if (!textParts || textParts.length === 0) {
3605
+ return null;
3606
+ }
3607
+ const fullText = textParts.map((part) => part.text).join("");
3608
+ const parsed = parseMessageContent(fullText);
3609
+ return parsed.map((part, index) => {
3610
+ if (part.type === "context") {
3611
+ return /* @__PURE__ */ jsxRuntime.jsx(
3612
+ InlineContextPill,
3613
+ {
3614
+ title: part.content
3615
+ },
3616
+ `context-${index}`
3617
+ );
3618
+ }
3619
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { children: part.content }, `text-${index}`);
3620
+ });
3621
+ }, [message.content]);
3622
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderedContent });
3623
+ };
3624
+ var CATEGORY_LABELS = {
3625
+ attachment: "Attachments",
3626
+ description: "Description",
3627
+ caption: "Video",
3628
+ link: "Links"
3629
+ };
3630
+ function useContextMention(options = {}) {
3631
+ const { onInsertMention } = options;
3632
+ const widgetContext = React.useContext(WidgetContext);
3633
+ if (!widgetContext) {
3634
+ throw new Error("useContextMention must be used within a WidgetProvider");
3635
+ }
3636
+ const { client } = widgetContext;
3637
+ const { selectedContext: selectedItems, addContextItem, removeContextItem, clearContext } = useMessageContext();
3638
+ const [isOpen, setIsOpen] = React.useState(false);
3639
+ const [searchTerm, setSearchTerm] = React.useState("");
3640
+ const [activeIndex, setActiveIndex] = React.useState(0);
3641
+ const [isLoading, setIsLoading] = React.useState(false);
3642
+ const [categories, setCategories] = React.useState([]);
3643
+ const [hasMore, setHasMore] = React.useState(false);
3644
+ const config = client.getConfig();
3645
+ const baseUrl = config.baseUrl || "http://localhost:3000";
3646
+ const assistantId = config.apiKey;
3647
+ const fetchContextItems = React.useCallback(
3648
+ async (search = "", limit = 10) => {
3649
+ setIsLoading(true);
3650
+ try {
3651
+ const params = new URLSearchParams({
3652
+ limit: limit.toString()
3653
+ });
3654
+ if (search) {
3655
+ params.set("search", search);
3656
+ }
3657
+ const response = await fetch(
3658
+ `${baseUrl}/api/widget/context?${params.toString()}`,
3659
+ {
3660
+ headers: {
3661
+ "Content-Type": "application/json",
3662
+ "X-Assistant-Id": assistantId
3663
+ }
3664
+ }
3665
+ );
3666
+ if (!response.ok) {
3667
+ console.error("[ContextMention] Failed to fetch context:", response.status);
3668
+ return;
3669
+ }
3670
+ const data = await response.json();
3671
+ setCategories(data.categories);
3672
+ setHasMore(data.hasMore);
3673
+ } catch (error) {
3674
+ console.error("[ContextMention] Error fetching context:", error);
3675
+ } finally {
3676
+ setIsLoading(false);
3677
+ }
3678
+ },
3679
+ [baseUrl, assistantId]
3680
+ );
3681
+ const openPopover = React.useCallback(() => {
3682
+ setIsOpen(true);
3683
+ setSearchTerm("");
3684
+ setActiveIndex(0);
3685
+ fetchContextItems();
3686
+ }, [fetchContextItems]);
3687
+ const closePopover = React.useCallback(() => {
3688
+ setIsOpen(false);
3689
+ setSearchTerm("");
3690
+ setActiveIndex(0);
3691
+ }, []);
3692
+ const updateSearch = React.useCallback(
3693
+ (term) => {
3694
+ setSearchTerm(term);
3695
+ setActiveIndex(0);
3696
+ fetchContextItems(term);
3697
+ },
3698
+ [fetchContextItems]
3699
+ );
3700
+ const flattenedItems = React.useMemo(() => {
3701
+ return categories.flatMap((category) => category.items);
3702
+ }, [categories]);
3703
+ const navigateDown = React.useCallback(() => {
3704
+ setActiveIndex(
3705
+ (prev2) => prev2 < flattenedItems.length - 1 ? prev2 + 1 : prev2
3706
+ );
3707
+ }, [flattenedItems.length]);
3708
+ const navigateUp = React.useCallback(() => {
3709
+ setActiveIndex((prev2) => prev2 > 0 ? prev2 - 1 : 0);
3710
+ }, []);
3711
+ const selectActiveItem = React.useCallback(() => {
3712
+ const item = flattenedItems[activeIndex];
3713
+ if (item) {
3714
+ addContextItem(item);
3715
+ closePopover();
3716
+ onInsertMention?.(item);
3717
+ }
3718
+ }, [flattenedItems, activeIndex, addContextItem, closePopover, onInsertMention]);
3719
+ const selectItem = React.useCallback(
3720
+ (item) => {
3721
+ addContextItem(item);
3722
+ closePopover();
3723
+ onInsertMention?.(item);
3724
+ },
3725
+ [addContextItem, closePopover, onInsertMention]
3726
+ );
3727
+ const removeItem = React.useCallback((itemId) => {
3728
+ removeContextItem(itemId);
3729
+ }, [removeContextItem]);
3730
+ const clearAll = React.useCallback(() => {
3731
+ clearContext();
3732
+ }, [clearContext]);
3733
+ const handleKeyDown = React.useCallback(
3734
+ (event) => {
3735
+ if (!isOpen) return;
3736
+ switch (event.key) {
3737
+ case "ArrowDown":
3738
+ event.preventDefault();
3739
+ navigateDown();
3740
+ break;
3741
+ case "ArrowUp":
3742
+ event.preventDefault();
3743
+ navigateUp();
3744
+ break;
3745
+ case "Enter":
3746
+ event.preventDefault();
3747
+ selectActiveItem();
3748
+ break;
3749
+ case "Escape":
3750
+ event.preventDefault();
3751
+ closePopover();
3752
+ break;
3753
+ }
3754
+ },
3755
+ [isOpen, navigateDown, navigateUp, selectActiveItem, closePopover]
3756
+ );
3757
+ const getCategoryLabel = React.useCallback((type) => {
3758
+ return CATEGORY_LABELS[type] || type;
3759
+ }, []);
3760
+ return {
3761
+ // Selected items
3762
+ selectedItems,
3763
+ selectItem,
3764
+ removeItem,
3765
+ clearAll,
3766
+ // Popover state
3767
+ isOpen,
3768
+ openPopover,
3769
+ closePopover,
3770
+ // Search
3771
+ searchTerm,
3772
+ updateSearch,
3773
+ // Navigation
3774
+ activeIndex,
3775
+ setActiveIndex,
3776
+ navigateUp,
3777
+ navigateDown,
3778
+ selectActiveItem,
3779
+ handleKeyDown,
3780
+ // Data
3781
+ categories,
3782
+ flattenedItems,
3783
+ isLoading,
3784
+ hasMore,
3785
+ // Utilities
3786
+ getCategoryLabel
3787
+ };
3788
+ }
3789
+ var Thread = () => {
3790
+ return /* @__PURE__ */ jsxRuntime.jsx(
3791
+ react.ThreadPrimitive.Root,
3792
+ {
3793
+ className: "aui-thread-root @container flex h-full flex-col bg-background",
3794
+ style: {
3795
+ ["--thread-max-width"]: "44rem"
3796
+ },
3797
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
3798
+ react.ThreadPrimitive.Viewport,
3799
+ {
3800
+ className: "aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth px-4 pt-4",
3801
+ children: [
3802
+ /* @__PURE__ */ jsxRuntime.jsx(react.AssistantIf, { condition: ({ thread }) => thread.isEmpty, children: /* @__PURE__ */ jsxRuntime.jsx(ThreadWelcome, {}) }),
3803
+ /* @__PURE__ */ jsxRuntime.jsx(
3804
+ react.ThreadPrimitive.Messages,
3805
+ {
3806
+ components: {
3807
+ UserMessage,
3808
+ EditComposer,
3809
+ AssistantMessage
3810
+ }
3811
+ }
3812
+ ),
3813
+ /* @__PURE__ */ jsxRuntime.jsxs(react.ThreadPrimitive.ViewportFooter, { className: "aui-thread-viewport-footer sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible rounded-t-3xl bg-background pb-4", children: [
3814
+ /* @__PURE__ */ jsxRuntime.jsx(ThreadScrollToBottom, {}),
3815
+ /* @__PURE__ */ jsxRuntime.jsx(Composer, {})
3816
+ ] })
3817
+ ]
3818
+ }
3819
+ )
3820
+ }
3821
+ );
3822
+ };
3823
+ var ThreadScrollToBottom = () => {
3824
+ return /* @__PURE__ */ jsxRuntime.jsx(react.ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3825
+ TooltipIconButton,
3826
+ {
3827
+ tooltip: "Scroll to bottom",
3828
+ variant: "outline",
3829
+ className: "aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center rounded-full p-4 disabled:invisible dark:bg-background dark:hover:bg-accent",
3830
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownIcon, {})
3831
+ }
3832
+ ) });
3833
+ };
3834
+ var getGreeting = () => {
3835
+ const hour = (/* @__PURE__ */ new Date()).getHours();
3836
+ if (hour < 12) return "Good morning";
3837
+ if (hour < 18) return "Good afternoon";
3838
+ return "Good evening";
3839
+ };
3840
+ var STATIC_SUGGESTIONS = [
3841
+ {
3842
+ label: "Explain this concept in detail",
3843
+ icon: lucideReact.MessageSquareTextIcon,
3844
+ prompt: "Explain this concept to me by drawing comparisons"
3845
+ },
3846
+ {
3847
+ label: "Generate a podcast",
3848
+ icon: lucideReact.PodcastIcon,
3849
+ prompt: "/audio"
3850
+ },
3851
+ {
3852
+ label: "Quiz me",
3853
+ icon: lucideReact.BadgeQuestionMarkIcon,
3854
+ prompt: "/quiz"
3855
+ },
3856
+ {
3857
+ label: "Generate flashcards",
3858
+ icon: lucideReact.WalletCardsIcon,
3859
+ prompt: "/flashcards"
3860
+ }
3861
+ ];
3862
+ var ThreadWelcome = () => {
3863
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-thread-welcome-root mx-auto flex w-full max-w-(--thread-max-width) flex-col gap-4", children: [
3864
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-thread-welcome-message flex size-full flex-col justify-center px-4", children: [
3865
+ /* @__PURE__ */ jsxRuntime.jsx(
3866
+ "h1",
3867
+ {
3868
+ className: "aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in font-semibold text-2xl duration-200",
3869
+ style: {
3870
+ color: "var(--color-primary)"
3871
+ },
3872
+ children: getGreeting()
3873
+ }
3874
+ ),
3875
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in text-muted-foreground text-xl delay-75 duration-200", children: "How may I be of service?" })
3876
+ ] }) }),
3877
+ /* @__PURE__ */ jsxRuntime.jsx(ThreadSuggestions, {})
3878
+ ] });
3879
+ };
3880
+ var ThreadSuggestions = () => {
3881
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aui-thread-welcome-suggestions flex w-full flex-col gap-2", children: STATIC_SUGGESTIONS.map((suggestion, index) => {
3882
+ const Icon = suggestion.icon;
3883
+ return /* @__PURE__ */ jsxRuntime.jsx(
3884
+ "div",
3885
+ {
3886
+ className: "fade-in slide-in-from-bottom-2 animate-in fill-mode-both duration-200",
3887
+ style: { animationDelay: `${200 + index * 50}ms` },
3888
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.ThreadPrimitive.Suggestion, { prompt: suggestion.prompt, send: true, asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3889
+ Button,
3890
+ {
3891
+ variant: "ghost",
3892
+ className: "aui-thread-welcome-suggestion h-auto w-full @md:flex-col flex-wrap items-start justify-start gap-1 rounded-2xl border text-left text-sm transition-colors hover:bg-muted hover:text-primary",
3893
+ "aria-label": suggestion.label,
3894
+ style: {
3895
+ borderWidth: 0,
3896
+ padding: 8
3897
+ },
3898
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3899
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "size-4 shrink-0" }),
3900
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: suggestion.label })
3901
+ ] })
3902
+ }
3903
+ ) })
3904
+ },
3905
+ suggestion.prompt
3906
+ );
3907
+ }) });
3908
+ };
3909
+ var Composer = () => {
3910
+ const inputRef = React.useRef(null);
3911
+ const composerRuntime = react.useComposerRuntime();
3912
+ const handleSubmit = React.useCallback(() => {
3913
+ composerRuntime.send();
3914
+ }, [composerRuntime]);
3915
+ const handleInsertMention = React.useCallback((item) => {
3916
+ inputRef.current?.insertMention({
3917
+ id: item.id,
3918
+ title: item.title,
3919
+ icon: item.icon,
3920
+ type: item.type
3921
+ });
3922
+ setTimeout(() => {
3923
+ inputRef.current?.focus();
3924
+ }, 0);
3925
+ }, []);
3926
+ const {
3927
+ isOpen,
3928
+ openPopover,
3929
+ closePopover,
3930
+ categories,
3931
+ isLoading,
3932
+ activeIndex,
3933
+ flattenedItems,
3934
+ selectItem,
3935
+ setActiveIndex,
3936
+ handleKeyDown,
3937
+ getCategoryLabel,
3938
+ searchTerm,
3939
+ updateSearch
3940
+ } = useContextMention({ onInsertMention: handleInsertMention });
3941
+ const { selectedContext, removeContextItem } = useMessageContext();
3942
+ const handleTriggerDetected = React.useCallback(
3943
+ (searchText) => {
3944
+ if (!isOpen) {
3945
+ openPopover();
3946
+ }
3947
+ updateSearch(searchText);
3948
+ },
3949
+ [isOpen, openPopover, updateSearch]
3950
+ );
3951
+ const handleTriggerDismissed = React.useCallback(() => {
3952
+ if (isOpen) {
3953
+ closePopover();
3954
+ }
3955
+ }, [isOpen, closePopover]);
3956
+ const handleComposerKeyDown = React.useCallback(
3957
+ (e) => {
3958
+ if (isOpen) {
3959
+ if (["ArrowUp", "ArrowDown", "Enter", "Escape"].includes(e.key)) {
3960
+ e.preventDefault();
3961
+ handleKeyDown(e);
3962
+ if (e.key === "Escape") {
3963
+ setTimeout(() => {
3964
+ inputRef.current?.focus();
3965
+ }, 0);
3966
+ }
3967
+ }
3968
+ }
3969
+ },
3970
+ [isOpen, handleKeyDown]
3971
+ );
3972
+ const handleMentionRemove = React.useCallback(
3973
+ (mentionId) => {
3974
+ removeContextItem(mentionId);
3975
+ },
3976
+ [removeContextItem]
3977
+ );
3978
+ return /* @__PURE__ */ jsxRuntime.jsx(react.ComposerPrimitive.Root, { className: "aui-composer-root relative flex w-full flex-col", children: /* @__PURE__ */ jsxRuntime.jsxs(react.ComposerPrimitive.AttachmentDropzone, { className: "aui-composer-attachment-dropzone flex w-full flex-col rounded-2xl border border-input bg-background px-1 pt-2 outline-none transition-shadow has-[[contenteditable]:focus-visible]:border-ring has-[[contenteditable]:focus-visible]:ring-2 has-[[contenteditable]:focus-visible]:ring-ring/20 data-[dragging=true]:border-ring data-[dragging=true]:border-dashed data-[dragging=true]:bg-accent/50", children: [
3979
+ /* @__PURE__ */ jsxRuntime.jsx(
3980
+ ComposerContextUI,
3981
+ {
3982
+ isOpen,
3983
+ onOpenChange: (open) => open ? openPopover() : closePopover(),
3984
+ categories,
3985
+ isLoading,
3986
+ activeIndex,
3987
+ flattenedItems,
3988
+ onSelectItem: selectItem,
3989
+ onActiveIndexChange: setActiveIndex,
3990
+ getCategoryLabel,
3991
+ searchTerm,
3992
+ selectedItems: selectedContext,
3993
+ onRemoveItem: removeContextItem
3994
+ }
3995
+ ),
3996
+ /* @__PURE__ */ jsxRuntime.jsx(ComposerAttachments, {}),
3997
+ /* @__PURE__ */ jsxRuntime.jsx(
3998
+ MentionComposerInput,
3999
+ {
4000
+ ref: inputRef,
4001
+ placeholder: "Ask, search, or make anything...",
4002
+ autoFocus: true,
4003
+ onTriggerDetected: handleTriggerDetected,
4004
+ onTriggerDismissed: handleTriggerDismissed,
4005
+ onKeyDown: handleComposerKeyDown,
4006
+ onMentionRemove: handleMentionRemove,
4007
+ onSubmit: handleSubmit
4008
+ }
4009
+ ),
4010
+ /* @__PURE__ */ jsxRuntime.jsx(ComposerAction, {})
4011
+ ] }) });
4012
+ };
4013
+ var ComposerContextUI = ({
4014
+ isOpen,
4015
+ onOpenChange,
4016
+ categories,
4017
+ isLoading,
4018
+ activeIndex,
4019
+ flattenedItems,
4020
+ onSelectItem,
4021
+ onActiveIndexChange,
4022
+ getCategoryLabel,
4023
+ searchTerm,
4024
+ selectedItems,
4025
+ onRemoveItem
4026
+ }) => {
4027
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-composer-context mb-2 flex items-center gap-2 overflow-x-auto px-1.5 pt-0.5 pb-1", children: [
4028
+ /* @__PURE__ */ jsxRuntime.jsx(
4029
+ ContextMentionPopover,
4030
+ {
4031
+ isOpen,
4032
+ onOpenChange,
4033
+ categories,
4034
+ isLoading,
4035
+ activeIndex,
4036
+ flattenedItems,
4037
+ onSelectItem,
4038
+ onActiveIndexChange,
4039
+ getCategoryLabel,
4040
+ searchTerm,
4041
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(
4042
+ TooltipIconButton,
4043
+ {
4044
+ tooltip: "Add context (@)",
4045
+ side: "bottom",
4046
+ variant: "ghost",
4047
+ size: "icon",
4048
+ className: "aui-composer-add-context size-[34px] rounded-full p-1 font-semibold text-xs hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30",
4049
+ "aria-label": "Add context (@)",
4050
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AtSignIcon, { className: "size-5 stroke-[1.5px]" })
4051
+ }
4052
+ )
4053
+ }
4054
+ ),
4055
+ selectedItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5 overflow-x-auto", children: selectedItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
4056
+ ContextPill,
4057
+ {
4058
+ label: item.title,
4059
+ onRemove: () => onRemoveItem(item.id)
4060
+ },
4061
+ item.id
4062
+ )) })
4063
+ ] });
4064
+ };
4065
+ var ComposerAction = () => {
4066
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between", children: [
4067
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4068
+ /* @__PURE__ */ jsxRuntime.jsx(ComposerAddAttachment, {}),
4069
+ /* @__PURE__ */ jsxRuntime.jsx(
4070
+ TooltipIconButton,
4071
+ {
4072
+ tooltip: "All sources",
4073
+ side: "bottom",
4074
+ variant: "ghost",
4075
+ size: "icon",
4076
+ className: "aui-composer-all-sources size-[34px] rounded-full p-1 font-semibold text-xs hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30",
4077
+ "aria-label": "All sources",
4078
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GlobeIcon, { className: "size-5 stroke-[1.5px]" })
4079
+ }
4080
+ )
4081
+ ] }),
4082
+ /* @__PURE__ */ jsxRuntime.jsx(react.AssistantIf, { condition: ({ thread }) => !thread.isRunning, children: /* @__PURE__ */ jsxRuntime.jsx(react.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4083
+ TooltipIconButton,
4084
+ {
4085
+ tooltip: "Send message",
4086
+ side: "bottom",
4087
+ type: "submit",
4088
+ variant: "default",
4089
+ className: "aui-composer-send size-8 rounded-full",
4090
+ "aria-label": "Send message",
4091
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpIcon, { className: "aui-composer-send-icon size-4" })
4092
+ }
4093
+ ) }) }),
4094
+ /* @__PURE__ */ jsxRuntime.jsx(react.AssistantIf, { condition: ({ thread }) => thread.isRunning, children: /* @__PURE__ */ jsxRuntime.jsx(react.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4095
+ Button,
4096
+ {
4097
+ type: "button",
4098
+ variant: "default",
4099
+ size: "icon",
4100
+ className: "aui-composer-cancel size-8 rounded-full",
4101
+ "aria-label": "Stop generating",
4102
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SquareIcon, { className: "aui-composer-cancel-icon size-3 fill-current" })
4103
+ }
4104
+ ) }) })
4105
+ ] });
4106
+ };
4107
+ var MessageError = () => {
4108
+ return /* @__PURE__ */ jsxRuntime.jsx(react.MessagePrimitive.Error, { children: /* @__PURE__ */ jsxRuntime.jsx(react.ErrorPrimitive.Root, { className: "aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm dark:bg-destructive/5 dark:text-red-200", children: /* @__PURE__ */ jsxRuntime.jsx(react.ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
4109
+ };
4110
+ var AssistantMessage = () => {
4111
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4112
+ react.MessagePrimitive.Root,
4113
+ {
4114
+ className: "aui-assistant-message-root fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in py-3 duration-150",
4115
+ "data-role": "assistant",
4116
+ children: [
4117
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed", children: [
4118
+ /* @__PURE__ */ jsxRuntime.jsx(
4119
+ react.MessagePrimitive.Parts,
4120
+ {
4121
+ components: {
4122
+ Text: MarkdownText,
4123
+ tools: { Fallback: ToolFallback }
4124
+ }
4125
+ }
4126
+ ),
4127
+ /* @__PURE__ */ jsxRuntime.jsx(MessageError, {})
4128
+ ] }),
4129
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-assistant-message-footer mt-1 ml-2 flex", children: [
4130
+ /* @__PURE__ */ jsxRuntime.jsx(BranchPicker, {}),
4131
+ /* @__PURE__ */ jsxRuntime.jsx(AssistantActionBar, {})
4132
+ ] })
4133
+ ]
4134
+ }
4135
+ );
4136
+ };
4137
+ var AssistantActionBar = () => {
4138
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4139
+ react.ActionBarPrimitive.Root,
4140
+ {
4141
+ hideWhenRunning: true,
4142
+ autohide: "not-last",
4143
+ autohideFloat: "single-branch",
4144
+ className: "aui-assistant-action-bar-root col-start-3 row-start-2 -ml-1 flex gap-1 text-muted-foreground data-floating:absolute data-floating:rounded-md data-floating:border data-floating:bg-background data-floating:p-1 data-floating:shadow-sm",
4145
+ children: [
4146
+ /* @__PURE__ */ jsxRuntime.jsx(react.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipIconButton, { tooltip: "Copy", children: [
4147
+ /* @__PURE__ */ jsxRuntime.jsx(react.AssistantIf, { condition: ({ message }) => message.isCopied, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, {}) }),
4148
+ /* @__PURE__ */ jsxRuntime.jsx(react.AssistantIf, { condition: ({ message }) => !message.isCopied, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CopyIcon, {}) })
4149
+ ] }) }),
4150
+ /* @__PURE__ */ jsxRuntime.jsx(react.ActionBarPrimitive.ExportMarkdown, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Export as Markdown", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.DownloadIcon, {}) }) }),
4151
+ /* @__PURE__ */ jsxRuntime.jsx(react.ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Refresh", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCwIcon, {}) }) })
4152
+ ]
4153
+ }
4154
+ );
4155
+ };
4156
+ var MessageContextIndicator = () => {
4157
+ const [isExpanded, setIsExpanded] = React.useState(false);
4158
+ const contextItems = react.useMessage((state) => {
4159
+ console.log("[MessageContextIndicator] Message state:", state);
4160
+ const metadata = state.metadata;
4161
+ const context = metadata?.context || metadata?.custom?.context;
4162
+ console.log("[MessageContextIndicator] Context:", context);
4163
+ return context;
4164
+ });
4165
+ if (!contextItems || contextItems.length === 0) {
4166
+ return null;
4167
+ }
4168
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-start-2 mb-1 flex flex-col items-end", children: [
4169
+ /* @__PURE__ */ jsxRuntime.jsxs(
4170
+ "button",
4171
+ {
4172
+ onClick: () => setIsExpanded(!isExpanded),
4173
+ className: "flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
4174
+ children: [
4175
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
4176
+ contextItems.length,
4177
+ " Context"
4178
+ ] }),
4179
+ /* @__PURE__ */ jsxRuntime.jsx(
4180
+ lucideReact.ChevronDownIcon,
4181
+ {
4182
+ className: cn(
4183
+ "size-3.5 transition-transform duration-200",
4184
+ isExpanded && "rotate-180"
4185
+ )
4186
+ }
4187
+ )
4188
+ ]
4189
+ }
4190
+ ),
4191
+ isExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 flex flex-wrap gap-1 justify-end", children: contextItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
4192
+ "span",
4193
+ {
4194
+ className: "rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground",
4195
+ children: item.title
4196
+ },
4197
+ item.id
4198
+ )) })
4199
+ ] });
4200
+ };
4201
+ var UserMessage = () => {
4202
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4203
+ react.MessagePrimitive.Root,
4204
+ {
4205
+ className: "aui-user-message-root fade-in slide-in-from-bottom-1 mx-auto grid w-full max-w-(--thread-max-width) animate-in auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] content-start gap-y-2 px-2 py-3 duration-150 [&:where(>*)]:col-start-2",
4206
+ "data-role": "user",
4207
+ children: [
4208
+ /* @__PURE__ */ jsxRuntime.jsx(MessageContextIndicator, {}),
4209
+ /* @__PURE__ */ jsxRuntime.jsx(UserMessageAttachments, {}),
4210
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-user-message-content-wrapper relative col-start-2 min-w-0", children: [
4211
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aui-user-message-content wrap-break-word rounded-2xl bg-muted px-4 py-2.5 text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(UserMessageContent, {}) }),
4212
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2", children: /* @__PURE__ */ jsxRuntime.jsx(UserActionBar, {}) })
4213
+ ] }),
4214
+ /* @__PURE__ */ jsxRuntime.jsx(BranchPicker, { className: "aui-user-branch-picker col-span-full col-start-1 row-start-3 -mr-1 justify-end" })
4215
+ ]
4216
+ }
4217
+ );
4218
+ };
4219
+ var UserActionBar = () => {
4220
+ return /* @__PURE__ */ jsxRuntime.jsx(
4221
+ react.ActionBarPrimitive.Root,
4222
+ {
4223
+ hideWhenRunning: true,
4224
+ autohide: "not-last",
4225
+ className: "aui-user-action-bar-root flex flex-col items-end",
4226
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Edit", className: "aui-user-action-edit p-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PencilIcon, {}) }) })
4227
+ }
4228
+ );
4229
+ };
4230
+ var EditComposer = () => {
4231
+ return /* @__PURE__ */ jsxRuntime.jsx(react.MessagePrimitive.Root, { className: "aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs(react.ComposerPrimitive.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted", children: [
4232
+ /* @__PURE__ */ jsxRuntime.jsx(
4233
+ react.ComposerPrimitive.Input,
4234
+ {
4235
+ className: "aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none",
4236
+ autoFocus: true
4237
+ }
4238
+ ),
4239
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
4240
+ /* @__PURE__ */ jsxRuntime.jsx(react.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", children: "Cancel" }) }),
4241
+ /* @__PURE__ */ jsxRuntime.jsx(react.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", children: "Update" }) })
4242
+ ] })
4243
+ ] }) });
4244
+ };
4245
+ var BranchPicker = ({
4246
+ className,
4247
+ ...rest
4248
+ }) => {
4249
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4250
+ react.BranchPickerPrimitive.Root,
4251
+ {
4252
+ hideWhenSingleBranch: true,
4253
+ className: cn(
4254
+ "aui-branch-picker-root mr-2 -ml-2 inline-flex items-center text-muted-foreground text-xs",
4255
+ className
4256
+ ),
4257
+ ...rest,
4258
+ children: [
4259
+ /* @__PURE__ */ jsxRuntime.jsx(react.BranchPickerPrimitive.Previous, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Previous", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeftIcon, {}) }) }),
4260
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "aui-branch-picker-state font-medium", children: [
4261
+ /* @__PURE__ */ jsxRuntime.jsx(react.BranchPickerPrimitive.Number, {}),
4262
+ " / ",
4263
+ /* @__PURE__ */ jsxRuntime.jsx(react.BranchPickerPrimitive.Count, {})
4264
+ ] }),
4265
+ /* @__PURE__ */ jsxRuntime.jsx(react.BranchPickerPrimitive.Next, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Next", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, {}) }) })
4266
+ ]
4267
+ }
4268
+ );
4269
+ };
4270
+ var ThreadList = () => {
4271
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.ThreadListPrimitive.Root, { className: "aui-thread-list-root flex flex-col", children: [
4272
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between border-b border-border px-3 py-2", children: [
4273
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground", children: "Chats" }),
4274
+ /* @__PURE__ */ jsxRuntime.jsx(react.ThreadListPrimitive.New, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4275
+ TooltipIconButton,
4276
+ {
4277
+ tooltip: "New chat",
4278
+ variant: "ghost",
4279
+ size: "icon",
4280
+ className: "h-7 w-7",
4281
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PlusIcon, { className: "h-4 w-4" })
4282
+ }
4283
+ ) })
4284
+ ] }),
4285
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto", children: [
4286
+ /* @__PURE__ */ jsxRuntime.jsx(
4287
+ react.ThreadListPrimitive.Items,
4288
+ {
4289
+ components: {
4290
+ ThreadListItem
4291
+ }
4292
+ }
4293
+ ),
4294
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Archived" }) }),
4295
+ /* @__PURE__ */ jsxRuntime.jsx(
4296
+ react.ThreadListPrimitive.Items,
4297
+ {
4298
+ archived: true,
4299
+ components: {
4300
+ ThreadListItem: ArchivedThreadListItem
4301
+ }
4302
+ }
4303
+ )
4304
+ ] })
4305
+ ] });
4306
+ };
4307
+ var ThreadListItem = () => {
4308
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.ThreadListItemPrimitive.Root, { className: "aui-thread-list-item group relative flex items-center gap-2 px-3 py-2 hover:bg-muted/50 data-[active]:bg-muted cursor-pointer transition-colors", children: [
4309
+ /* @__PURE__ */ jsxRuntime.jsxs(react.ThreadListItemPrimitive.Trigger, { className: "flex flex-1 items-center gap-2 min-w-0", children: [
4310
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquareIcon, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" }),
4311
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 flex-col min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-medium text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(react.ThreadListItemPrimitive.Title, { fallback: "New Chat" }) }) })
4312
+ ] }),
4313
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity", children: [
4314
+ /* @__PURE__ */ jsxRuntime.jsx(react.ThreadListItemPrimitive.Archive, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4315
+ TooltipIconButton,
4316
+ {
4317
+ tooltip: "Archive",
4318
+ variant: "ghost",
4319
+ size: "icon",
4320
+ className: "h-6 w-6",
4321
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArchiveIcon, { className: "h-3.5 w-3.5" })
4322
+ }
4323
+ ) }),
4324
+ /* @__PURE__ */ jsxRuntime.jsx(react.ThreadListItemPrimitive.Delete, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4325
+ TooltipIconButton,
4326
+ {
4327
+ tooltip: "Delete",
4328
+ variant: "ghost",
4329
+ size: "icon",
4330
+ className: "h-6 w-6 text-destructive hover:text-destructive",
4331
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2Icon, { className: "h-3.5 w-3.5" })
4332
+ }
4333
+ ) })
4334
+ ] })
4335
+ ] });
4336
+ };
4337
+ var ArchivedThreadListItem = () => {
4338
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.ThreadListItemPrimitive.Root, { className: "aui-thread-list-item-archived group relative flex items-center gap-2 px-3 py-2 hover:bg-muted/50 data-[active]:bg-muted cursor-pointer transition-colors opacity-70", children: [
4339
+ /* @__PURE__ */ jsxRuntime.jsxs(react.ThreadListItemPrimitive.Trigger, { className: "flex flex-1 items-center gap-2 min-w-0", children: [
4340
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArchiveIcon, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" }),
4341
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 flex-col min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(react.ThreadListItemPrimitive.Title, { fallback: "Archived Chat" }) }) })
4342
+ ] }),
4343
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity", children: [
4344
+ /* @__PURE__ */ jsxRuntime.jsx(react.ThreadListItemPrimitive.Unarchive, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4345
+ TooltipIconButton,
4346
+ {
4347
+ tooltip: "Unarchive",
4348
+ variant: "ghost",
4349
+ size: "icon",
4350
+ className: "h-6 w-6",
4351
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArchiveRestoreIcon, { className: "h-3.5 w-3.5" })
4352
+ }
4353
+ ) }),
4354
+ /* @__PURE__ */ jsxRuntime.jsx(react.ThreadListItemPrimitive.Delete, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4355
+ TooltipIconButton,
4356
+ {
4357
+ tooltip: "Delete",
4358
+ variant: "ghost",
4359
+ size: "icon",
4360
+ className: "h-6 w-6 text-destructive hover:text-destructive",
4361
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2Icon, { className: "h-3.5 w-3.5" })
4362
+ }
4363
+ ) })
4364
+ ] })
4365
+ ] });
4366
+ };
4367
+ var categoryIcons = {
4368
+ audio: lucideReact.HeadphonesIcon,
4369
+ "audio-overview": lucideReact.HeadphonesIcon,
4370
+ "video-overview": lucideReact.VideoIcon,
4371
+ "mind-map": lucideReact.NetworkIcon,
4372
+ reports: lucideReact.FileTextIcon,
4373
+ flashcards: lucideReact.LayersIcon,
4374
+ quiz: lucideReact.HelpCircleIcon,
4375
+ "slide-deck": lucideReact.PresentationIcon,
4376
+ infographic: lucideReact.BarChart3Icon
4377
+ };
4378
+ var categoryColors = {
4379
+ audio: "bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300",
4380
+ "audio-overview": "bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300",
4381
+ "video-overview": "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300",
4382
+ "mind-map": "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300",
4383
+ reports: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300",
4384
+ flashcards: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-300",
4385
+ quiz: "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300",
4386
+ "slide-deck": "bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-300",
4387
+ infographic: "bg-teal-100 text-teal-700 dark:bg-teal-900/30 dark:text-teal-300"
4388
+ };
4389
+ var categoryLabels = {
4390
+ audio: "Audio",
4391
+ "audio-overview": "Audio Overview",
4392
+ "video-overview": "Video Overview",
4393
+ "mind-map": "Mind Map",
4394
+ reports: "Report",
4395
+ flashcards: "Flashcards",
4396
+ quiz: "Quiz",
4397
+ "slide-deck": "Slide Deck",
4398
+ infographic: "Infographic"
4399
+ };
4400
+ var ArtifactCard = ({
4401
+ category,
4402
+ title,
4403
+ content,
4404
+ isLoading,
4405
+ children
4406
+ }) => {
4407
+ const Icon = categoryIcons[category];
4408
+ const colorClass = categoryColors[category];
4409
+ const label = categoryLabels[category];
4410
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "my-3 overflow-hidden rounded-xl border border-border bg-card shadow-sm", children: [
4411
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-3 px-4 py-3", colorClass), children: [
4412
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-white/50 dark:bg-black/20", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2Icon, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4" }) }),
4413
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
4414
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium opacity-80", children: label }),
4415
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "truncate font-semibold text-sm", children: title })
4416
+ ] })
4417
+ ] }),
4418
+ content && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-3 text-sm text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "line-clamp-4 whitespace-pre-wrap", children: content }) }),
4419
+ children,
4420
+ !isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-2 border-t border-border px-4 py-2", children: [
4421
+ /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted transition-colors", children: [
4422
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.DownloadIcon, { className: "h-3 w-3" }),
4423
+ "Export"
4424
+ ] }),
4425
+ /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted transition-colors", children: [
4426
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLinkIcon, { className: "h-3 w-3" }),
4427
+ "Open"
4428
+ ] })
4429
+ ] })
4430
+ ] });
4431
+ };
4432
+ function createArtifactToolUI(category) {
4433
+ return react.makeAssistantToolUI({
4434
+ toolName: `create_${category.replace(/-/g, "_")}`,
4435
+ render: ({ args, result, status }) => {
4436
+ const isLoading = status.type === "running";
4437
+ return /* @__PURE__ */ jsxRuntime.jsx(
4438
+ ArtifactCard,
4439
+ {
4440
+ category,
4441
+ title: args.title || "Generating...",
4442
+ content: result?.content || args.content,
4443
+ isLoading
4444
+ }
4445
+ );
4446
+ }
4447
+ });
4448
+ }
4449
+ var AudioOverviewToolUI = createArtifactToolUI("audio-overview");
4450
+ var VideoOverviewToolUI = createArtifactToolUI("video-overview");
4451
+ var MindMapToolUI = createArtifactToolUI("mind-map");
4452
+ var ReportsToolUI = createArtifactToolUI("reports");
4453
+ var FlashcardsToolUI = createArtifactToolUI("flashcards");
4454
+ var QuizToolUI = createArtifactToolUI("quiz");
4455
+ var SlideDeckToolUI = createArtifactToolUI("slide-deck");
4456
+ var InfographicToolUI = createArtifactToolUI("infographic");
4457
+ var ArtifactToolUIs = () => {
4458
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4459
+ /* @__PURE__ */ jsxRuntime.jsx(AudioOverviewToolUI, {}),
4460
+ /* @__PURE__ */ jsxRuntime.jsx(VideoOverviewToolUI, {}),
4461
+ /* @__PURE__ */ jsxRuntime.jsx(MindMapToolUI, {}),
4462
+ /* @__PURE__ */ jsxRuntime.jsx(ReportsToolUI, {}),
4463
+ /* @__PURE__ */ jsxRuntime.jsx(FlashcardsToolUI, {}),
4464
+ /* @__PURE__ */ jsxRuntime.jsx(QuizToolUI, {}),
4465
+ /* @__PURE__ */ jsxRuntime.jsx(SlideDeckToolUI, {}),
4466
+ /* @__PURE__ */ jsxRuntime.jsx(InfographicToolUI, {})
4467
+ ] });
4468
+ };
4469
+ var ChatWidget = ({
4470
+ sidebarOpen = false,
4471
+ onSidebarClose
4472
+ }) => {
4473
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-1 h-full w-full overflow-hidden bg-background", children: [
4474
+ /* @__PURE__ */ jsxRuntime.jsx(ArtifactToolUIs, {}),
4475
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 flex-col min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden relative", children: /* @__PURE__ */ jsxRuntime.jsx(Thread, {}) }) }),
4476
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: sidebarOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4477
+ /* @__PURE__ */ jsxRuntime.jsx(
4478
+ react$1.motion.div,
4479
+ {
4480
+ initial: { opacity: 0 },
4481
+ animate: { opacity: 1 },
4482
+ exit: { opacity: 0 },
4483
+ transition: { duration: 0.2 },
4484
+ className: "absolute inset-0 bg-black/50 z-40",
4485
+ onClick: onSidebarClose
4486
+ }
4487
+ ),
4488
+ /* @__PURE__ */ jsxRuntime.jsx(
4489
+ react$1.motion.div,
4490
+ {
4491
+ initial: { x: -256 },
4492
+ animate: { x: 0 },
4493
+ exit: { x: -256 },
4494
+ transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] },
4495
+ className: cn(
4496
+ "absolute left-0 top-0 bottom-0 w-64 bg-background z-50 overflow-hidden shadow-lg"
4497
+ ),
4498
+ children: /* @__PURE__ */ jsxRuntime.jsx(ThreadList, {})
4499
+ }
4500
+ )
4501
+ ] }) })
4502
+ ] });
4503
+ };
4504
+ var ThreadListItem2 = () => {
4505
+ return /* @__PURE__ */ jsxRuntime.jsx(react.ThreadListItemPrimitive.Root, { className: "group relative flex items-center gap-2 px-2 py-1.5 hover:bg-muted/50 data-[active]:bg-muted cursor-pointer transition-colors rounded-sm", children: /* @__PURE__ */ jsxRuntime.jsx(react.ThreadListItemPrimitive.Trigger, { className: "flex flex-1 items-center gap-2 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(react.ThreadListItemPrimitive.Title, { fallback: "New Chat" }) }) }) });
4506
+ };
4507
+ var ChatHistoryPopover = ({
4508
+ onSelectThread
4509
+ }) => {
4510
+ const handleThreadSelect = () => {
4511
+ onSelectThread?.();
4512
+ };
4513
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", onClick: handleThreadSelect, children: [
4514
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(Text, { size: "xs", style: { color: "hsl(var(--muted-foreground))" }, children: "Previous 7 days" }) }),
4515
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[300px] overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
4516
+ react.ThreadListPrimitive.Items,
4517
+ {
4518
+ components: {
4519
+ ThreadListItem: ThreadListItem2
4520
+ }
4521
+ }
4522
+ ) })
4523
+ ] });
4524
+ };
4525
+ var layoutOptions = [
4526
+ {
4527
+ value: "sidebar",
4528
+ label: "Sidebar",
4529
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeftIcon, { className: "h-4 w-4" })
4530
+ },
4531
+ {
4532
+ value: "floating",
4533
+ label: "Floating",
4534
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SquareIcon, { className: "h-4 w-4" })
4535
+ },
4536
+ {
4537
+ value: "fullscreen",
4538
+ label: "Full Screen",
4539
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2Icon, { className: "h-4 w-4" })
4540
+ }
4541
+ ];
4542
+ var LayoutPopover = ({
4543
+ currentLayout,
4544
+ onLayoutChange
4545
+ }) => {
4546
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children: layoutOptions.map((option) => {
4547
+ const isSelected = currentLayout === option.value;
4548
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4549
+ "button",
4550
+ {
4551
+ onClick: () => onLayoutChange(option.value),
4552
+ className: cn(
4553
+ "flex items-center gap-2 px-2 py-1.5 rounded-sm hover:bg-muted/50 transition-colors cursor-pointer w-full text-left",
4554
+ isSelected && "bg-muted/30"
4555
+ ),
4556
+ children: [
4557
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center w-4 h-4", children: option.icon }),
4558
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: "sm", style: { flex: 1 }, children: option.label }),
4559
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, { className: "h-4 w-4 text-foreground" })
4560
+ ]
4561
+ },
4562
+ option.value
4563
+ );
4564
+ }) });
4565
+ };
4566
+ var LAYOUT_STORAGE_KEY = "learn-alchemy-widget-layout";
4567
+ function WidgetContainer({
4568
+ defaultOpen = false,
4569
+ position: position2 = "bottom-right"
4570
+ }) {
4571
+ const [isOpen, setIsOpen] = React.useState(defaultOpen);
4572
+ const [sidebarOpen, setSidebarOpen] = React.useState(false);
4573
+ const [chatHistoryOpen, setChatHistoryOpen] = React.useState(false);
4574
+ const [layoutOpen, setLayoutOpen] = React.useState(false);
4575
+ const [layout, setLayout] = React.useState("floating");
4576
+ React.useEffect(() => {
4577
+ const savedLayout = localStorage.getItem(LAYOUT_STORAGE_KEY);
4578
+ if (savedLayout && ["floating", "fullscreen", "sidebar"].includes(savedLayout)) {
4579
+ setLayout(savedLayout);
4580
+ }
4581
+ }, []);
4582
+ const handleLayoutChange = (newLayout) => {
4583
+ setLayout(newLayout);
4584
+ localStorage.setItem(LAYOUT_STORAGE_KEY, newLayout);
4585
+ setLayoutOpen(false);
4586
+ };
4587
+ const threadTitle = react.useAssistantState(
4588
+ ({ threadListItem }) => threadListItem?.title ?? "New AI chat"
4589
+ );
4590
+ const handleMinimize = () => {
4591
+ setIsOpen(false);
4592
+ };
4593
+ const handleChatHistorySelect = () => {
4594
+ setChatHistoryOpen(false);
4595
+ };
4596
+ const getWidgetStyles = () => {
4597
+ const baseStyle = {
4598
+ transformOrigin: position2 === "bottom-right" ? "bottom right" : "bottom left"
4599
+ };
4600
+ switch (layout) {
4601
+ case "fullscreen":
4602
+ return {
4603
+ ...baseStyle,
4604
+ position: "fixed",
4605
+ width: "100vw",
4606
+ height: "100vh",
4607
+ maxWidth: "100vw",
4608
+ maxHeight: "100vh",
4609
+ borderRadius: 0,
4610
+ bottom: 0,
4611
+ right: 0,
4612
+ left: 0,
4613
+ top: 0,
4614
+ margin: 0
4615
+ };
4616
+ case "sidebar":
4617
+ return {
4618
+ ...baseStyle,
4619
+ position: "fixed",
4620
+ width: "400px",
4621
+ height: "100vh",
4622
+ maxHeight: "100vh",
4623
+ bottom: 0,
4624
+ top: 0,
4625
+ right: position2 === "bottom-right" ? 0 : "auto",
4626
+ left: position2 === "bottom-left" ? 0 : "auto",
4627
+ borderRadius: 0,
4628
+ margin: 0
4629
+ };
4630
+ case "floating":
4631
+ default:
4632
+ return baseStyle;
4633
+ }
4634
+ };
4635
+ return /* @__PURE__ */ jsxRuntime.jsxs(WidgetRoot, { position: position2, children: [
4636
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: isOpen && /* @__PURE__ */ jsxRuntime.jsxs(
4637
+ WidgetPanel,
4638
+ {
4639
+ initial: { opacity: 0, scale: 0, y: 0 },
4640
+ animate: { opacity: 1, scale: 1, y: 0 },
4641
+ exit: { opacity: 0, scale: 0, y: 0 },
4642
+ transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] },
4643
+ style: getWidgetStyles(),
4644
+ children: [
4645
+ /* @__PURE__ */ jsxRuntime.jsxs(WidgetHeader, { children: [
4646
+ /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: chatHistoryOpen, onOpenChange: setChatHistoryOpen, children: [
4647
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4648
+ "button",
4649
+ {
4650
+ type: "button",
4651
+ style: {
4652
+ cursor: "pointer",
4653
+ background: "none",
4654
+ border: "none",
4655
+ padding: 0,
4656
+ display: "flex",
4657
+ alignItems: "center",
4658
+ minWidth: 0,
4659
+ flex: 1
4660
+ },
4661
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
4662
+ Flex,
4663
+ {
4664
+ align: "center",
4665
+ gap: "xs",
4666
+ style: { minWidth: 0, flex: 1 },
4667
+ children: [
4668
+ /* @__PURE__ */ jsxRuntime.jsx(
4669
+ Text,
4670
+ {
4671
+ size: "sm",
4672
+ style: {
4673
+ fontWeight: 500,
4674
+ overflow: "hidden",
4675
+ textOverflow: "ellipsis",
4676
+ whiteSpace: "nowrap",
4677
+ minWidth: 0
4678
+ },
4679
+ children: threadTitle
4680
+ }
4681
+ ),
4682
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { size: 16, style: { flexShrink: 0 } })
4683
+ ]
4684
+ }
4685
+ )
4686
+ }
4687
+ ) }),
4688
+ /* @__PURE__ */ jsxRuntime.jsx(
4689
+ PopoverContent,
4690
+ {
4691
+ align: "start",
4692
+ side: "bottom",
4693
+ sideOffset: 8,
4694
+ className: "w-64 p-0",
4695
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4696
+ ChatHistoryPopover,
4697
+ {
4698
+ onSelectThread: handleChatHistorySelect
4699
+ }
4700
+ )
4701
+ }
4702
+ )
4703
+ ] }),
4704
+ /* @__PURE__ */ jsxRuntime.jsxs(Flex, { align: "center", gap: "xs", style: { flexShrink: 0 }, children: [
4705
+ /* @__PURE__ */ jsxRuntime.jsx(react.ThreadListPrimitive.New, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(IconButton, { "aria-label": "New chat", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EditIcon, { size: 18 }) }) }),
4706
+ /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: layoutOpen, onOpenChange: setLayoutOpen, children: [
4707
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4708
+ IconButton,
4709
+ {
4710
+ "aria-label": "Layout options",
4711
+ style: {
4712
+ backgroundColor: layoutOpen ? "hsl(var(--muted))" : "transparent"
4713
+ },
4714
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LayoutIcon, { size: 18 })
4715
+ }
4716
+ ) }),
4717
+ /* @__PURE__ */ jsxRuntime.jsx(
4718
+ PopoverContent,
4719
+ {
4720
+ align: "end",
4721
+ side: "bottom",
4722
+ sideOffset: 8,
4723
+ className: "w-48 p-2",
4724
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4725
+ LayoutPopover,
4726
+ {
4727
+ currentLayout: layout,
4728
+ onLayoutChange: handleLayoutChange
4729
+ }
4730
+ )
4731
+ }
4732
+ )
4733
+ ] }),
4734
+ /* @__PURE__ */ jsxRuntime.jsx(
4735
+ IconButton,
4736
+ {
4737
+ onClick: handleMinimize,
4738
+ "aria-label": "Minimize widget",
4739
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minimize2Icon, { size: 18 })
4740
+ }
4741
+ )
4742
+ ] })
4743
+ ] }),
4744
+ /* @__PURE__ */ jsxRuntime.jsx(WidgetContent, { children: /* @__PURE__ */ jsxRuntime.jsx(
4745
+ ChatWidget,
4746
+ {
4747
+ sidebarOpen,
4748
+ onSidebarClose: () => setSidebarOpen(false)
4749
+ }
4750
+ ) })
4751
+ ]
4752
+ }
4753
+ ) }),
4754
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: !isOpen && /* @__PURE__ */ jsxRuntime.jsx(
4755
+ Flex,
4756
+ {
4757
+ justify: position2 === "bottom-right" ? "flex-end" : "flex-start",
4758
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4759
+ FAB,
4760
+ {
4761
+ onClick: () => setIsOpen(true),
4762
+ initial: { opacity: 0, y: 20 },
4763
+ animate: { opacity: 1, y: 0 },
4764
+ exit: { opacity: 0, y: 20 },
4765
+ transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] },
4766
+ whileHover: { scale: 1.1 },
4767
+ whileTap: { scale: 0.9 },
4768
+ "aria-label": "Open chat",
4769
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BotIcon, { size: 24, strokeWidth: 2 })
4770
+ }
4771
+ )
4772
+ }
4773
+ ) })
4774
+ ] });
4775
+ }
4776
+ var ReadOnlyThread = () => {
4777
+ return /* @__PURE__ */ jsxRuntime.jsx(
4778
+ react.ThreadPrimitive.Root,
4779
+ {
4780
+ className: "aui-thread-root @container flex h-full flex-col bg-background",
4781
+ style: {
4782
+ ["--thread-max-width"]: "44rem"
4783
+ },
4784
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
4785
+ react.ThreadPrimitive.Viewport,
4786
+ {
4787
+ turnAnchor: "top",
4788
+ className: "aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth px-4 pt-4 pb-4",
4789
+ children: [
4790
+ /* @__PURE__ */ jsxRuntime.jsx(
4791
+ react.ThreadPrimitive.Messages,
4792
+ {
4793
+ components: {
4794
+ UserMessage: ReadOnlyUserMessage,
4795
+ EditComposer: ReadOnlyUserMessage,
4796
+ // Disable edit mode
4797
+ AssistantMessage: ReadOnlyAssistantMessage
4798
+ }
4799
+ }
4800
+ ),
4801
+ /* @__PURE__ */ jsxRuntime.jsx(react.ThreadPrimitive.Empty, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center text-muted-foreground", children: "No messages in this conversation." }) })
4802
+ ]
4803
+ }
4804
+ )
4805
+ }
4806
+ );
4807
+ };
4808
+ var ReadOnlyAssistantMessage = () => {
4809
+ return /* @__PURE__ */ jsxRuntime.jsx(
4810
+ react.MessagePrimitive.Root,
4811
+ {
4812
+ className: "aui-assistant-message-root fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in py-3 duration-150",
4813
+ "data-role": "assistant",
4814
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed", children: [
4815
+ /* @__PURE__ */ jsxRuntime.jsx(
4816
+ react.MessagePrimitive.Parts,
4817
+ {
4818
+ components: {
4819
+ Text: MarkdownText,
4820
+ tools: { Fallback: ToolFallback }
4821
+ }
4822
+ }
4823
+ ),
4824
+ /* @__PURE__ */ jsxRuntime.jsx(react.MessagePrimitive.Error, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm", children: /* @__PURE__ */ jsxRuntime.jsx(react.MessagePrimitive.Error, {}) }) })
4825
+ ] })
4826
+ }
4827
+ );
4828
+ };
4829
+ var ReadOnlyUserMessage = () => {
4830
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4831
+ react.MessagePrimitive.Root,
4832
+ {
4833
+ className: "aui-user-message-root fade-in slide-in-from-bottom-1 mx-auto grid w-full max-w-(--thread-max-width) animate-in auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] content-start gap-y-2 px-2 py-3 duration-150 [&:where(>*)]:col-start-2",
4834
+ "data-role": "user",
4835
+ children: [
4836
+ /* @__PURE__ */ jsxRuntime.jsx(UserMessageAttachments, {}),
4837
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aui-user-message-content-wrapper relative col-start-2 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aui-user-message-content wrap-break-word rounded-2xl bg-muted px-4 py-2.5 text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(UserMessageContent, {}) }) })
4838
+ ]
4839
+ }
4840
+ );
4841
+ };
4842
+
4843
+ exports.ArtifactToolUIs = ArtifactToolUIs;
4844
+ exports.ChatWidget = ChatWidget;
4845
+ exports.ReadOnlyThread = ReadOnlyThread;
4846
+ exports.Thread = Thread;
4847
+ exports.ThreadList = ThreadList;
4848
+ exports.WidgetContainer = WidgetContainer;
4849
+ exports.WidgetContext = WidgetContext;
4850
+ exports.WidgetProvider = WidgetProvider;
4851
+ exports.createWidgetCache = createWidgetCache;
4852
+ exports.theme = theme;
4853
+ exports.useChat = useChat;
4854
+ exports.useWidget = useWidget;
4855
+ exports.widgetCache = widgetCache;
4856
+ //# sourceMappingURL=react.cjs.map
4857
+ //# sourceMappingURL=react.cjs.map