@arc-lo/ui 0.1.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/index.js ADDED
@@ -0,0 +1,2957 @@
1
+ import { createContext, forwardRef, useState, useCallback, useRef, useEffect, useMemo, useId, useContext } from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
+
6
+ var __defProp = Object.defineProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+
12
+ // src/streaming-text/index.ts
13
+ var streaming_text_exports = {};
14
+ __export(streaming_text_exports, {
15
+ Content: () => Content,
16
+ Cursor: () => Cursor,
17
+ ErrorFallback: () => ErrorFallback,
18
+ RateLimit: () => RateLimit,
19
+ Root: () => Root,
20
+ Skeleton: () => Skeleton,
21
+ Stop: () => Stop,
22
+ Toolbar: () => Toolbar,
23
+ useStreamingText: () => useStreamingText,
24
+ useStreamingTextContext: () => useStreamingTextContext
25
+ });
26
+ function cn(...inputs) {
27
+ return twMerge(clsx(inputs));
28
+ }
29
+
30
+ // src/lib/theme.ts
31
+ var themeVars = {
32
+ accent: "var(--arclo-accent, #6C5CE7)",
33
+ surface: "var(--arclo-surface, #ffffff)",
34
+ surfaceSecondary: "var(--arclo-surface-secondary, #f9fafb)",
35
+ border: "var(--arclo-border, #e5e7eb)",
36
+ text: "var(--arclo-text, #1a1a1a)",
37
+ textSecondary: "var(--arclo-text-secondary, #6b7280)",
38
+ textMuted: "var(--arclo-text-muted, #9ca3af)",
39
+ error: "var(--arclo-error, #ef4444)",
40
+ errorSurface: "var(--arclo-error-surface, #fef2f2)"};
41
+ function chunkText(text, mode) {
42
+ switch (mode) {
43
+ case "char":
44
+ return text.split("");
45
+ case "word":
46
+ return text.match(/\S+\s*/g) ?? [text];
47
+ case "line":
48
+ return text.match(/[^\n]*\n?/g)?.filter(Boolean) ?? [text];
49
+ }
50
+ }
51
+ function useStreamingText({
52
+ stream,
53
+ text,
54
+ speed = 30,
55
+ chunkSize = "char",
56
+ onDone,
57
+ onError,
58
+ onInterrupt
59
+ }) {
60
+ const [displayedText, setDisplayedText] = useState("");
61
+ const [fullText, setFullText] = useState("");
62
+ const [state, setState] = useState("pending");
63
+ const bufferRef = useRef([]);
64
+ const drainingRef = useRef(false);
65
+ const timerRef = useRef(null);
66
+ const interruptedRef = useRef(false);
67
+ const readerRef = useRef(null);
68
+ const speedRef = useRef(speed);
69
+ const fullTextRef = useRef("");
70
+ const onDoneRef = useRef(onDone);
71
+ const onErrorRef = useRef(onError);
72
+ const onInterruptRef = useRef(onInterrupt);
73
+ speedRef.current = speed;
74
+ onDoneRef.current = onDone;
75
+ onErrorRef.current = onError;
76
+ onInterruptRef.current = onInterrupt;
77
+ const startDraining = useCallback(() => {
78
+ if (drainingRef.current) return;
79
+ drainingRef.current = true;
80
+ function tick() {
81
+ if (bufferRef.current.length === 0) {
82
+ drainingRef.current = false;
83
+ return;
84
+ }
85
+ const chunk = bufferRef.current.shift();
86
+ setDisplayedText((prev) => prev + chunk);
87
+ timerRef.current = setTimeout(tick, speedRef.current);
88
+ }
89
+ tick();
90
+ }, []);
91
+ useEffect(() => {
92
+ if (!stream) return;
93
+ interruptedRef.current = false;
94
+ drainingRef.current = false;
95
+ bufferRef.current = [];
96
+ fullTextRef.current = "";
97
+ setDisplayedText("");
98
+ setFullText("");
99
+ setState("streaming");
100
+ let cancelled = false;
101
+ let reader;
102
+ try {
103
+ reader = stream.getReader();
104
+ } catch {
105
+ return;
106
+ }
107
+ readerRef.current = reader;
108
+ async function read() {
109
+ try {
110
+ while (true) {
111
+ const { done, value } = await reader.read();
112
+ if (cancelled || interruptedRef.current) break;
113
+ if (done) {
114
+ const waitForDrain = () => {
115
+ if (cancelled) return;
116
+ if (bufferRef.current.length === 0 && !drainingRef.current) {
117
+ setState("done");
118
+ onDoneRef.current?.(fullTextRef.current);
119
+ } else {
120
+ setTimeout(waitForDrain, 50);
121
+ }
122
+ };
123
+ waitForDrain();
124
+ return;
125
+ }
126
+ const chunks = chunkText(value, chunkSize);
127
+ bufferRef.current.push(...chunks);
128
+ fullTextRef.current += value;
129
+ setFullText(fullTextRef.current);
130
+ startDraining();
131
+ }
132
+ } catch (err) {
133
+ if (!cancelled && !interruptedRef.current) {
134
+ setState("error");
135
+ onErrorRef.current?.(
136
+ err instanceof Error ? err : new Error(String(err))
137
+ );
138
+ }
139
+ }
140
+ }
141
+ read();
142
+ return () => {
143
+ cancelled = true;
144
+ if (timerRef.current) clearTimeout(timerRef.current);
145
+ drainingRef.current = false;
146
+ reader.cancel().catch(() => {
147
+ });
148
+ };
149
+ }, [stream, chunkSize, startDraining]);
150
+ useEffect(() => {
151
+ if (text == null || stream) return;
152
+ interruptedRef.current = false;
153
+ drainingRef.current = false;
154
+ bufferRef.current = [];
155
+ fullTextRef.current = text;
156
+ setDisplayedText("");
157
+ setFullText(text);
158
+ setState("streaming");
159
+ const chunks = chunkText(text, chunkSize);
160
+ bufferRef.current = chunks;
161
+ startDraining();
162
+ const waitForDrain = () => {
163
+ if (bufferRef.current.length === 0 && !drainingRef.current) {
164
+ setState("done");
165
+ onDoneRef.current?.(text);
166
+ } else {
167
+ setTimeout(waitForDrain, 50);
168
+ }
169
+ };
170
+ setTimeout(waitForDrain, 100);
171
+ return () => {
172
+ if (timerRef.current) clearTimeout(timerRef.current);
173
+ drainingRef.current = false;
174
+ };
175
+ }, [text, stream, chunkSize, startDraining]);
176
+ const interrupt = useCallback(() => {
177
+ interruptedRef.current = true;
178
+ if (timerRef.current) clearTimeout(timerRef.current);
179
+ drainingRef.current = false;
180
+ readerRef.current?.cancel().catch(() => {
181
+ });
182
+ bufferRef.current = [];
183
+ setState("interrupted");
184
+ setDisplayedText((t) => {
185
+ onInterruptRef.current?.(t);
186
+ return t;
187
+ });
188
+ }, []);
189
+ const reset = useCallback(() => {
190
+ interruptedRef.current = false;
191
+ if (timerRef.current) clearTimeout(timerRef.current);
192
+ drainingRef.current = false;
193
+ bufferRef.current = [];
194
+ fullTextRef.current = "";
195
+ setDisplayedText("");
196
+ setFullText("");
197
+ setState("pending");
198
+ }, []);
199
+ const skipAnimation = useCallback(() => {
200
+ if (timerRef.current) clearTimeout(timerRef.current);
201
+ drainingRef.current = false;
202
+ bufferRef.current = [];
203
+ setDisplayedText(fullTextRef.current);
204
+ }, []);
205
+ return { displayedText, fullText, state, interrupt, reset, skipAnimation };
206
+ }
207
+ var StreamingTextContext = createContext(
208
+ null
209
+ );
210
+ function useStreamingTextContext() {
211
+ const ctx = useContext(StreamingTextContext);
212
+ if (!ctx) {
213
+ throw new Error(
214
+ "useStreamingTextContext must be used within <StreamingText.Root>"
215
+ );
216
+ }
217
+ return ctx;
218
+ }
219
+ var Root = forwardRef(
220
+ ({
221
+ stream,
222
+ text,
223
+ speed,
224
+ chunkSize,
225
+ onDone,
226
+ onError,
227
+ onInterrupt,
228
+ children,
229
+ className,
230
+ ...props
231
+ }, ref) => {
232
+ const ctx = useStreamingText({
233
+ stream,
234
+ text,
235
+ speed,
236
+ chunkSize,
237
+ onDone,
238
+ onError,
239
+ onInterrupt
240
+ });
241
+ return /* @__PURE__ */ jsx(StreamingTextContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
242
+ "div",
243
+ {
244
+ ref,
245
+ "data-state": ctx.state,
246
+ className: cn("arclo-streaming-text", className),
247
+ ...props,
248
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
249
+ /* @__PURE__ */ jsx(Content, {}),
250
+ /* @__PURE__ */ jsx(Cursor, {})
251
+ ] })
252
+ }
253
+ ) });
254
+ }
255
+ );
256
+ Root.displayName = "StreamingText.Root";
257
+ var Content = forwardRef(
258
+ ({ render, className, ...props }, ref) => {
259
+ const { displayedText, state } = useStreamingTextContext();
260
+ return /* @__PURE__ */ jsx(
261
+ "div",
262
+ {
263
+ ref,
264
+ "data-state": state,
265
+ className: cn("arclo-streaming-content whitespace-pre-wrap", className),
266
+ ...props,
267
+ children: render ? render(displayedText) : displayedText
268
+ }
269
+ );
270
+ }
271
+ );
272
+ Content.displayName = "StreamingText.Content";
273
+ var Cursor = forwardRef(
274
+ ({ char = "\u258B", className, ...props }, ref) => {
275
+ const { state } = useStreamingTextContext();
276
+ const visible = state === "streaming" || state === "pending";
277
+ if (!visible) return null;
278
+ return /* @__PURE__ */ jsx(
279
+ "span",
280
+ {
281
+ ref,
282
+ "aria-hidden": true,
283
+ style: { color: themeVars.accent },
284
+ className: cn(
285
+ "arclo-streaming-cursor inline-block animate-pulse",
286
+ className
287
+ ),
288
+ ...props,
289
+ children: char
290
+ }
291
+ );
292
+ }
293
+ );
294
+ Cursor.displayName = "StreamingText.Cursor";
295
+ var Skeleton = forwardRef(
296
+ ({ lines = 3, className, ...props }, ref) => {
297
+ const { state } = useStreamingTextContext();
298
+ if (state !== "pending") return null;
299
+ return /* @__PURE__ */ jsx(
300
+ "div",
301
+ {
302
+ ref,
303
+ role: "status",
304
+ "aria-label": "Loading",
305
+ className: cn("arclo-streaming-skeleton space-y-2", className),
306
+ ...props,
307
+ children: Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx(
308
+ "div",
309
+ {
310
+ className: cn(
311
+ "h-4 rounded bg-gray-200 animate-pulse",
312
+ i === lines - 1 && "w-2/3"
313
+ )
314
+ },
315
+ i
316
+ ))
317
+ }
318
+ );
319
+ }
320
+ );
321
+ Skeleton.displayName = "StreamingText.Skeleton";
322
+ var ErrorFallback = forwardRef(
323
+ ({ message = "Something went wrong.", onRetry, className, ...props }, ref) => {
324
+ const { state } = useStreamingTextContext();
325
+ if (state !== "error") return null;
326
+ return /* @__PURE__ */ jsxs(
327
+ "div",
328
+ {
329
+ ref,
330
+ role: "alert",
331
+ style: {
332
+ borderColor: themeVars.error,
333
+ backgroundColor: themeVars.errorSurface,
334
+ color: themeVars.error
335
+ },
336
+ className: cn(
337
+ "arclo-streaming-error rounded-lg border p-4 text-sm",
338
+ className
339
+ ),
340
+ ...props,
341
+ children: [
342
+ /* @__PURE__ */ jsx("p", { children: message }),
343
+ onRetry && /* @__PURE__ */ jsx(
344
+ "button",
345
+ {
346
+ type: "button",
347
+ onClick: onRetry,
348
+ className: "mt-2 text-red-600 underline hover:text-red-800 cursor-pointer",
349
+ children: "Try again"
350
+ }
351
+ )
352
+ ]
353
+ }
354
+ );
355
+ }
356
+ );
357
+ ErrorFallback.displayName = "StreamingText.ErrorFallback";
358
+ var RateLimit = forwardRef(
359
+ ({
360
+ retryAfter,
361
+ message = "Rate limit reached. Please wait.",
362
+ className,
363
+ ...props
364
+ }, ref) => {
365
+ const { state } = useStreamingTextContext();
366
+ if (state !== "ratelimit") return null;
367
+ return /* @__PURE__ */ jsxs(
368
+ "div",
369
+ {
370
+ ref,
371
+ role: "status",
372
+ className: cn(
373
+ "arclo-streaming-ratelimit rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm text-amber-800",
374
+ className
375
+ ),
376
+ ...props,
377
+ children: [
378
+ /* @__PURE__ */ jsx("p", { children: message }),
379
+ retryAfter != null && /* @__PURE__ */ jsxs("p", { className: "mt-1 text-amber-600", children: [
380
+ "Retry in ",
381
+ retryAfter,
382
+ "s"
383
+ ] })
384
+ ]
385
+ }
386
+ );
387
+ }
388
+ );
389
+ RateLimit.displayName = "StreamingText.RateLimit";
390
+ var Toolbar = forwardRef(
391
+ ({ showIn = ["done", "interrupted"], children, className, ...props }, ref) => {
392
+ const { state } = useStreamingTextContext();
393
+ if (!showIn.includes(state)) return null;
394
+ return /* @__PURE__ */ jsx(
395
+ "div",
396
+ {
397
+ ref,
398
+ className: cn(
399
+ "arclo-streaming-toolbar mt-2 flex items-center gap-2 animate-in fade-in duration-150",
400
+ className
401
+ ),
402
+ ...props,
403
+ children
404
+ }
405
+ );
406
+ }
407
+ );
408
+ Toolbar.displayName = "StreamingText.Toolbar";
409
+ var Stop = forwardRef(
410
+ ({ children, className, ...props }, ref) => {
411
+ const { state, interrupt } = useStreamingTextContext();
412
+ if (state !== "streaming") return null;
413
+ return /* @__PURE__ */ jsx(
414
+ "button",
415
+ {
416
+ ref,
417
+ type: "button",
418
+ onClick: interrupt,
419
+ className: cn(
420
+ "arclo-streaming-stop rounded-md border border-gray-300 px-3 py-1.5 text-sm hover:bg-gray-50 cursor-pointer",
421
+ className
422
+ ),
423
+ ...props,
424
+ children: children ?? "Stop generating"
425
+ }
426
+ );
427
+ }
428
+ );
429
+ Stop.displayName = "StreamingText.Stop";
430
+
431
+ // src/prompt-box/index.ts
432
+ var prompt_box_exports = {};
433
+ __export(prompt_box_exports, {
434
+ Chip: () => Chip,
435
+ Chips: () => Chips,
436
+ Footer: () => Footer,
437
+ Input: () => Input,
438
+ Root: () => Root2,
439
+ SubmitButton: () => SubmitButton,
440
+ Suggestions: () => Suggestions,
441
+ usePromptBoxContext: () => usePromptBoxContext
442
+ });
443
+ var PromptBoxContext = createContext(null);
444
+ function usePromptBoxContext() {
445
+ const ctx = useContext(PromptBoxContext);
446
+ if (!ctx) {
447
+ throw new Error(
448
+ "usePromptBoxContext must be used within <PromptBox.Root>"
449
+ );
450
+ }
451
+ return ctx;
452
+ }
453
+ var Root2 = forwardRef(
454
+ ({
455
+ value: controlledValue,
456
+ defaultValue = "",
457
+ onSubmit,
458
+ onValueChange,
459
+ isSubmitting = false,
460
+ disabled = false,
461
+ children,
462
+ className,
463
+ ...props
464
+ }, ref) => {
465
+ const [internalValue, setInternalValue] = useState(defaultValue);
466
+ const value = controlledValue ?? internalValue;
467
+ const setValue = useCallback(
468
+ (v) => {
469
+ if (controlledValue === void 0) setInternalValue(v);
470
+ onValueChange?.(v);
471
+ },
472
+ [controlledValue, onValueChange]
473
+ );
474
+ const submit = useCallback(() => {
475
+ if (!value.trim() || isSubmitting || disabled) return;
476
+ onSubmit?.(value);
477
+ }, [value, isSubmitting, disabled, onSubmit]);
478
+ const handleFormSubmit = useCallback(
479
+ (e) => {
480
+ e.preventDefault();
481
+ submit();
482
+ },
483
+ [submit]
484
+ );
485
+ return /* @__PURE__ */ jsx(
486
+ PromptBoxContext.Provider,
487
+ {
488
+ value: { value, setValue, submit, isSubmitting, disabled },
489
+ children: /* @__PURE__ */ jsx(
490
+ "form",
491
+ {
492
+ ref,
493
+ onSubmit: handleFormSubmit,
494
+ style: {
495
+ backgroundColor: themeVars.surface,
496
+ borderColor: themeVars.border,
497
+ color: themeVars.text
498
+ },
499
+ className: cn(
500
+ "arclo-prompt-box rounded-2xl border shadow-sm transition-all focus-within:shadow-md",
501
+ disabled && "opacity-50 pointer-events-none",
502
+ className
503
+ ),
504
+ ...props,
505
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
506
+ /* @__PURE__ */ jsx(Input, {}),
507
+ /* @__PURE__ */ jsx(Footer, { children: /* @__PURE__ */ jsx(SubmitButton, {}) })
508
+ ] })
509
+ }
510
+ )
511
+ }
512
+ );
513
+ }
514
+ );
515
+ Root2.displayName = "PromptBox.Root";
516
+ var Chips = forwardRef(
517
+ ({ children, className, ...props }, ref) => {
518
+ return /* @__PURE__ */ jsx(
519
+ "div",
520
+ {
521
+ ref,
522
+ className: cn(
523
+ "arclo-prompt-chips flex flex-wrap gap-2 px-4 pt-4 pb-1",
524
+ className
525
+ ),
526
+ ...props,
527
+ children
528
+ }
529
+ );
530
+ }
531
+ );
532
+ Chips.displayName = "PromptBox.Chips";
533
+ var Chip = forwardRef(
534
+ ({ children, onRemove, className, ...props }, ref) => {
535
+ return /* @__PURE__ */ jsxs(
536
+ "span",
537
+ {
538
+ ref,
539
+ className: cn(
540
+ "arclo-prompt-chip inline-flex items-center gap-1.5 rounded-lg bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-600",
541
+ className
542
+ ),
543
+ ...props,
544
+ children: [
545
+ children,
546
+ onRemove && /* @__PURE__ */ jsx(
547
+ "button",
548
+ {
549
+ type: "button",
550
+ onClick: onRemove,
551
+ className: "text-gray-400 hover:text-gray-600 transition-colors cursor-pointer",
552
+ "aria-label": "Remove",
553
+ children: "\xD7"
554
+ }
555
+ )
556
+ ]
557
+ }
558
+ );
559
+ }
560
+ );
561
+ Chip.displayName = "PromptBox.Chip";
562
+ var Input = forwardRef(
563
+ ({ minRows = 1, maxRows = 8, className, onKeyDown, ...props }, ref) => {
564
+ const { value, setValue, submit, isSubmitting, disabled } = usePromptBoxContext();
565
+ const internalRef = useRef(null);
566
+ const textareaRef = ref ?? internalRef;
567
+ useEffect(() => {
568
+ const el = textareaRef.current;
569
+ if (!el) return;
570
+ el.style.height = "auto";
571
+ const lineHeight = parseInt(getComputedStyle(el).lineHeight) || 20;
572
+ const minH = lineHeight * minRows;
573
+ const maxH = lineHeight * maxRows;
574
+ el.style.height = `${Math.min(Math.max(el.scrollHeight, minH), maxH)}px`;
575
+ }, [value, minRows, maxRows, textareaRef]);
576
+ const handleKeyDown = useCallback(
577
+ (e) => {
578
+ if (e.key === "Enter" && !e.shiftKey) {
579
+ e.preventDefault();
580
+ submit();
581
+ }
582
+ onKeyDown?.(e);
583
+ },
584
+ [submit, onKeyDown]
585
+ );
586
+ return /* @__PURE__ */ jsx(
587
+ "textarea",
588
+ {
589
+ ref: textareaRef,
590
+ value,
591
+ onChange: (e) => setValue(e.target.value),
592
+ onKeyDown: handleKeyDown,
593
+ disabled: disabled || isSubmitting,
594
+ rows: minRows,
595
+ placeholder: "Ask anything...",
596
+ className: cn(
597
+ "arclo-prompt-input w-full resize-none bg-transparent px-4 py-3 text-[15px] leading-relaxed outline-none placeholder:text-gray-400 [scrollbar-width:thin] [scrollbar-color:theme(colors.gray.300)_transparent] [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-gray-300",
598
+ className
599
+ ),
600
+ ...props
601
+ }
602
+ );
603
+ }
604
+ );
605
+ Input.displayName = "PromptBox.Input";
606
+ var Footer = forwardRef(
607
+ ({ children, className, ...props }, ref) => {
608
+ return /* @__PURE__ */ jsx(
609
+ "div",
610
+ {
611
+ ref,
612
+ className: cn(
613
+ "arclo-prompt-footer flex items-center justify-between px-4 pb-3 pt-1",
614
+ className
615
+ ),
616
+ ...props,
617
+ children
618
+ }
619
+ );
620
+ }
621
+ );
622
+ Footer.displayName = "PromptBox.Footer";
623
+ var SubmitButton = forwardRef(
624
+ ({ children, className, ...props }, ref) => {
625
+ const { value, isSubmitting, disabled } = usePromptBoxContext();
626
+ const isEmpty = !value.trim();
627
+ return /* @__PURE__ */ jsx(
628
+ "button",
629
+ {
630
+ ref,
631
+ type: "submit",
632
+ disabled: isEmpty || isSubmitting || disabled,
633
+ style: { backgroundColor: themeVars.accent },
634
+ className: cn(
635
+ "arclo-prompt-submit ml-auto rounded-xl px-4 py-2 text-sm font-medium text-white transition-all hover:brightness-90 disabled:opacity-25 cursor-pointer disabled:cursor-default",
636
+ className
637
+ ),
638
+ ...props,
639
+ children: children ?? (isSubmitting ? "Sending..." : "Send")
640
+ }
641
+ );
642
+ }
643
+ );
644
+ SubmitButton.displayName = "PromptBox.SubmitButton";
645
+ var Suggestions = forwardRef(({ suggestions, onSelect, className, ...props }, ref) => {
646
+ const { setValue } = usePromptBoxContext();
647
+ if (suggestions.length === 0) return null;
648
+ return /* @__PURE__ */ jsx(
649
+ "div",
650
+ {
651
+ ref,
652
+ className: cn(
653
+ "arclo-prompt-suggestions flex flex-wrap gap-2 px-4 pb-2 pt-1",
654
+ className
655
+ ),
656
+ ...props,
657
+ children: suggestions.map((s) => /* @__PURE__ */ jsx(
658
+ "button",
659
+ {
660
+ type: "button",
661
+ onClick: () => {
662
+ setValue(s);
663
+ onSelect?.(s);
664
+ },
665
+ className: "rounded-full border border-gray-200 px-3.5 py-1.5 text-xs text-gray-500 transition-all hover:border-gray-300 hover:bg-gray-50 hover:text-gray-700 cursor-pointer",
666
+ children: s
667
+ },
668
+ s
669
+ ))
670
+ }
671
+ );
672
+ });
673
+ Suggestions.displayName = "PromptBox.Suggestions";
674
+
675
+ // src/feedback-bar/index.ts
676
+ var feedback_bar_exports = {};
677
+ __export(feedback_bar_exports, {
678
+ Copy: () => Copy,
679
+ Regenerate: () => Regenerate,
680
+ Root: () => Root3,
681
+ ThumbsDown: () => ThumbsDown,
682
+ ThumbsUp: () => ThumbsUp
683
+ });
684
+ var FeedbackBarContext = createContext(null);
685
+ function useFeedbackBarContext() {
686
+ const ctx = useContext(FeedbackBarContext);
687
+ if (!ctx) {
688
+ throw new Error("FeedbackBar parts must be used within <FeedbackBar.Root>");
689
+ }
690
+ return ctx;
691
+ }
692
+ var Root3 = forwardRef(
693
+ ({ onFeedback, children, className, ...props }, ref) => {
694
+ const [feedback, setFeedbackState] = useState(null);
695
+ const [copied, setCopied] = useState(false);
696
+ const setFeedback = useCallback(
697
+ (v) => {
698
+ setFeedbackState(v);
699
+ onFeedback?.(v);
700
+ },
701
+ [onFeedback]
702
+ );
703
+ return /* @__PURE__ */ jsx(
704
+ FeedbackBarContext.Provider,
705
+ {
706
+ value: { feedback, setFeedback, copied, setCopied },
707
+ children: /* @__PURE__ */ jsx(
708
+ "div",
709
+ {
710
+ ref,
711
+ role: "toolbar",
712
+ "aria-label": "Response actions",
713
+ className: cn(
714
+ "arclo-feedback-bar flex items-center gap-1",
715
+ className
716
+ ),
717
+ ...props,
718
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
719
+ /* @__PURE__ */ jsx(ThumbsUp, {}),
720
+ /* @__PURE__ */ jsx(ThumbsDown, {}),
721
+ /* @__PURE__ */ jsx(Copy, {})
722
+ ] })
723
+ }
724
+ )
725
+ }
726
+ );
727
+ }
728
+ );
729
+ Root3.displayName = "FeedbackBar.Root";
730
+ var btnClass = "arclo-feedback-btn inline-flex items-center justify-center rounded-md p-1.5 text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-600 cursor-pointer";
731
+ var ThumbsUp = forwardRef(
732
+ ({ className, ...props }, ref) => {
733
+ const { feedback, setFeedback } = useFeedbackBarContext();
734
+ const active = feedback === "up";
735
+ return /* @__PURE__ */ jsx(
736
+ "button",
737
+ {
738
+ ref,
739
+ type: "button",
740
+ "aria-label": "Good response",
741
+ "aria-pressed": active,
742
+ onClick: () => setFeedback(active ? null : "up"),
743
+ style: active ? { color: themeVars.accent } : void 0,
744
+ className: cn(btnClass, className),
745
+ ...props,
746
+ children: /* @__PURE__ */ jsxs(
747
+ "svg",
748
+ {
749
+ width: "16",
750
+ height: "16",
751
+ viewBox: "0 0 24 24",
752
+ fill: "none",
753
+ stroke: "currentColor",
754
+ strokeWidth: "2",
755
+ strokeLinecap: "round",
756
+ strokeLinejoin: "round",
757
+ children: [
758
+ /* @__PURE__ */ jsx("path", { d: "M7 10v12" }),
759
+ /* @__PURE__ */ jsx("path", { d: "M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z" })
760
+ ]
761
+ }
762
+ )
763
+ }
764
+ );
765
+ }
766
+ );
767
+ ThumbsUp.displayName = "FeedbackBar.ThumbsUp";
768
+ var ThumbsDown = forwardRef(({ className, ...props }, ref) => {
769
+ const { feedback, setFeedback } = useFeedbackBarContext();
770
+ const active = feedback === "down";
771
+ return /* @__PURE__ */ jsx(
772
+ "button",
773
+ {
774
+ ref,
775
+ type: "button",
776
+ "aria-label": "Bad response",
777
+ "aria-pressed": active,
778
+ onClick: () => setFeedback(active ? null : "down"),
779
+ className: cn(btnClass, active && "text-red-500", className),
780
+ ...props,
781
+ children: /* @__PURE__ */ jsxs(
782
+ "svg",
783
+ {
784
+ width: "16",
785
+ height: "16",
786
+ viewBox: "0 0 24 24",
787
+ fill: "none",
788
+ stroke: "currentColor",
789
+ strokeWidth: "2",
790
+ strokeLinecap: "round",
791
+ strokeLinejoin: "round",
792
+ children: [
793
+ /* @__PURE__ */ jsx("path", { d: "M17 14V2" }),
794
+ /* @__PURE__ */ jsx("path", { d: "M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z" })
795
+ ]
796
+ }
797
+ )
798
+ }
799
+ );
800
+ });
801
+ ThumbsDown.displayName = "FeedbackBar.ThumbsDown";
802
+ var Copy = forwardRef(
803
+ ({ text, className, ...props }, ref) => {
804
+ const { copied, setCopied } = useFeedbackBarContext();
805
+ const handleCopy = useCallback(async () => {
806
+ const content = text ?? ref?.current?.closest("[data-arclo-copyable]")?.textContent ?? "";
807
+ await navigator.clipboard.writeText(content);
808
+ setCopied(true);
809
+ setTimeout(() => setCopied(false), 2e3);
810
+ }, [text, ref, setCopied]);
811
+ return /* @__PURE__ */ jsx(
812
+ "button",
813
+ {
814
+ ref,
815
+ type: "button",
816
+ "aria-label": copied ? "Copied" : "Copy",
817
+ onClick: handleCopy,
818
+ className: cn(btnClass, copied && "text-emerald-600", className),
819
+ ...props,
820
+ children: copied ? /* @__PURE__ */ jsx(
821
+ "svg",
822
+ {
823
+ width: "16",
824
+ height: "16",
825
+ viewBox: "0 0 24 24",
826
+ fill: "none",
827
+ stroke: "currentColor",
828
+ strokeWidth: "2",
829
+ strokeLinecap: "round",
830
+ strokeLinejoin: "round",
831
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
832
+ }
833
+ ) : /* @__PURE__ */ jsxs(
834
+ "svg",
835
+ {
836
+ width: "16",
837
+ height: "16",
838
+ viewBox: "0 0 24 24",
839
+ fill: "none",
840
+ stroke: "currentColor",
841
+ strokeWidth: "2",
842
+ strokeLinecap: "round",
843
+ strokeLinejoin: "round",
844
+ children: [
845
+ /* @__PURE__ */ jsx("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
846
+ /* @__PURE__ */ jsx("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
847
+ ]
848
+ }
849
+ )
850
+ }
851
+ );
852
+ }
853
+ );
854
+ Copy.displayName = "FeedbackBar.Copy";
855
+ var Regenerate = forwardRef(({ onRegenerate, className, ...props }, ref) => {
856
+ return /* @__PURE__ */ jsx(
857
+ "button",
858
+ {
859
+ ref,
860
+ type: "button",
861
+ "aria-label": "Regenerate response",
862
+ onClick: onRegenerate,
863
+ className: cn(btnClass, className),
864
+ ...props,
865
+ children: /* @__PURE__ */ jsxs(
866
+ "svg",
867
+ {
868
+ width: "16",
869
+ height: "16",
870
+ viewBox: "0 0 24 24",
871
+ fill: "none",
872
+ stroke: "currentColor",
873
+ strokeWidth: "2",
874
+ strokeLinecap: "round",
875
+ strokeLinejoin: "round",
876
+ children: [
877
+ /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
878
+ /* @__PURE__ */ jsx("path", { d: "M3 3v5h5" }),
879
+ /* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" }),
880
+ /* @__PURE__ */ jsx("path", { d: "M16 16h5v5" })
881
+ ]
882
+ }
883
+ )
884
+ }
885
+ );
886
+ });
887
+ Regenerate.displayName = "FeedbackBar.Regenerate";
888
+
889
+ // src/thinking-block/index.ts
890
+ var thinking_block_exports = {};
891
+ __export(thinking_block_exports, {
892
+ Content: () => Content2,
893
+ Root: () => Root4,
894
+ Trigger: () => Trigger
895
+ });
896
+ var ThinkingBlockContext = createContext(
897
+ null
898
+ );
899
+ function useThinkingBlockContext() {
900
+ const ctx = useContext(ThinkingBlockContext);
901
+ if (!ctx) {
902
+ throw new Error(
903
+ "ThinkingBlock parts must be used within <ThinkingBlock.Root>"
904
+ );
905
+ }
906
+ return ctx;
907
+ }
908
+ var Root4 = forwardRef(
909
+ ({
910
+ state = "thinking",
911
+ defaultOpen = true,
912
+ collapseOnDone = true,
913
+ duration = null,
914
+ children,
915
+ className,
916
+ ...props
917
+ }, ref) => {
918
+ const [isOpen, setIsOpen] = useState(defaultOpen);
919
+ useEffect(() => {
920
+ if (state === "done" && collapseOnDone) {
921
+ const timer = setTimeout(() => setIsOpen(false), 500);
922
+ return () => clearTimeout(timer);
923
+ }
924
+ }, [state, collapseOnDone]);
925
+ const toggle = useCallback(() => setIsOpen((o) => !o), []);
926
+ return /* @__PURE__ */ jsx(ThinkingBlockContext.Provider, { value: { state, isOpen, toggle, duration }, children: /* @__PURE__ */ jsx(
927
+ "div",
928
+ {
929
+ ref,
930
+ "data-state": state,
931
+ "data-open": isOpen,
932
+ className: cn(
933
+ "arclo-thinking-block rounded-xl border border-gray-200 overflow-hidden transition-all",
934
+ state === "thinking" && "border-[var(--arclo-accent,#6C5CE7)]/20 bg-[var(--arclo-accent,#6C5CE7)]/[0.02]",
935
+ state === "done" && "border-gray-200 bg-white",
936
+ state === "error" && "border-red-200 bg-red-50/30",
937
+ className
938
+ ),
939
+ ...props,
940
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
941
+ /* @__PURE__ */ jsx(Trigger, {}),
942
+ /* @__PURE__ */ jsx(Content2, {})
943
+ ] })
944
+ }
945
+ ) });
946
+ }
947
+ );
948
+ Root4.displayName = "ThinkingBlock.Root";
949
+ var Trigger = forwardRef(
950
+ ({ label, className, children, ...props }, ref) => {
951
+ const { state, isOpen, toggle, duration } = useThinkingBlockContext();
952
+ const defaultLabel = state === "thinking" ? "Thinking..." : state === "error" ? "Thinking failed" : duration != null ? `Thought for ${duration}s` : "Thought process";
953
+ return /* @__PURE__ */ jsxs(
954
+ "button",
955
+ {
956
+ ref,
957
+ type: "button",
958
+ onClick: toggle,
959
+ "aria-expanded": isOpen,
960
+ className: cn(
961
+ "arclo-thinking-trigger flex w-full items-center gap-2 px-4 py-3 text-left text-sm transition-colors cursor-pointer hover:bg-gray-50/50",
962
+ className
963
+ ),
964
+ ...props,
965
+ children: [
966
+ state === "thinking" && /* @__PURE__ */ jsx(
967
+ "svg",
968
+ {
969
+ className: "h-4 w-4 shrink-0 animate-spin",
970
+ style: { color: themeVars.accent },
971
+ viewBox: "0 0 24 24",
972
+ fill: "none",
973
+ children: /* @__PURE__ */ jsx(
974
+ "circle",
975
+ {
976
+ cx: "12",
977
+ cy: "12",
978
+ r: "10",
979
+ stroke: "currentColor",
980
+ strokeWidth: "3",
981
+ strokeDasharray: "60",
982
+ strokeDashoffset: "20",
983
+ strokeLinecap: "round"
984
+ }
985
+ )
986
+ }
987
+ ),
988
+ state === "done" && /* @__PURE__ */ jsx(
989
+ "svg",
990
+ {
991
+ className: "h-4 w-4 shrink-0",
992
+ style: { color: themeVars.accent },
993
+ viewBox: "0 0 24 24",
994
+ fill: "none",
995
+ stroke: "currentColor",
996
+ strokeWidth: "2",
997
+ strokeLinecap: "round",
998
+ strokeLinejoin: "round",
999
+ children: /* @__PURE__ */ jsx("path", { d: "m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z" })
1000
+ }
1001
+ ),
1002
+ state === "error" && /* @__PURE__ */ jsxs(
1003
+ "svg",
1004
+ {
1005
+ className: "h-4 w-4 shrink-0 text-red-500",
1006
+ viewBox: "0 0 24 24",
1007
+ fill: "none",
1008
+ stroke: "currentColor",
1009
+ strokeWidth: "2",
1010
+ strokeLinecap: "round",
1011
+ children: [
1012
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
1013
+ /* @__PURE__ */ jsx("path", { d: "m15 9-6 6M9 9l6 6" })
1014
+ ]
1015
+ }
1016
+ ),
1017
+ /* @__PURE__ */ jsx(
1018
+ "span",
1019
+ {
1020
+ className: cn(
1021
+ "flex-1 font-medium",
1022
+ state === "thinking" && "text-[var(--arclo-accent,#6C5CE7)]",
1023
+ state === "done" && "text-gray-500",
1024
+ state === "error" && "text-red-600"
1025
+ ),
1026
+ children: children ?? label ?? defaultLabel
1027
+ }
1028
+ ),
1029
+ /* @__PURE__ */ jsx(
1030
+ "svg",
1031
+ {
1032
+ className: cn(
1033
+ "h-4 w-4 shrink-0 text-gray-400 transition-transform duration-200",
1034
+ isOpen && "rotate-180"
1035
+ ),
1036
+ viewBox: "0 0 24 24",
1037
+ fill: "none",
1038
+ stroke: "currentColor",
1039
+ strokeWidth: "2",
1040
+ strokeLinecap: "round",
1041
+ strokeLinejoin: "round",
1042
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
1043
+ }
1044
+ )
1045
+ ]
1046
+ }
1047
+ );
1048
+ }
1049
+ );
1050
+ Trigger.displayName = "ThinkingBlock.Trigger";
1051
+ var Content2 = forwardRef(
1052
+ ({ children, className, ...props }, ref) => {
1053
+ const { isOpen, state } = useThinkingBlockContext();
1054
+ if (!isOpen) return null;
1055
+ return /* @__PURE__ */ jsx(
1056
+ "div",
1057
+ {
1058
+ ref,
1059
+ className: cn(
1060
+ "arclo-thinking-content border-t border-gray-100 px-4 py-3",
1061
+ className
1062
+ ),
1063
+ ...props,
1064
+ children: children ?? /* @__PURE__ */ jsx(
1065
+ "p",
1066
+ {
1067
+ className: cn(
1068
+ "text-sm leading-relaxed",
1069
+ state === "thinking" ? "text-gray-600 italic" : "text-gray-500"
1070
+ ),
1071
+ children: state === "thinking" ? "Analyzing the request..." : "No content provided."
1072
+ }
1073
+ )
1074
+ }
1075
+ );
1076
+ }
1077
+ );
1078
+ Content2.displayName = "ThinkingBlock.Content";
1079
+
1080
+ // src/tool-call/index.ts
1081
+ var tool_call_exports = {};
1082
+ __export(tool_call_exports, {
1083
+ Header: () => Header,
1084
+ Input: () => Input2,
1085
+ Output: () => Output,
1086
+ Root: () => Root5
1087
+ });
1088
+ var ToolCallContext = createContext(null);
1089
+ function useToolCallContext() {
1090
+ const ctx = useContext(ToolCallContext);
1091
+ if (!ctx) {
1092
+ throw new Error("ToolCall parts must be used within <ToolCall.Root>");
1093
+ }
1094
+ return ctx;
1095
+ }
1096
+ var Root5 = forwardRef(
1097
+ ({
1098
+ toolName,
1099
+ status = "pending",
1100
+ defaultOpen = false,
1101
+ children,
1102
+ className,
1103
+ ...props
1104
+ }, ref) => {
1105
+ const [isOpen, setIsOpen] = useState(defaultOpen);
1106
+ const toggle = useCallback(() => setIsOpen((o) => !o), []);
1107
+ return /* @__PURE__ */ jsx(ToolCallContext.Provider, { value: { status, toolName, isOpen, toggle }, children: /* @__PURE__ */ jsx(
1108
+ "div",
1109
+ {
1110
+ ref,
1111
+ "data-status": status,
1112
+ className: cn(
1113
+ "arclo-tool-call rounded-xl border overflow-hidden transition-all",
1114
+ status === "pending" && "border-gray-200 bg-gray-50/50",
1115
+ status === "running" && "border-blue-200 bg-blue-50/30",
1116
+ status === "success" && "border-emerald-200 bg-emerald-50/30",
1117
+ status === "error" && "border-red-200 bg-red-50/30",
1118
+ className
1119
+ ),
1120
+ ...props,
1121
+ children: children ?? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Header, {}) })
1122
+ }
1123
+ ) });
1124
+ }
1125
+ );
1126
+ Root5.displayName = "ToolCall.Root";
1127
+ var Header = forwardRef(
1128
+ ({ children, className, ...props }, ref) => {
1129
+ const { status, toolName, isOpen, toggle } = useToolCallContext();
1130
+ return /* @__PURE__ */ jsxs(
1131
+ "button",
1132
+ {
1133
+ ref,
1134
+ type: "button",
1135
+ onClick: toggle,
1136
+ "aria-expanded": isOpen,
1137
+ className: cn(
1138
+ "arclo-tool-call-header flex w-full items-center gap-3 px-4 py-3 text-left text-sm cursor-pointer hover:bg-gray-50/50 transition-colors",
1139
+ className
1140
+ ),
1141
+ ...props,
1142
+ children: [
1143
+ /* @__PURE__ */ jsxs("span", { className: "shrink-0", children: [
1144
+ status === "pending" && /* @__PURE__ */ jsx("span", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-gray-200", children: /* @__PURE__ */ jsx("span", { className: "h-2 w-2 rounded-full bg-gray-400" }) }),
1145
+ status === "running" && /* @__PURE__ */ jsx(
1146
+ "svg",
1147
+ {
1148
+ className: "h-5 w-5 animate-spin text-blue-500",
1149
+ viewBox: "0 0 24 24",
1150
+ fill: "none",
1151
+ children: /* @__PURE__ */ jsx(
1152
+ "circle",
1153
+ {
1154
+ cx: "12",
1155
+ cy: "12",
1156
+ r: "10",
1157
+ stroke: "currentColor",
1158
+ strokeWidth: "3",
1159
+ strokeDasharray: "60",
1160
+ strokeDashoffset: "20",
1161
+ strokeLinecap: "round"
1162
+ }
1163
+ )
1164
+ }
1165
+ ),
1166
+ status === "success" && /* @__PURE__ */ jsx("span", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100", children: /* @__PURE__ */ jsx(
1167
+ "svg",
1168
+ {
1169
+ className: "h-3 w-3 text-emerald-600",
1170
+ viewBox: "0 0 24 24",
1171
+ fill: "none",
1172
+ stroke: "currentColor",
1173
+ strokeWidth: "3",
1174
+ strokeLinecap: "round",
1175
+ strokeLinejoin: "round",
1176
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
1177
+ }
1178
+ ) }),
1179
+ status === "error" && /* @__PURE__ */ jsx("span", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-red-100", children: /* @__PURE__ */ jsx(
1180
+ "svg",
1181
+ {
1182
+ className: "h-3 w-3 text-red-600",
1183
+ viewBox: "0 0 24 24",
1184
+ fill: "none",
1185
+ stroke: "currentColor",
1186
+ strokeWidth: "3",
1187
+ strokeLinecap: "round",
1188
+ children: /* @__PURE__ */ jsx("path", { d: "m15 9-6 6M9 9l6 6" })
1189
+ }
1190
+ ) })
1191
+ ] }),
1192
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1193
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1194
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-xs font-semibold text-gray-700 truncate", children: toolName }),
1195
+ /* @__PURE__ */ jsxs(
1196
+ "span",
1197
+ {
1198
+ className: cn(
1199
+ "rounded-full px-2 py-0.5 text-[10px] font-medium",
1200
+ status === "pending" && "bg-gray-100 text-gray-500",
1201
+ status === "running" && "bg-blue-100 text-blue-600",
1202
+ status === "success" && "bg-emerald-100 text-emerald-600",
1203
+ status === "error" && "bg-red-100 text-red-600"
1204
+ ),
1205
+ children: [
1206
+ status === "pending" && "Queued",
1207
+ status === "running" && "Running",
1208
+ status === "success" && "Done",
1209
+ status === "error" && "Failed"
1210
+ ]
1211
+ }
1212
+ )
1213
+ ] }),
1214
+ children
1215
+ ] }),
1216
+ /* @__PURE__ */ jsx(
1217
+ "svg",
1218
+ {
1219
+ className: cn(
1220
+ "h-4 w-4 shrink-0 text-gray-400 transition-transform duration-200",
1221
+ isOpen && "rotate-180"
1222
+ ),
1223
+ viewBox: "0 0 24 24",
1224
+ fill: "none",
1225
+ stroke: "currentColor",
1226
+ strokeWidth: "2",
1227
+ strokeLinecap: "round",
1228
+ strokeLinejoin: "round",
1229
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
1230
+ }
1231
+ )
1232
+ ]
1233
+ }
1234
+ );
1235
+ }
1236
+ );
1237
+ Header.displayName = "ToolCall.Header";
1238
+ var Input2 = forwardRef(
1239
+ ({ label = "Input", children, className, ...props }, ref) => {
1240
+ const { isOpen } = useToolCallContext();
1241
+ if (!isOpen) return null;
1242
+ return /* @__PURE__ */ jsxs(
1243
+ "div",
1244
+ {
1245
+ ref,
1246
+ className: cn(
1247
+ "arclo-tool-call-input border-t border-gray-100 px-4 py-3",
1248
+ className
1249
+ ),
1250
+ ...props,
1251
+ children: [
1252
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-gray-400", children: label }),
1253
+ /* @__PURE__ */ jsx("div", { className: "rounded-lg bg-gray-50 p-3 font-mono text-xs text-gray-600 overflow-x-auto", children })
1254
+ ]
1255
+ }
1256
+ );
1257
+ }
1258
+ );
1259
+ Input2.displayName = "ToolCall.Input";
1260
+ var Output = forwardRef(
1261
+ ({ label = "Output", children, className, ...props }, ref) => {
1262
+ const { isOpen, status } = useToolCallContext();
1263
+ if (!isOpen || status === "pending" || status === "running") return null;
1264
+ return /* @__PURE__ */ jsxs(
1265
+ "div",
1266
+ {
1267
+ ref,
1268
+ className: cn(
1269
+ "arclo-tool-call-output border-t border-gray-100 px-4 py-3",
1270
+ className
1271
+ ),
1272
+ ...props,
1273
+ children: [
1274
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-gray-400", children: label }),
1275
+ /* @__PURE__ */ jsx(
1276
+ "div",
1277
+ {
1278
+ className: cn(
1279
+ "rounded-lg p-3 font-mono text-xs overflow-x-auto",
1280
+ status === "success" && "bg-emerald-50 text-emerald-800",
1281
+ status === "error" && "bg-red-50 text-red-800"
1282
+ ),
1283
+ children
1284
+ }
1285
+ )
1286
+ ]
1287
+ }
1288
+ );
1289
+ }
1290
+ );
1291
+ Output.displayName = "ToolCall.Output";
1292
+
1293
+ // src/chat-thread/index.ts
1294
+ var chat_thread_exports = {};
1295
+ __export(chat_thread_exports, {
1296
+ AssistantMessage: () => AssistantMessage,
1297
+ Message: () => Message,
1298
+ Messages: () => Messages,
1299
+ Root: () => Root6,
1300
+ ScrollAnchor: () => ScrollAnchor,
1301
+ SystemMessage: () => SystemMessage,
1302
+ UserMessage: () => UserMessage
1303
+ });
1304
+ var Root6 = forwardRef(
1305
+ ({ children, className, ...props }, ref) => {
1306
+ return /* @__PURE__ */ jsx(
1307
+ "div",
1308
+ {
1309
+ ref,
1310
+ className: cn("arclo-chat-thread flex flex-col", className),
1311
+ ...props,
1312
+ children
1313
+ }
1314
+ );
1315
+ }
1316
+ );
1317
+ Root6.displayName = "ChatThread.Root";
1318
+ var Messages = forwardRef(
1319
+ ({ children, className, ...props }, ref) => {
1320
+ return /* @__PURE__ */ jsx(
1321
+ "div",
1322
+ {
1323
+ ref,
1324
+ className: cn(
1325
+ "arclo-chat-messages flex-1 overflow-y-auto space-y-4 p-4 [scrollbar-width:thin] [scrollbar-color:theme(colors.gray.300)_transparent] [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-gray-300",
1326
+ className
1327
+ ),
1328
+ ...props,
1329
+ children
1330
+ }
1331
+ );
1332
+ }
1333
+ );
1334
+ Messages.displayName = "ChatThread.Messages";
1335
+ var Message = forwardRef(
1336
+ ({ role, avatar, name, timestamp, children, className, ...props }, ref) => {
1337
+ if (role === "system") {
1338
+ return /* @__PURE__ */ jsx(
1339
+ "div",
1340
+ {
1341
+ ref,
1342
+ "data-role": role,
1343
+ className: cn(
1344
+ "arclo-chat-message flex justify-center",
1345
+ className
1346
+ ),
1347
+ ...props,
1348
+ children: /* @__PURE__ */ jsxs(
1349
+ "div",
1350
+ {
1351
+ className: "max-w-md rounded-lg px-4 py-2 text-center text-xs",
1352
+ style: { color: themeVars.textMuted },
1353
+ children: [
1354
+ (name || timestamp) && /* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center justify-center gap-2", children: [
1355
+ avatar,
1356
+ name && /* @__PURE__ */ jsx("span", { className: "font-medium", children: name }),
1357
+ timestamp && /* @__PURE__ */ jsx("span", { className: "opacity-60", children: timestamp })
1358
+ ] }),
1359
+ /* @__PURE__ */ jsx("div", { children })
1360
+ ]
1361
+ }
1362
+ )
1363
+ }
1364
+ );
1365
+ }
1366
+ const isUser = role === "user";
1367
+ return /* @__PURE__ */ jsxs(
1368
+ "div",
1369
+ {
1370
+ ref,
1371
+ "data-role": role,
1372
+ className: cn(
1373
+ "arclo-chat-message flex gap-3",
1374
+ isUser ? "flex-row-reverse" : "flex-row",
1375
+ className
1376
+ ),
1377
+ ...props,
1378
+ children: [
1379
+ avatar && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 mt-1", children: avatar }),
1380
+ /* @__PURE__ */ jsxs(
1381
+ "div",
1382
+ {
1383
+ className: cn("max-w-[80%] min-w-0", isUser ? "items-end" : "items-start"),
1384
+ children: [
1385
+ (name || timestamp) && /* @__PURE__ */ jsxs(
1386
+ "div",
1387
+ {
1388
+ className: cn(
1389
+ "mb-1 flex items-center gap-2 text-xs",
1390
+ isUser ? "justify-end" : "justify-start"
1391
+ ),
1392
+ style: { color: themeVars.textSecondary },
1393
+ children: [
1394
+ name && /* @__PURE__ */ jsx("span", { className: "font-medium", children: name }),
1395
+ timestamp && /* @__PURE__ */ jsx("span", { className: "opacity-60", children: timestamp })
1396
+ ]
1397
+ }
1398
+ ),
1399
+ /* @__PURE__ */ jsx(
1400
+ "div",
1401
+ {
1402
+ className: cn(
1403
+ "rounded-2xl px-4 py-3 text-sm leading-relaxed",
1404
+ isUser ? "rounded-tr-sm" : "rounded-tl-sm"
1405
+ ),
1406
+ style: isUser ? {
1407
+ backgroundColor: themeVars.accent,
1408
+ color: "#ffffff"
1409
+ } : {
1410
+ backgroundColor: themeVars.surfaceSecondary,
1411
+ color: themeVars.text,
1412
+ border: `1px solid ${themeVars.border}`
1413
+ },
1414
+ children
1415
+ }
1416
+ )
1417
+ ]
1418
+ }
1419
+ )
1420
+ ]
1421
+ }
1422
+ );
1423
+ }
1424
+ );
1425
+ Message.displayName = "ChatThread.Message";
1426
+ var UserMessage = forwardRef(
1427
+ (props, ref) => /* @__PURE__ */ jsx(Message, { ref, role: "user", ...props })
1428
+ );
1429
+ UserMessage.displayName = "ChatThread.UserMessage";
1430
+ var AssistantMessage = forwardRef((props, ref) => /* @__PURE__ */ jsx(Message, { ref, role: "assistant", ...props }));
1431
+ AssistantMessage.displayName = "ChatThread.AssistantMessage";
1432
+ var SystemMessage = forwardRef((props, ref) => /* @__PURE__ */ jsx(Message, { ref, role: "system", ...props }));
1433
+ SystemMessage.displayName = "ChatThread.SystemMessage";
1434
+ var ScrollAnchor = forwardRef(
1435
+ ({ className, ...props }, ref) => {
1436
+ const innerRef = useRef(null);
1437
+ const setRef = (node) => {
1438
+ innerRef.current = node;
1439
+ if (typeof ref === "function") ref(node);
1440
+ else if (ref) ref.current = node;
1441
+ };
1442
+ useEffect(() => {
1443
+ const el = innerRef.current;
1444
+ if (!el) return;
1445
+ const observer = new MutationObserver(() => {
1446
+ el.scrollIntoView({ behavior: "smooth", block: "end" });
1447
+ });
1448
+ const parent = el.parentElement;
1449
+ if (parent) {
1450
+ observer.observe(parent, { childList: true, subtree: true });
1451
+ }
1452
+ return () => observer.disconnect();
1453
+ }, []);
1454
+ return /* @__PURE__ */ jsx(
1455
+ "div",
1456
+ {
1457
+ ref: setRef,
1458
+ "aria-hidden": true,
1459
+ className: cn("arclo-chat-scroll-anchor h-px", className),
1460
+ ...props
1461
+ }
1462
+ );
1463
+ }
1464
+ );
1465
+ ScrollAnchor.displayName = "ChatThread.ScrollAnchor";
1466
+ var levelConfig = {
1467
+ high: {
1468
+ label: "High confidence",
1469
+ classes: "bg-emerald-50 text-emerald-700 border-emerald-200"
1470
+ },
1471
+ medium: {
1472
+ label: "Medium confidence",
1473
+ classes: "bg-amber-50 text-amber-700 border-amber-200"
1474
+ },
1475
+ low: {
1476
+ label: "Low confidence",
1477
+ classes: "bg-red-50 text-red-700 border-red-200"
1478
+ },
1479
+ unknown: {
1480
+ label: "Confidence unknown",
1481
+ classes: "bg-gray-50 text-gray-500 border-gray-200"
1482
+ }
1483
+ };
1484
+ var ConfidenceBadge = forwardRef(
1485
+ ({ level, label, variant = "badge", className, ...props }, ref) => {
1486
+ const config = levelConfig[level];
1487
+ const displayLabel = label ?? config.label;
1488
+ if (variant === "dot") {
1489
+ return /* @__PURE__ */ jsx(
1490
+ "span",
1491
+ {
1492
+ ref,
1493
+ role: "status",
1494
+ "aria-label": displayLabel,
1495
+ title: displayLabel,
1496
+ className: cn(
1497
+ "arclo-confidence-dot inline-block h-2.5 w-2.5 shrink-0 rounded-full",
1498
+ level === "high" && "bg-emerald-500",
1499
+ level === "medium" && "bg-amber-500",
1500
+ level === "low" && "bg-red-500",
1501
+ level === "unknown" && "bg-gray-400",
1502
+ className
1503
+ ),
1504
+ ...props
1505
+ }
1506
+ );
1507
+ }
1508
+ if (variant === "inline") {
1509
+ return /* @__PURE__ */ jsx(
1510
+ "span",
1511
+ {
1512
+ ref,
1513
+ role: "status",
1514
+ className: cn(
1515
+ "arclo-confidence-inline text-xs italic",
1516
+ level === "high" && "text-emerald-600",
1517
+ level === "medium" && "text-amber-600",
1518
+ level === "low" && "text-red-600",
1519
+ level === "unknown" && "text-gray-400",
1520
+ className
1521
+ ),
1522
+ ...props,
1523
+ children: displayLabel
1524
+ }
1525
+ );
1526
+ }
1527
+ return /* @__PURE__ */ jsxs(
1528
+ "span",
1529
+ {
1530
+ ref,
1531
+ role: "status",
1532
+ className: cn(
1533
+ "arclo-confidence-badge inline-flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs font-medium",
1534
+ config.classes,
1535
+ className
1536
+ ),
1537
+ ...props,
1538
+ children: [
1539
+ /* @__PURE__ */ jsx(
1540
+ "span",
1541
+ {
1542
+ className: cn(
1543
+ "h-2 w-2 shrink-0 rounded-full",
1544
+ level === "high" && "bg-emerald-500",
1545
+ level === "medium" && "bg-amber-500",
1546
+ level === "low" && "bg-red-500",
1547
+ level === "unknown" && "bg-gray-400"
1548
+ )
1549
+ }
1550
+ ),
1551
+ displayLabel
1552
+ ]
1553
+ }
1554
+ );
1555
+ }
1556
+ );
1557
+ ConfidenceBadge.displayName = "ConfidenceBadge";
1558
+ var CitationInline = forwardRef(
1559
+ ({
1560
+ index,
1561
+ href,
1562
+ sourceTitle,
1563
+ preview,
1564
+ variant = "superscript",
1565
+ className,
1566
+ ...props
1567
+ }, ref) => {
1568
+ const [showPreview, setShowPreview] = useState(false);
1569
+ const label = variant === "bracket" ? `[${index}]` : `${index}`;
1570
+ const Tag = href ? "a" : "span";
1571
+ const linkProps = href ? { href, target: "_blank", rel: "noopener noreferrer" } : {};
1572
+ return /* @__PURE__ */ jsxs(
1573
+ "span",
1574
+ {
1575
+ ref,
1576
+ className: cn("arclo-citation relative inline-block", className),
1577
+ onMouseEnter: () => setShowPreview(true),
1578
+ onMouseLeave: () => setShowPreview(false),
1579
+ ...props,
1580
+ children: [
1581
+ /* @__PURE__ */ jsx(
1582
+ Tag,
1583
+ {
1584
+ ...linkProps,
1585
+ className: cn(
1586
+ "arclo-citation-trigger transition-colors cursor-pointer",
1587
+ variant === "superscript" && "align-super text-[0.65em] text-blue-600 hover:text-blue-800",
1588
+ variant === "bracket" && "text-sm text-blue-600 hover:text-blue-800",
1589
+ variant === "pill" && "inline-flex h-5 w-5 items-center justify-center rounded-full bg-blue-100 text-[0.6rem] font-medium text-blue-700 hover:bg-blue-200"
1590
+ ),
1591
+ "aria-label": sourceTitle ? `Source: ${sourceTitle}` : `Citation ${index}`,
1592
+ children: label
1593
+ }
1594
+ ),
1595
+ preview && showPreview && /* @__PURE__ */ jsxs(
1596
+ "div",
1597
+ {
1598
+ role: "tooltip",
1599
+ className: "arclo-citation-preview absolute bottom-full left-1/2 z-50 mb-2 w-64 -translate-x-1/2 rounded-lg border border-gray-200 bg-white p-3 text-sm shadow-lg",
1600
+ children: [
1601
+ sourceTitle && /* @__PURE__ */ jsx("p", { className: "mb-1 font-medium text-gray-900", children: sourceTitle }),
1602
+ /* @__PURE__ */ jsx("div", { className: "text-gray-600", children: preview }),
1603
+ href && /* @__PURE__ */ jsx("p", { className: "mt-2 truncate text-xs text-blue-500", children: href }),
1604
+ /* @__PURE__ */ jsx("div", { className: "absolute left-1/2 top-full -translate-x-1/2 border-4 border-transparent border-t-white" })
1605
+ ]
1606
+ }
1607
+ )
1608
+ ]
1609
+ }
1610
+ );
1611
+ }
1612
+ );
1613
+ CitationInline.displayName = "CitationInline";
1614
+ var CitationGroup = forwardRef(
1615
+ ({ children, className, ...props }, ref) => {
1616
+ return /* @__PURE__ */ jsx(
1617
+ "span",
1618
+ {
1619
+ ref,
1620
+ className: cn("arclo-citation-group inline-flex gap-0.5", className),
1621
+ ...props,
1622
+ children
1623
+ }
1624
+ );
1625
+ }
1626
+ );
1627
+ CitationGroup.displayName = "CitationGroup";
1628
+ var typeConfig = {
1629
+ safety: {
1630
+ icon: "\u{1F6E1}",
1631
+ defaultReason: "I can't help with that request for safety reasons.",
1632
+ accent: "border-red-200 bg-red-50"
1633
+ },
1634
+ capability: {
1635
+ icon: "\u26A1",
1636
+ defaultReason: "I'm not able to do that right now.",
1637
+ accent: "border-amber-200 bg-amber-50"
1638
+ },
1639
+ policy: {
1640
+ icon: "\u{1F4CB}",
1641
+ defaultReason: "That request falls outside my usage policy.",
1642
+ accent: "border-orange-200 bg-orange-50"
1643
+ },
1644
+ context: {
1645
+ icon: "\u{1F50D}",
1646
+ defaultReason: "I don't have enough context to help with that.",
1647
+ accent: "border-blue-200 bg-blue-50"
1648
+ }
1649
+ };
1650
+ var RefusalCard = forwardRef(
1651
+ ({
1652
+ reason,
1653
+ type = "capability",
1654
+ suggestions,
1655
+ onSuggestionClick,
1656
+ icon,
1657
+ className,
1658
+ children,
1659
+ ...props
1660
+ }, ref) => {
1661
+ const config = typeConfig[type];
1662
+ const displayReason = reason ?? config.defaultReason;
1663
+ return /* @__PURE__ */ jsx(
1664
+ "div",
1665
+ {
1666
+ ref,
1667
+ role: "alert",
1668
+ "data-refusal-type": type,
1669
+ className: cn(
1670
+ "arclo-refusal-card rounded-lg border p-4",
1671
+ config.accent,
1672
+ className
1673
+ ),
1674
+ ...props,
1675
+ children: /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
1676
+ /* @__PURE__ */ jsx("span", { className: "text-lg", "aria-hidden": true, children: icon ?? config.icon }),
1677
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
1678
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-800", children: displayReason }),
1679
+ children,
1680
+ suggestions && suggestions.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-3", children: [
1681
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-medium text-gray-500", children: "Try instead:" }),
1682
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: suggestions.map((s) => /* @__PURE__ */ jsx(
1683
+ "button",
1684
+ {
1685
+ type: "button",
1686
+ onClick: () => onSuggestionClick?.(s),
1687
+ className: "rounded-full border border-gray-200 bg-white px-3 py-1 text-xs text-gray-600 transition-colors hover:bg-gray-50 cursor-pointer",
1688
+ children: s
1689
+ },
1690
+ s
1691
+ )) })
1692
+ ] })
1693
+ ] })
1694
+ ] })
1695
+ }
1696
+ );
1697
+ }
1698
+ );
1699
+ RefusalCard.displayName = "RefusalCard";
1700
+ function parseMarkdown(text) {
1701
+ const blocks = [];
1702
+ const lines = text.split("\n");
1703
+ let i = 0;
1704
+ while (i < lines.length) {
1705
+ const line = lines[i];
1706
+ if (line.trim() === "") {
1707
+ i++;
1708
+ continue;
1709
+ }
1710
+ if (/^(-{3,}|\*{3,}|_{3,})\s*$/.test(line)) {
1711
+ blocks.push({ type: "hr", content: "" });
1712
+ i++;
1713
+ continue;
1714
+ }
1715
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
1716
+ if (headingMatch) {
1717
+ blocks.push({
1718
+ type: "heading",
1719
+ content: headingMatch[2],
1720
+ level: headingMatch[1].length
1721
+ });
1722
+ i++;
1723
+ continue;
1724
+ }
1725
+ const codeMatch = line.match(/^```(\w*)/);
1726
+ if (codeMatch) {
1727
+ const lang = codeMatch[1] || void 0;
1728
+ const codeLines = [];
1729
+ i++;
1730
+ while (i < lines.length && !lines[i].startsWith("```")) {
1731
+ codeLines.push(lines[i]);
1732
+ i++;
1733
+ }
1734
+ blocks.push({
1735
+ type: "code",
1736
+ content: codeLines.join("\n"),
1737
+ lang
1738
+ });
1739
+ i++;
1740
+ continue;
1741
+ }
1742
+ if (line.startsWith("> ")) {
1743
+ const quoteLines = [];
1744
+ while (i < lines.length && lines[i].startsWith("> ")) {
1745
+ quoteLines.push(lines[i].slice(2));
1746
+ i++;
1747
+ }
1748
+ blocks.push({ type: "blockquote", content: quoteLines.join("\n") });
1749
+ continue;
1750
+ }
1751
+ if (/^[-*+]\s/.test(line)) {
1752
+ const items = [];
1753
+ while (i < lines.length && /^[-*+]\s/.test(lines[i])) {
1754
+ items.push(lines[i].replace(/^[-*+]\s/, ""));
1755
+ i++;
1756
+ }
1757
+ blocks.push({ type: "list", content: "", items, ordered: false });
1758
+ continue;
1759
+ }
1760
+ if (/^\d+\.\s/.test(line)) {
1761
+ const items = [];
1762
+ while (i < lines.length && /^\d+\.\s/.test(lines[i])) {
1763
+ items.push(lines[i].replace(/^\d+\.\s/, ""));
1764
+ i++;
1765
+ }
1766
+ blocks.push({ type: "list", content: "", items, ordered: true });
1767
+ continue;
1768
+ }
1769
+ const paraLines = [];
1770
+ while (i < lines.length && lines[i].trim() !== "" && !lines[i].startsWith("#") && !lines[i].startsWith("```") && !lines[i].startsWith("> ") && !/^[-*+]\s/.test(lines[i]) && !/^\d+\.\s/.test(lines[i]) && !/^(-{3,}|\*{3,}|_{3,})\s*$/.test(lines[i])) {
1771
+ paraLines.push(lines[i]);
1772
+ i++;
1773
+ }
1774
+ if (paraLines.length > 0) {
1775
+ blocks.push({ type: "paragraph", content: paraLines.join("\n") });
1776
+ }
1777
+ }
1778
+ return blocks;
1779
+ }
1780
+ function renderInline(text) {
1781
+ const parts = [];
1782
+ const regex = /(\*\*(.+?)\*\*)|(\*(.+?)\*)|(`(.+?)`)|(\[(.+?)\]\((.+?)\))/g;
1783
+ let lastIndex = 0;
1784
+ let match;
1785
+ while ((match = regex.exec(text)) !== null) {
1786
+ if (match.index > lastIndex) {
1787
+ parts.push(text.slice(lastIndex, match.index));
1788
+ }
1789
+ if (match[1]) {
1790
+ parts.push(
1791
+ /* @__PURE__ */ jsx("strong", { className: "font-semibold", children: match[2] }, match.index)
1792
+ );
1793
+ } else if (match[3]) {
1794
+ parts.push(
1795
+ /* @__PURE__ */ jsx("em", { className: "italic", children: match[4] }, match.index)
1796
+ );
1797
+ } else if (match[5]) {
1798
+ parts.push(
1799
+ /* @__PURE__ */ jsx(
1800
+ "code",
1801
+ {
1802
+ className: "rounded bg-gray-100 px-1.5 py-0.5 text-[0.85em] font-mono text-gray-800",
1803
+ children: match[6]
1804
+ },
1805
+ match.index
1806
+ )
1807
+ );
1808
+ } else if (match[7]) {
1809
+ parts.push(
1810
+ /* @__PURE__ */ jsx(
1811
+ "a",
1812
+ {
1813
+ href: match[9],
1814
+ target: "_blank",
1815
+ rel: "noopener noreferrer",
1816
+ className: "text-[#6C5CE7] underline underline-offset-2 hover:text-[#5A4BD1]",
1817
+ children: match[8]
1818
+ },
1819
+ match.index
1820
+ )
1821
+ );
1822
+ }
1823
+ lastIndex = match.index + match[0].length;
1824
+ }
1825
+ if (lastIndex < text.length) {
1826
+ parts.push(text.slice(lastIndex));
1827
+ }
1828
+ return parts.length > 0 ? parts : [text];
1829
+ }
1830
+ var MarkdownRenderer = forwardRef(({ content, renderCode, className, ...props }, ref) => {
1831
+ const blocks = useMemo(() => parseMarkdown(content), [content]);
1832
+ return /* @__PURE__ */ jsx(
1833
+ "div",
1834
+ {
1835
+ ref,
1836
+ className: cn(
1837
+ "arclo-markdown space-y-4 text-sm leading-relaxed text-gray-700",
1838
+ className
1839
+ ),
1840
+ ...props,
1841
+ children: blocks.map((block, i) => {
1842
+ switch (block.type) {
1843
+ case "heading": {
1844
+ const Tag = `h${block.level}`;
1845
+ return /* @__PURE__ */ jsx(
1846
+ Tag,
1847
+ {
1848
+ className: cn(
1849
+ "font-semibold text-gray-900",
1850
+ block.level === 1 && "text-2xl",
1851
+ block.level === 2 && "text-xl",
1852
+ block.level === 3 && "text-lg",
1853
+ (block.level ?? 4) >= 4 && "text-base"
1854
+ ),
1855
+ children: renderInline(block.content)
1856
+ },
1857
+ i
1858
+ );
1859
+ }
1860
+ case "paragraph":
1861
+ return /* @__PURE__ */ jsx("p", { children: renderInline(block.content) }, i);
1862
+ case "code":
1863
+ if (renderCode) {
1864
+ return /* @__PURE__ */ jsx("div", { children: renderCode(block.content, block.lang) }, i);
1865
+ }
1866
+ return /* @__PURE__ */ jsxs(
1867
+ "div",
1868
+ {
1869
+ className: "overflow-hidden rounded-xl border border-gray-200 bg-gray-50",
1870
+ children: [
1871
+ block.lang && /* @__PURE__ */ jsx("div", { className: "border-b border-gray-200 bg-gray-50 px-4 py-1.5 text-[11px] font-medium uppercase tracking-wider text-gray-400", children: block.lang }),
1872
+ /* @__PURE__ */ jsx("pre", { className: "overflow-x-auto p-4 text-[13px] leading-relaxed", children: /* @__PURE__ */ jsx("code", { className: "font-mono text-gray-800", children: block.content }) })
1873
+ ]
1874
+ },
1875
+ i
1876
+ );
1877
+ case "list": {
1878
+ const Tag = block.ordered ? "ol" : "ul";
1879
+ return /* @__PURE__ */ jsx(
1880
+ Tag,
1881
+ {
1882
+ className: cn(
1883
+ "space-y-1 pl-6",
1884
+ block.ordered ? "list-decimal" : "list-disc"
1885
+ ),
1886
+ children: block.items?.map((item, j) => /* @__PURE__ */ jsx("li", { className: "text-gray-700", children: renderInline(item) }, j))
1887
+ },
1888
+ i
1889
+ );
1890
+ }
1891
+ case "blockquote":
1892
+ return /* @__PURE__ */ jsx(
1893
+ "blockquote",
1894
+ {
1895
+ className: "border-l-3 border-gray-300 pl-4 text-gray-500 italic",
1896
+ children: renderInline(block.content)
1897
+ },
1898
+ i
1899
+ );
1900
+ case "hr":
1901
+ return /* @__PURE__ */ jsx("hr", { className: "border-gray-200" }, i);
1902
+ default:
1903
+ return null;
1904
+ }
1905
+ })
1906
+ }
1907
+ );
1908
+ });
1909
+ MarkdownRenderer.displayName = "MarkdownRenderer";
1910
+ var stateDefaults = {
1911
+ idle: { label: "Ready", colorKey: "gray" },
1912
+ thinking: { label: "Thinking...", colorKey: "amber" },
1913
+ streaming: { label: "Writing...", colorKey: "purple" },
1914
+ "tool-calling": { label: "Using tools...", colorKey: "blue" },
1915
+ error: { label: "Error", colorKey: "red" }
1916
+ };
1917
+ var colorMap = {
1918
+ purple: { base: themeVars.accent, bright: "var(--arclo-accent-bright, rgb(167,139,250))" },
1919
+ amber: { base: "rgb(217,119,6)", bright: "rgb(251,191,36)" },
1920
+ blue: { base: "rgb(37,99,235)", bright: "rgb(96,165,250)" },
1921
+ red: { base: "rgb(239,68,68)", bright: "rgb(252,129,129)" },
1922
+ gray: { base: "rgb(156,163,175)", bright: "rgb(209,213,219)" }
1923
+ };
1924
+ var StatusIndicator = forwardRef(
1925
+ ({
1926
+ state = "idle",
1927
+ label,
1928
+ icon,
1929
+ color,
1930
+ animation = "sweep",
1931
+ className,
1932
+ ...props
1933
+ }, ref) => {
1934
+ const id = useId().replace(/:/g, "");
1935
+ const defaults = stateDefaults[state];
1936
+ const resolvedColor = color ?? defaults.colorKey;
1937
+ const colors = colorMap[resolvedColor] ?? colorMap.gray;
1938
+ const displayLabel = label ?? defaults.label;
1939
+ const isActive = state !== "idle" && state !== "error";
1940
+ return /* @__PURE__ */ jsxs(
1941
+ "span",
1942
+ {
1943
+ ref,
1944
+ "data-state": state,
1945
+ className: cn(
1946
+ "arclo-status-indicator inline-flex items-center gap-1.5 text-sm font-medium",
1947
+ className
1948
+ ),
1949
+ style: { color: colors.base },
1950
+ ...props,
1951
+ children: [
1952
+ /* @__PURE__ */ jsx(
1953
+ "style",
1954
+ {
1955
+ dangerouslySetInnerHTML: {
1956
+ __html: `
1957
+ @keyframes arclo-sweep-${id} {
1958
+ 0%, 100% { color: ${colors.base}; opacity: 0.5; }
1959
+ 50% { color: ${colors.bright}; opacity: 1; }
1960
+ }
1961
+ @keyframes arclo-pulse-${id} {
1962
+ 0%, 100% { opacity: 1; }
1963
+ 50% { opacity: 0.4; }
1964
+ }
1965
+ @keyframes arclo-spin-${id} {
1966
+ from { transform: rotate(0deg); }
1967
+ to { transform: rotate(360deg); }
1968
+ }`
1969
+ }
1970
+ }
1971
+ ),
1972
+ /* @__PURE__ */ jsx("span", { className: "shrink-0", children: icon ?? /* @__PURE__ */ jsx(
1973
+ "svg",
1974
+ {
1975
+ width: "14",
1976
+ height: "14",
1977
+ viewBox: "0 0 24 24",
1978
+ fill: "currentColor",
1979
+ style: isActive ? { animation: `arclo-spin-${id} 3s linear infinite` } : void 0,
1980
+ children: /* @__PURE__ */ jsx("path", { d: "M12 2l2.4 7.2H22l-6 4.8 2.4 7.2L12 16.4 5.6 21.2 8 14 2 9.2h7.6L12 2z" })
1981
+ }
1982
+ ) }),
1983
+ isActive && animation === "sweep" ? /* @__PURE__ */ jsx("span", { "aria-label": displayLabel, children: displayLabel.split("").map((char, i) => /* @__PURE__ */ jsx(
1984
+ "span",
1985
+ {
1986
+ style: {
1987
+ display: "inline-block",
1988
+ animation: `arclo-sweep-${id} 1.5s ease-in-out infinite`,
1989
+ animationDelay: `${i * 0.08}s`
1990
+ },
1991
+ children: char === " " ? "\xA0" : char
1992
+ },
1993
+ i
1994
+ )) }) : /* @__PURE__ */ jsx(
1995
+ "span",
1996
+ {
1997
+ style: isActive && animation === "pulse" ? {
1998
+ animation: `arclo-pulse-${id} 1.5s ease-in-out infinite`
1999
+ } : void 0,
2000
+ children: displayLabel
2001
+ }
2002
+ )
2003
+ ]
2004
+ }
2005
+ );
2006
+ }
2007
+ );
2008
+ StatusIndicator.displayName = "StatusIndicator";
2009
+ function formatNumber(n) {
2010
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
2011
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
2012
+ return n.toLocaleString();
2013
+ }
2014
+ var TokenUsage = forwardRef(
2015
+ ({ inputTokens, outputTokens, maxTokens, cost, className, ...props }, ref) => {
2016
+ const total = inputTokens + outputTokens;
2017
+ const inputPct = maxTokens > 0 ? inputTokens / maxTokens * 100 : 0;
2018
+ const outputPct = maxTokens > 0 ? outputTokens / maxTokens * 100 : 0;
2019
+ const totalPct = Math.min(inputPct + outputPct, 100);
2020
+ const isHigh = totalPct > 80;
2021
+ const isMedium = totalPct > 50 && totalPct <= 80;
2022
+ return /* @__PURE__ */ jsxs(
2023
+ "div",
2024
+ {
2025
+ ref,
2026
+ className: cn(
2027
+ "arclo-token-usage rounded-lg border border-gray-200 bg-white p-4",
2028
+ className
2029
+ ),
2030
+ ...props,
2031
+ children: [
2032
+ /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between text-xs text-gray-500", children: [
2033
+ /* @__PURE__ */ jsxs("span", { className: "font-medium text-gray-700", children: [
2034
+ formatNumber(total),
2035
+ " ",
2036
+ /* @__PURE__ */ jsxs("span", { className: "font-normal text-gray-400", children: [
2037
+ "/ ",
2038
+ formatNumber(maxTokens),
2039
+ " tokens"
2040
+ ] })
2041
+ ] }),
2042
+ cost != null && /* @__PURE__ */ jsxs("span", { className: "font-medium text-gray-600", children: [
2043
+ "$",
2044
+ cost.toFixed(4)
2045
+ ] })
2046
+ ] }),
2047
+ /* @__PURE__ */ jsxs("div", { className: "relative h-2.5 w-full overflow-hidden rounded-full bg-gray-100", children: [
2048
+ /* @__PURE__ */ jsx(
2049
+ "div",
2050
+ {
2051
+ className: cn(
2052
+ "absolute inset-y-0 left-0 rounded-l-full transition-all duration-300",
2053
+ isHigh ? "bg-red-400" : isMedium ? "bg-amber-400" : "bg-blue-400"
2054
+ ),
2055
+ style: { width: `${Math.min(inputPct, 100)}%` }
2056
+ }
2057
+ ),
2058
+ /* @__PURE__ */ jsx(
2059
+ "div",
2060
+ {
2061
+ className: cn(
2062
+ "absolute inset-y-0 transition-all duration-300",
2063
+ isHigh ? "bg-red-300" : isMedium ? "bg-amber-300" : "bg-violet-400",
2064
+ outputPct > 0 && inputPct + outputPct >= 100 && "rounded-r-full"
2065
+ ),
2066
+ style: {
2067
+ left: `${Math.min(inputPct, 100)}%`,
2068
+ width: `${Math.min(outputPct, 100 - Math.min(inputPct, 100))}%`
2069
+ }
2070
+ }
2071
+ )
2072
+ ] }),
2073
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-4 text-[11px] text-gray-500", children: [
2074
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
2075
+ /* @__PURE__ */ jsx(
2076
+ "span",
2077
+ {
2078
+ className: cn(
2079
+ "inline-block h-2 w-2 rounded-full",
2080
+ isHigh ? "bg-red-400" : isMedium ? "bg-amber-400" : "bg-blue-400"
2081
+ )
2082
+ }
2083
+ ),
2084
+ "Input: ",
2085
+ formatNumber(inputTokens)
2086
+ ] }),
2087
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
2088
+ /* @__PURE__ */ jsx(
2089
+ "span",
2090
+ {
2091
+ className: cn(
2092
+ "inline-block h-2 w-2 rounded-full",
2093
+ isHigh ? "bg-red-300" : isMedium ? "bg-amber-300" : "bg-violet-400"
2094
+ )
2095
+ }
2096
+ ),
2097
+ "Output: ",
2098
+ formatNumber(outputTokens)
2099
+ ] })
2100
+ ] })
2101
+ ]
2102
+ }
2103
+ );
2104
+ }
2105
+ );
2106
+ TokenUsage.displayName = "TokenUsage";
2107
+ var ModelSelector = forwardRef(
2108
+ ({ models, value, onChange, className, ...props }, ref) => {
2109
+ const [open, setOpen] = useState(false);
2110
+ const containerRef = useRef(null);
2111
+ const selected = models.find((m) => m.id === value);
2112
+ useEffect(() => {
2113
+ if (!open) return;
2114
+ function handleClick(e) {
2115
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
2116
+ setOpen(false);
2117
+ }
2118
+ }
2119
+ document.addEventListener("mousedown", handleClick);
2120
+ return () => document.removeEventListener("mousedown", handleClick);
2121
+ }, [open]);
2122
+ useEffect(() => {
2123
+ if (!open) return;
2124
+ function handleKey(e) {
2125
+ if (e.key === "Escape") setOpen(false);
2126
+ }
2127
+ document.addEventListener("keydown", handleKey);
2128
+ return () => document.removeEventListener("keydown", handleKey);
2129
+ }, [open]);
2130
+ return /* @__PURE__ */ jsx(
2131
+ "div",
2132
+ {
2133
+ ref,
2134
+ className: cn("arclo-model-selector relative inline-block", className),
2135
+ ...props,
2136
+ children: /* @__PURE__ */ jsxs("div", { ref: containerRef, children: [
2137
+ /* @__PURE__ */ jsxs(
2138
+ "button",
2139
+ {
2140
+ type: "button",
2141
+ onClick: () => setOpen((o) => !o),
2142
+ "aria-expanded": open,
2143
+ "aria-haspopup": "listbox",
2144
+ className: "cursor-pointer inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50",
2145
+ children: [
2146
+ /* @__PURE__ */ jsx(
2147
+ "svg",
2148
+ {
2149
+ width: "14",
2150
+ height: "14",
2151
+ viewBox: "0 0 24 24",
2152
+ fill: "none",
2153
+ stroke: "currentColor",
2154
+ strokeWidth: "2",
2155
+ strokeLinecap: "round",
2156
+ strokeLinejoin: "round",
2157
+ className: "shrink-0 text-gray-400",
2158
+ children: /* @__PURE__ */ jsx("path", { d: "M12 2l2.4 7.2H22l-6 4.8 2.4 7.2L12 16.4 5.6 21.2 8 14 2 9.2h7.6L12 2z" })
2159
+ }
2160
+ ),
2161
+ /* @__PURE__ */ jsx("span", { children: selected?.name ?? value }),
2162
+ selected?.badge && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-[#6C5CE7]/10 px-2 py-0.5 text-[10px] font-semibold text-[#6C5CE7]", children: selected.badge }),
2163
+ /* @__PURE__ */ jsx(
2164
+ "svg",
2165
+ {
2166
+ width: "12",
2167
+ height: "12",
2168
+ viewBox: "0 0 24 24",
2169
+ fill: "none",
2170
+ stroke: "currentColor",
2171
+ strokeWidth: "2",
2172
+ strokeLinecap: "round",
2173
+ strokeLinejoin: "round",
2174
+ className: cn(
2175
+ "shrink-0 text-gray-400 transition-transform",
2176
+ open && "rotate-180"
2177
+ ),
2178
+ children: /* @__PURE__ */ jsx("polyline", { points: "6 9 12 15 18 9" })
2179
+ }
2180
+ )
2181
+ ]
2182
+ }
2183
+ ),
2184
+ open && /* @__PURE__ */ jsx(
2185
+ "div",
2186
+ {
2187
+ role: "listbox",
2188
+ className: "absolute left-0 z-50 mt-1 w-72 overflow-hidden rounded-xl border border-gray-200 bg-white shadow-lg",
2189
+ children: models.map((model) => {
2190
+ const isSelected = model.id === value;
2191
+ return /* @__PURE__ */ jsxs(
2192
+ "button",
2193
+ {
2194
+ type: "button",
2195
+ role: "option",
2196
+ "aria-selected": isSelected,
2197
+ onClick: () => {
2198
+ onChange(model.id);
2199
+ setOpen(false);
2200
+ },
2201
+ className: cn(
2202
+ "cursor-pointer flex w-full items-start gap-3 px-4 py-3 text-left transition-colors hover:bg-gray-50",
2203
+ isSelected && "bg-gray-50"
2204
+ ),
2205
+ children: [
2206
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
2207
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2208
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-800", children: model.name }),
2209
+ model.badge && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-[#6C5CE7]/10 px-2 py-0.5 text-[10px] font-semibold text-[#6C5CE7]", children: model.badge })
2210
+ ] }),
2211
+ model.description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-gray-400 truncate", children: model.description })
2212
+ ] }),
2213
+ isSelected && /* @__PURE__ */ jsx(
2214
+ "svg",
2215
+ {
2216
+ width: "16",
2217
+ height: "16",
2218
+ viewBox: "0 0 24 24",
2219
+ fill: "none",
2220
+ stroke: "currentColor",
2221
+ strokeWidth: "2",
2222
+ strokeLinecap: "round",
2223
+ strokeLinejoin: "round",
2224
+ className: "mt-0.5 shrink-0 text-[#6C5CE7]",
2225
+ children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
2226
+ }
2227
+ )
2228
+ ]
2229
+ },
2230
+ model.id
2231
+ );
2232
+ })
2233
+ }
2234
+ )
2235
+ ] })
2236
+ }
2237
+ );
2238
+ }
2239
+ );
2240
+ ModelSelector.displayName = "ModelSelector";
2241
+ function relevanceColor(score) {
2242
+ if (score >= 0.8) return { bar: "bg-emerald-400", text: "text-emerald-600" };
2243
+ if (score >= 0.5) return { bar: "bg-amber-400", text: "text-amber-600" };
2244
+ return { bar: "bg-red-400", text: "text-red-600" };
2245
+ }
2246
+ function relevanceLabel(score) {
2247
+ if (score >= 0.8) return "High";
2248
+ if (score >= 0.5) return "Medium";
2249
+ return "Low";
2250
+ }
2251
+ var SourceCard = forwardRef(
2252
+ ({ title, url, content, relevance, variant = "full", className, ...props }, ref) => {
2253
+ const colors = relevanceColor(relevance);
2254
+ const pct = Math.round(relevance * 100);
2255
+ if (variant === "compact") {
2256
+ return /* @__PURE__ */ jsxs(
2257
+ "div",
2258
+ {
2259
+ ref,
2260
+ "data-variant": "compact",
2261
+ className: cn(
2262
+ "arclo-source-card flex items-start gap-3 rounded-lg border border-gray-200 bg-white px-3 py-2.5",
2263
+ className
2264
+ ),
2265
+ ...props,
2266
+ children: [
2267
+ /* @__PURE__ */ jsx(
2268
+ "span",
2269
+ {
2270
+ className: cn("mt-1 inline-block h-2 w-2 shrink-0 rounded-full", colors.bar),
2271
+ title: `${pct}% relevance`
2272
+ }
2273
+ ),
2274
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
2275
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2276
+ url ? /* @__PURE__ */ jsx(
2277
+ "a",
2278
+ {
2279
+ href: url,
2280
+ target: "_blank",
2281
+ rel: "noopener noreferrer",
2282
+ className: "truncate text-sm font-medium text-gray-800 hover:text-[#6C5CE7] hover:underline",
2283
+ children: title
2284
+ }
2285
+ ) : /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium text-gray-800", children: title }),
2286
+ /* @__PURE__ */ jsxs("span", { className: cn("shrink-0 text-[10px] font-semibold", colors.text), children: [
2287
+ pct,
2288
+ "%"
2289
+ ] })
2290
+ ] }),
2291
+ /* @__PURE__ */ jsx("p", { className: "mt-0.5 truncate text-xs text-gray-400", children: content })
2292
+ ] })
2293
+ ]
2294
+ }
2295
+ );
2296
+ }
2297
+ return /* @__PURE__ */ jsxs(
2298
+ "div",
2299
+ {
2300
+ ref,
2301
+ "data-variant": "full",
2302
+ className: cn(
2303
+ "arclo-source-card overflow-hidden rounded-lg border border-gray-200 bg-white",
2304
+ className
2305
+ ),
2306
+ ...props,
2307
+ children: [
2308
+ /* @__PURE__ */ jsx("div", { className: "relative h-1.5 w-full bg-gray-100", children: /* @__PURE__ */ jsx(
2309
+ "div",
2310
+ {
2311
+ className: cn("absolute inset-y-0 left-0 transition-all duration-300", colors.bar),
2312
+ style: { width: `${pct}%` }
2313
+ }
2314
+ ) }),
2315
+ /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
2316
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
2317
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
2318
+ url ? /* @__PURE__ */ jsx(
2319
+ "a",
2320
+ {
2321
+ href: url,
2322
+ target: "_blank",
2323
+ rel: "noopener noreferrer",
2324
+ className: "text-sm font-medium text-gray-800 hover:text-[#6C5CE7] hover:underline",
2325
+ children: title
2326
+ }
2327
+ ) : /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-800", children: title }),
2328
+ url && /* @__PURE__ */ jsx("p", { className: "mt-0.5 truncate text-xs text-gray-400", children: url })
2329
+ ] }),
2330
+ /* @__PURE__ */ jsxs(
2331
+ "span",
2332
+ {
2333
+ className: cn(
2334
+ "shrink-0 rounded-full border px-2 py-0.5 text-[10px] font-semibold",
2335
+ relevance >= 0.8 && "border-emerald-200 bg-emerald-50 text-emerald-700",
2336
+ relevance >= 0.5 && relevance < 0.8 && "border-amber-200 bg-amber-50 text-amber-700",
2337
+ relevance < 0.5 && "border-red-200 bg-red-50 text-red-700"
2338
+ ),
2339
+ children: [
2340
+ relevanceLabel(relevance),
2341
+ " ",
2342
+ pct,
2343
+ "%"
2344
+ ]
2345
+ }
2346
+ )
2347
+ ] }),
2348
+ /* @__PURE__ */ jsx("p", { className: "mt-2 line-clamp-3 text-sm leading-relaxed text-gray-500", children: content })
2349
+ ] })
2350
+ ]
2351
+ }
2352
+ );
2353
+ }
2354
+ );
2355
+ SourceCard.displayName = "SourceCard";
2356
+ function FileIcon({
2357
+ type,
2358
+ className
2359
+ }) {
2360
+ const base = cn("shrink-0", className);
2361
+ if (type === "image") {
2362
+ return /* @__PURE__ */ jsxs(
2363
+ "svg",
2364
+ {
2365
+ className: base,
2366
+ viewBox: "0 0 24 24",
2367
+ fill: "none",
2368
+ stroke: "currentColor",
2369
+ strokeWidth: "1.5",
2370
+ strokeLinecap: "round",
2371
+ strokeLinejoin: "round",
2372
+ children: [
2373
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
2374
+ /* @__PURE__ */ jsx("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
2375
+ /* @__PURE__ */ jsx("path", { d: "m21 15-5-5L5 21" })
2376
+ ]
2377
+ }
2378
+ );
2379
+ }
2380
+ if (type === "pdf") {
2381
+ return /* @__PURE__ */ jsxs(
2382
+ "svg",
2383
+ {
2384
+ className: base,
2385
+ viewBox: "0 0 24 24",
2386
+ fill: "none",
2387
+ stroke: "currentColor",
2388
+ strokeWidth: "1.5",
2389
+ strokeLinecap: "round",
2390
+ strokeLinejoin: "round",
2391
+ children: [
2392
+ /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" }),
2393
+ /* @__PURE__ */ jsx("path", { d: "M14 2v6h6" }),
2394
+ /* @__PURE__ */ jsx("path", { d: "M9 15v-1h2a1 1 0 0 1 0 2H9" })
2395
+ ]
2396
+ }
2397
+ );
2398
+ }
2399
+ if (type === "code") {
2400
+ return /* @__PURE__ */ jsxs(
2401
+ "svg",
2402
+ {
2403
+ className: base,
2404
+ viewBox: "0 0 24 24",
2405
+ fill: "none",
2406
+ stroke: "currentColor",
2407
+ strokeWidth: "1.5",
2408
+ strokeLinecap: "round",
2409
+ strokeLinejoin: "round",
2410
+ children: [
2411
+ /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" }),
2412
+ /* @__PURE__ */ jsx("path", { d: "M14 2v6h6" }),
2413
+ /* @__PURE__ */ jsx("path", { d: "m10 13-2 2 2 2" }),
2414
+ /* @__PURE__ */ jsx("path", { d: "m14 17 2-2-2-2" })
2415
+ ]
2416
+ }
2417
+ );
2418
+ }
2419
+ if (type === "csv") {
2420
+ return /* @__PURE__ */ jsxs(
2421
+ "svg",
2422
+ {
2423
+ className: base,
2424
+ viewBox: "0 0 24 24",
2425
+ fill: "none",
2426
+ stroke: "currentColor",
2427
+ strokeWidth: "1.5",
2428
+ strokeLinecap: "round",
2429
+ strokeLinejoin: "round",
2430
+ children: [
2431
+ /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" }),
2432
+ /* @__PURE__ */ jsx("path", { d: "M14 2v6h6" }),
2433
+ /* @__PURE__ */ jsx("path", { d: "M8 15h8" }),
2434
+ /* @__PURE__ */ jsx("path", { d: "M8 11h8" }),
2435
+ /* @__PURE__ */ jsx("path", { d: "M12 11v8" })
2436
+ ]
2437
+ }
2438
+ );
2439
+ }
2440
+ if (type === "text") {
2441
+ return /* @__PURE__ */ jsxs(
2442
+ "svg",
2443
+ {
2444
+ className: base,
2445
+ viewBox: "0 0 24 24",
2446
+ fill: "none",
2447
+ stroke: "currentColor",
2448
+ strokeWidth: "1.5",
2449
+ strokeLinecap: "round",
2450
+ strokeLinejoin: "round",
2451
+ children: [
2452
+ /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" }),
2453
+ /* @__PURE__ */ jsx("path", { d: "M14 2v6h6" }),
2454
+ /* @__PURE__ */ jsx("path", { d: "M16 13H8" }),
2455
+ /* @__PURE__ */ jsx("path", { d: "M16 17H8" }),
2456
+ /* @__PURE__ */ jsx("path", { d: "M10 9H8" })
2457
+ ]
2458
+ }
2459
+ );
2460
+ }
2461
+ return /* @__PURE__ */ jsxs(
2462
+ "svg",
2463
+ {
2464
+ className: base,
2465
+ viewBox: "0 0 24 24",
2466
+ fill: "none",
2467
+ stroke: "currentColor",
2468
+ strokeWidth: "1.5",
2469
+ strokeLinecap: "round",
2470
+ strokeLinejoin: "round",
2471
+ children: [
2472
+ /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" }),
2473
+ /* @__PURE__ */ jsx("path", { d: "M14 2v6h6" })
2474
+ ]
2475
+ }
2476
+ );
2477
+ }
2478
+ var FileAttachment = forwardRef(
2479
+ ({
2480
+ name,
2481
+ size,
2482
+ type = "other",
2483
+ preview,
2484
+ progress,
2485
+ onRemove,
2486
+ variant = "chip",
2487
+ className,
2488
+ ...props
2489
+ }, ref) => {
2490
+ if (variant === "card") {
2491
+ return /* @__PURE__ */ jsxs(
2492
+ "div",
2493
+ {
2494
+ ref,
2495
+ className: cn(
2496
+ "arclo-file-attachment-card group relative inline-flex w-48 flex-col overflow-hidden rounded-xl border border-gray-200 bg-white",
2497
+ className
2498
+ ),
2499
+ ...props,
2500
+ children: [
2501
+ /* @__PURE__ */ jsxs("div", { className: "relative flex h-28 items-center justify-center bg-gray-50", children: [
2502
+ preview ? /* @__PURE__ */ jsx(
2503
+ "img",
2504
+ {
2505
+ src: preview,
2506
+ alt: name,
2507
+ className: "h-full w-full object-cover"
2508
+ }
2509
+ ) : /* @__PURE__ */ jsx(FileIcon, { type, className: "h-10 w-10 text-gray-300" }),
2510
+ onRemove && /* @__PURE__ */ jsx(
2511
+ "button",
2512
+ {
2513
+ type: "button",
2514
+ onClick: onRemove,
2515
+ "aria-label": `Remove ${name}`,
2516
+ className: "absolute right-1.5 top-1.5 flex h-6 w-6 items-center justify-center rounded-full bg-black/50 text-white opacity-0 transition-opacity hover:bg-black/70 group-hover:opacity-100 cursor-pointer",
2517
+ children: /* @__PURE__ */ jsx(
2518
+ "svg",
2519
+ {
2520
+ className: "h-3 w-3",
2521
+ viewBox: "0 0 24 24",
2522
+ fill: "none",
2523
+ stroke: "currentColor",
2524
+ strokeWidth: "2.5",
2525
+ strokeLinecap: "round",
2526
+ children: /* @__PURE__ */ jsx("path", { d: "m18 6-12 12M6 6l12 12" })
2527
+ }
2528
+ )
2529
+ }
2530
+ )
2531
+ ] }),
2532
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 px-3 py-2", children: [
2533
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs font-medium text-gray-700", children: name }),
2534
+ size && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400", children: size })
2535
+ ] }),
2536
+ progress != null && /* @__PURE__ */ jsx("div", { className: "h-1 w-full bg-gray-100", children: /* @__PURE__ */ jsx(
2537
+ "div",
2538
+ {
2539
+ className: "h-full rounded-r-full bg-[#6C5CE7] transition-all duration-300",
2540
+ style: { width: `${Math.min(100, Math.max(0, progress))}%` }
2541
+ }
2542
+ ) })
2543
+ ]
2544
+ }
2545
+ );
2546
+ }
2547
+ return /* @__PURE__ */ jsxs(
2548
+ "div",
2549
+ {
2550
+ ref,
2551
+ className: cn(
2552
+ "arclo-file-attachment-chip group inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 py-2",
2553
+ className
2554
+ ),
2555
+ ...props,
2556
+ children: [
2557
+ /* @__PURE__ */ jsx(FileIcon, { type, className: "h-4 w-4 text-gray-400" }),
2558
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col", children: [
2559
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs font-medium text-gray-700", children: name }),
2560
+ (size || progress != null) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2561
+ size && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400", children: size }),
2562
+ progress != null && /* @__PURE__ */ jsx("div", { className: "h-1 w-16 rounded-full bg-gray-100", children: /* @__PURE__ */ jsx(
2563
+ "div",
2564
+ {
2565
+ className: "h-full rounded-full bg-[#6C5CE7] transition-all duration-300",
2566
+ style: {
2567
+ width: `${Math.min(100, Math.max(0, progress))}%`
2568
+ }
2569
+ }
2570
+ ) })
2571
+ ] })
2572
+ ] }),
2573
+ onRemove && /* @__PURE__ */ jsx(
2574
+ "button",
2575
+ {
2576
+ type: "button",
2577
+ onClick: onRemove,
2578
+ "aria-label": `Remove ${name}`,
2579
+ className: "ml-1 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-gray-300 transition-colors hover:bg-gray-100 hover:text-gray-500 cursor-pointer",
2580
+ children: /* @__PURE__ */ jsx(
2581
+ "svg",
2582
+ {
2583
+ className: "h-3 w-3",
2584
+ viewBox: "0 0 24 24",
2585
+ fill: "none",
2586
+ stroke: "currentColor",
2587
+ strokeWidth: "2.5",
2588
+ strokeLinecap: "round",
2589
+ children: /* @__PURE__ */ jsx("path", { d: "m18 6-12 12M6 6l12 12" })
2590
+ }
2591
+ )
2592
+ }
2593
+ )
2594
+ ]
2595
+ }
2596
+ );
2597
+ }
2598
+ );
2599
+ FileAttachment.displayName = "FileAttachment";
2600
+ var CodeBlock = forwardRef(
2601
+ ({
2602
+ code,
2603
+ language,
2604
+ showLineNumbers = false,
2605
+ maxHeight = "400px",
2606
+ onCopy,
2607
+ className,
2608
+ ...props
2609
+ }, ref) => {
2610
+ const [copied, setCopied] = useState(false);
2611
+ const handleCopy = useCallback(() => {
2612
+ navigator.clipboard.writeText(code).then(() => {
2613
+ setCopied(true);
2614
+ onCopy?.();
2615
+ setTimeout(() => setCopied(false), 2e3);
2616
+ });
2617
+ }, [code, onCopy]);
2618
+ const lines = code.split("\n");
2619
+ return /* @__PURE__ */ jsxs(
2620
+ "div",
2621
+ {
2622
+ ref,
2623
+ className: cn(
2624
+ "arclo-code-block overflow-hidden rounded-xl border",
2625
+ className
2626
+ ),
2627
+ style: { backgroundColor: "#1e1e2e", borderColor: "#313244" },
2628
+ ...props,
2629
+ children: [
2630
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2", style: { borderBottom: "1px solid #313244" }, children: [
2631
+ /* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium uppercase tracking-wider", style: { color: "#a6adc8" }, children: language ?? "code" }),
2632
+ /* @__PURE__ */ jsx(
2633
+ "button",
2634
+ {
2635
+ type: "button",
2636
+ onClick: handleCopy,
2637
+ className: "flex items-center gap-1.5 rounded-md px-2 py-1 text-[11px] transition-colors cursor-pointer",
2638
+ style: { color: "#a6adc8" },
2639
+ children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
2640
+ /* @__PURE__ */ jsx(
2641
+ "svg",
2642
+ {
2643
+ className: "h-3.5 w-3.5 text-emerald-400",
2644
+ viewBox: "0 0 24 24",
2645
+ fill: "none",
2646
+ stroke: "currentColor",
2647
+ strokeWidth: "2",
2648
+ strokeLinecap: "round",
2649
+ strokeLinejoin: "round",
2650
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
2651
+ }
2652
+ ),
2653
+ "Copied"
2654
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2655
+ /* @__PURE__ */ jsxs(
2656
+ "svg",
2657
+ {
2658
+ className: "h-3.5 w-3.5",
2659
+ viewBox: "0 0 24 24",
2660
+ fill: "none",
2661
+ stroke: "currentColor",
2662
+ strokeWidth: "2",
2663
+ strokeLinecap: "round",
2664
+ strokeLinejoin: "round",
2665
+ children: [
2666
+ /* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
2667
+ /* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
2668
+ ]
2669
+ }
2670
+ ),
2671
+ "Copy"
2672
+ ] })
2673
+ }
2674
+ )
2675
+ ] }),
2676
+ /* @__PURE__ */ jsx("div", { className: "overflow-auto [scrollbar-width:thin] [scrollbar-color:theme(colors.gray.700)_transparent] [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-gray-700", style: { maxHeight }, children: /* @__PURE__ */ jsx("pre", { className: "p-4 text-[13px] leading-relaxed", children: /* @__PURE__ */ jsx("code", { className: "font-mono", style: { color: "#cdd6f4" }, children: lines.map((line, i) => /* @__PURE__ */ jsxs("div", { className: "flex", children: [
2677
+ showLineNumbers && /* @__PURE__ */ jsx("span", { className: "mr-4 inline-block w-8 shrink-0 select-none text-right", style: { color: "#585b70" }, children: i + 1 }),
2678
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children: line || "\n" })
2679
+ ] }, i)) }) }) })
2680
+ ]
2681
+ }
2682
+ );
2683
+ }
2684
+ );
2685
+ CodeBlock.displayName = "CodeBlock";
2686
+ var ConversationBranch = forwardRef(({ current, total, onPrevious, onNext, className, ...props }, ref) => {
2687
+ const atStart = current <= 1;
2688
+ const atEnd = current >= total;
2689
+ return /* @__PURE__ */ jsxs(
2690
+ "div",
2691
+ {
2692
+ ref,
2693
+ className: cn(
2694
+ "arclo-conversation-branch inline-flex items-center gap-1 rounded-lg border border-gray-200 bg-white",
2695
+ className
2696
+ ),
2697
+ ...props,
2698
+ children: [
2699
+ /* @__PURE__ */ jsx(
2700
+ "button",
2701
+ {
2702
+ type: "button",
2703
+ onClick: onPrevious,
2704
+ disabled: atStart,
2705
+ "aria-label": "Previous branch",
2706
+ className: cn(
2707
+ "flex h-7 w-7 items-center justify-center rounded-l-lg transition-colors cursor-pointer",
2708
+ atStart ? "cursor-not-allowed text-gray-200" : "text-gray-400 hover:bg-gray-50 hover:text-gray-600"
2709
+ ),
2710
+ children: /* @__PURE__ */ jsx(
2711
+ "svg",
2712
+ {
2713
+ className: "h-3.5 w-3.5",
2714
+ viewBox: "0 0 24 24",
2715
+ fill: "none",
2716
+ stroke: "currentColor",
2717
+ strokeWidth: "2",
2718
+ strokeLinecap: "round",
2719
+ strokeLinejoin: "round",
2720
+ children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" })
2721
+ }
2722
+ )
2723
+ }
2724
+ ),
2725
+ /* @__PURE__ */ jsxs("span", { className: "select-none px-1 text-xs font-medium tabular-nums text-gray-500", children: [
2726
+ current,
2727
+ "/",
2728
+ total
2729
+ ] }),
2730
+ /* @__PURE__ */ jsx(
2731
+ "button",
2732
+ {
2733
+ type: "button",
2734
+ onClick: onNext,
2735
+ disabled: atEnd,
2736
+ "aria-label": "Next branch",
2737
+ className: cn(
2738
+ "flex h-7 w-7 items-center justify-center rounded-r-lg transition-colors cursor-pointer",
2739
+ atEnd ? "cursor-not-allowed text-gray-200" : "text-gray-400 hover:bg-gray-50 hover:text-gray-600"
2740
+ ),
2741
+ children: /* @__PURE__ */ jsx(
2742
+ "svg",
2743
+ {
2744
+ className: "h-3.5 w-3.5",
2745
+ viewBox: "0 0 24 24",
2746
+ fill: "none",
2747
+ stroke: "currentColor",
2748
+ strokeWidth: "2",
2749
+ strokeLinecap: "round",
2750
+ strokeLinejoin: "round",
2751
+ children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
2752
+ }
2753
+ )
2754
+ }
2755
+ )
2756
+ ]
2757
+ }
2758
+ );
2759
+ });
2760
+ ConversationBranch.displayName = "ConversationBranch";
2761
+ var TopicCard = forwardRef(
2762
+ ({ title, description, icon, onSelect, variant = "card", className, ...props }, ref) => {
2763
+ if (variant === "compact") {
2764
+ return /* @__PURE__ */ jsxs(
2765
+ "button",
2766
+ {
2767
+ ref,
2768
+ type: "button",
2769
+ onClick: () => onSelect?.(title),
2770
+ className: cn(
2771
+ "arclo-topic-card inline-flex shrink-0 items-center gap-2 rounded-full border px-3.5 py-2 text-left transition-all cursor-pointer",
2772
+ "hover:shadow-sm",
2773
+ className
2774
+ ),
2775
+ style: {
2776
+ backgroundColor: themeVars.surface,
2777
+ borderColor: themeVars.border
2778
+ },
2779
+ ...props,
2780
+ children: [
2781
+ icon && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-sm", children: icon }),
2782
+ /* @__PURE__ */ jsx(
2783
+ "span",
2784
+ {
2785
+ className: "text-xs font-medium whitespace-nowrap",
2786
+ style: { color: themeVars.text },
2787
+ children: title
2788
+ }
2789
+ )
2790
+ ]
2791
+ }
2792
+ );
2793
+ }
2794
+ return /* @__PURE__ */ jsxs(
2795
+ "button",
2796
+ {
2797
+ ref,
2798
+ type: "button",
2799
+ onClick: () => onSelect?.(title),
2800
+ className: cn(
2801
+ "arclo-topic-card group flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all cursor-pointer",
2802
+ "hover:scale-[1.01] hover:shadow-sm",
2803
+ className
2804
+ ),
2805
+ style: {
2806
+ backgroundColor: themeVars.surface,
2807
+ borderColor: themeVars.border
2808
+ },
2809
+ ...props,
2810
+ children: [
2811
+ icon && /* @__PURE__ */ jsx(
2812
+ "span",
2813
+ {
2814
+ className: "mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-sm",
2815
+ style: {
2816
+ backgroundColor: `color-mix(in srgb, ${themeVars.accent} 10%, transparent)`,
2817
+ color: themeVars.accent
2818
+ },
2819
+ children: icon
2820
+ }
2821
+ ),
2822
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
2823
+ /* @__PURE__ */ jsx(
2824
+ "p",
2825
+ {
2826
+ className: "text-sm font-medium leading-snug",
2827
+ style: { color: themeVars.text },
2828
+ children: title
2829
+ }
2830
+ ),
2831
+ description && /* @__PURE__ */ jsx(
2832
+ "p",
2833
+ {
2834
+ className: "mt-1 text-xs leading-relaxed",
2835
+ style: { color: themeVars.textMuted },
2836
+ children: description
2837
+ }
2838
+ )
2839
+ ] }),
2840
+ /* @__PURE__ */ jsx(
2841
+ "svg",
2842
+ {
2843
+ className: "mt-1 h-4 w-4 shrink-0 opacity-0 transition-opacity group-hover:opacity-100",
2844
+ style: { color: themeVars.textMuted },
2845
+ viewBox: "0 0 24 24",
2846
+ fill: "none",
2847
+ stroke: "currentColor",
2848
+ strokeWidth: "2",
2849
+ strokeLinecap: "round",
2850
+ strokeLinejoin: "round",
2851
+ children: /* @__PURE__ */ jsx("path", { d: "M5 12h14M12 5l7 7-7 7" })
2852
+ }
2853
+ )
2854
+ ]
2855
+ }
2856
+ );
2857
+ }
2858
+ );
2859
+ TopicCard.displayName = "TopicCard";
2860
+ var SuggestTopics = forwardRef(
2861
+ ({ variant = "grid", columns = 2, children, className, ...props }, ref) => {
2862
+ const scrollRef = useRef(null);
2863
+ const isDragging = useRef(false);
2864
+ const startX = useRef(0);
2865
+ const scrollLeft = useRef(0);
2866
+ const hasDragged = useRef(false);
2867
+ const onMouseDown = useCallback((e) => {
2868
+ const el = scrollRef.current;
2869
+ if (!el) return;
2870
+ isDragging.current = true;
2871
+ hasDragged.current = false;
2872
+ startX.current = e.pageX - el.offsetLeft;
2873
+ scrollLeft.current = el.scrollLeft;
2874
+ el.style.cursor = "grabbing";
2875
+ el.style.userSelect = "none";
2876
+ }, []);
2877
+ const onMouseMove = useCallback((e) => {
2878
+ if (!isDragging.current) return;
2879
+ const el = scrollRef.current;
2880
+ if (!el) return;
2881
+ e.preventDefault();
2882
+ const x = e.pageX - el.offsetLeft;
2883
+ const walk = (x - startX.current) * 1.5;
2884
+ if (Math.abs(walk) > 3) hasDragged.current = true;
2885
+ el.scrollLeft = scrollLeft.current - walk;
2886
+ }, []);
2887
+ const onMouseUp = useCallback(() => {
2888
+ isDragging.current = false;
2889
+ const el = scrollRef.current;
2890
+ if (el) {
2891
+ el.style.cursor = "grab";
2892
+ el.style.userSelect = "";
2893
+ }
2894
+ }, []);
2895
+ const onClickCapture = useCallback((e) => {
2896
+ if (hasDragged.current) {
2897
+ e.stopPropagation();
2898
+ e.preventDefault();
2899
+ hasDragged.current = false;
2900
+ }
2901
+ }, []);
2902
+ if (variant === "compact") {
2903
+ return /* @__PURE__ */ jsxs(
2904
+ "div",
2905
+ {
2906
+ ref: (node) => {
2907
+ scrollRef.current = node;
2908
+ if (typeof ref === "function") ref(node);
2909
+ else if (ref) ref.current = node;
2910
+ },
2911
+ className: cn(
2912
+ "arclo-suggest-topics",
2913
+ className
2914
+ ),
2915
+ style: {
2916
+ display: "flex",
2917
+ gap: "0.5rem",
2918
+ overflowX: "auto",
2919
+ cursor: "grab",
2920
+ scrollbarWidth: "none",
2921
+ msOverflowStyle: "none"
2922
+ },
2923
+ onMouseDown,
2924
+ onMouseMove,
2925
+ onMouseUp,
2926
+ onMouseLeave: onMouseUp,
2927
+ onClickCapture,
2928
+ ...props,
2929
+ children: [
2930
+ children,
2931
+ /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: `.arclo-suggest-topics::-webkit-scrollbar { display: none; }` } })
2932
+ ]
2933
+ }
2934
+ );
2935
+ }
2936
+ return /* @__PURE__ */ jsx(
2937
+ "div",
2938
+ {
2939
+ ref,
2940
+ className: cn(
2941
+ "arclo-suggest-topics grid gap-3",
2942
+ columns === 1 && "grid-cols-1",
2943
+ columns === 2 && "grid-cols-1 sm:grid-cols-2",
2944
+ columns === 3 && "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
2945
+ className
2946
+ ),
2947
+ ...props,
2948
+ children
2949
+ }
2950
+ );
2951
+ }
2952
+ );
2953
+ SuggestTopics.displayName = "SuggestTopics";
2954
+
2955
+ export { chat_thread_exports as ChatThread, CitationGroup, CitationInline, CodeBlock, ConfidenceBadge, ConversationBranch, feedback_bar_exports as FeedbackBar, FileAttachment, MarkdownRenderer, ModelSelector, prompt_box_exports as PromptBox, RefusalCard, SourceCard, StatusIndicator, streaming_text_exports as StreamingText, SuggestTopics, thinking_block_exports as ThinkingBlock, TokenUsage, tool_call_exports as ToolCall, TopicCard, useStreamingText };
2956
+ //# sourceMappingURL=index.js.map
2957
+ //# sourceMappingURL=index.js.map