@aomi-labs/widget-lib 1.0.0 → 1.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.
Files changed (76) hide show
  1. package/SHADCN-FETCH-GUIDE.md +105 -0
  2. package/components.json +10 -0
  3. package/dist/accordion.json +18 -0
  4. package/dist/alert.json +17 -0
  5. package/dist/aomi-frame.json +24 -0
  6. package/dist/assistant-thread-list.json +22 -0
  7. package/dist/assistant-thread.json +27 -0
  8. package/dist/assistant-threadlist-collapsible.json +23 -0
  9. package/dist/assistant-threadlist-sidebar.json +20 -0
  10. package/dist/assistant-tool-fallback.json +20 -0
  11. package/dist/avatar.json +17 -0
  12. package/dist/badge.json +17 -0
  13. package/dist/breadcrumb.json +17 -0
  14. package/dist/button.json +18 -0
  15. package/dist/card.json +15 -0
  16. package/dist/collapsible.json +17 -0
  17. package/dist/command.json +21 -0
  18. package/dist/dialog.json +18 -0
  19. package/dist/drawer.json +17 -0
  20. package/dist/input.json +15 -0
  21. package/dist/label.json +15 -0
  22. package/dist/notification.json +20 -0
  23. package/dist/popover.json +17 -0
  24. package/dist/registry.json +429 -0
  25. package/dist/separator.json +17 -0
  26. package/dist/sheet.json +18 -0
  27. package/dist/sidebar.json +18 -0
  28. package/dist/skeleton.json +15 -0
  29. package/dist/sonner.json +17 -0
  30. package/dist/tooltip.json +17 -0
  31. package/package.json +24 -88
  32. package/scripts/build-registry.js +74 -0
  33. package/src/components/aomi-frame.tsx +128 -0
  34. package/src/components/assistant-ui/attachment.tsx +235 -0
  35. package/src/components/assistant-ui/markdown-text.tsx +228 -0
  36. package/src/components/assistant-ui/thread-list.tsx +106 -0
  37. package/src/components/assistant-ui/thread.tsx +457 -0
  38. package/src/components/assistant-ui/threadlist-sidebar.tsx +71 -0
  39. package/src/components/assistant-ui/tool-fallback.tsx +48 -0
  40. package/src/components/assistant-ui/tooltip-icon-button.tsx +42 -0
  41. package/src/components/test/ThreadContextTest.tsx +204 -0
  42. package/src/components/tools/example-tool/ExampleTool.tsx +102 -0
  43. package/src/components/ui/accordion.tsx +58 -0
  44. package/src/components/ui/alert.tsx +62 -0
  45. package/src/components/ui/avatar.tsx +53 -0
  46. package/src/components/ui/badge.tsx +37 -0
  47. package/src/components/ui/breadcrumb.tsx +109 -0
  48. package/src/components/ui/button.tsx +59 -0
  49. package/src/components/ui/card.tsx +86 -0
  50. package/src/components/ui/collapsible.tsx +12 -0
  51. package/src/components/ui/command.tsx +156 -0
  52. package/src/components/ui/dialog.tsx +143 -0
  53. package/src/components/ui/drawer.tsx +118 -0
  54. package/src/components/ui/input.tsx +21 -0
  55. package/src/components/ui/label.tsx +20 -0
  56. package/src/components/ui/notification.tsx +57 -0
  57. package/src/components/ui/popover.tsx +33 -0
  58. package/src/components/ui/separator.tsx +28 -0
  59. package/src/components/ui/sheet.tsx +139 -0
  60. package/src/components/ui/sidebar.tsx +820 -0
  61. package/src/components/ui/skeleton.tsx +15 -0
  62. package/src/components/ui/sonner.tsx +29 -0
  63. package/src/components/ui/tooltip.tsx +61 -0
  64. package/src/hooks/use-mobile.ts +21 -0
  65. package/src/index.ts +26 -0
  66. package/src/registry.ts +218 -0
  67. package/{dist/styles.css → src/themes/default.css} +21 -3
  68. package/src/themes/tokens.config.ts +39 -0
  69. package/tsconfig.json +19 -0
  70. package/README.md +0 -41
  71. package/dist/index.cjs +0 -3780
  72. package/dist/index.cjs.map +0 -1
  73. package/dist/index.d.cts +0 -302
  74. package/dist/index.d.ts +0 -302
  75. package/dist/index.js +0 -3696
  76. package/dist/index.js.map +0 -1
package/dist/index.js DELETED
@@ -1,3696 +0,0 @@
1
- "use client";
2
- var __defProp = Object.defineProperty;
3
- var __defProps = Object.defineProperties;
4
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
- var __spreadValues = (a, b) => {
10
- for (var prop in b || (b = {}))
11
- if (__hasOwnProp.call(b, prop))
12
- __defNormalProp(a, prop, b[prop]);
13
- if (__getOwnPropSymbols)
14
- for (var prop of __getOwnPropSymbols(b)) {
15
- if (__propIsEnum.call(b, prop))
16
- __defNormalProp(a, prop, b[prop]);
17
- }
18
- return a;
19
- };
20
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
- var __objRest = (source, exclude) => {
22
- var target = {};
23
- for (var prop in source)
24
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
25
- target[prop] = source[prop];
26
- if (source != null && __getOwnPropSymbols)
27
- for (var prop of __getOwnPropSymbols(source)) {
28
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
29
- target[prop] = source[prop];
30
- }
31
- return target;
32
- };
33
-
34
- // src/components/aomi-frame.tsx
35
- import { useState as useState8, useCallback as useCallback4 } from "react";
36
-
37
- // src/components/assistant-ui/thread.tsx
38
- import {
39
- AlertCircleIcon,
40
- ArrowDownIcon,
41
- ArrowUpIcon,
42
- CheckIcon as CheckIcon3,
43
- ChevronLeftIcon,
44
- ChevronRightIcon,
45
- CopyIcon as CopyIcon2,
46
- PencilIcon,
47
- RefreshCwIcon,
48
- Square
49
- } from "lucide-react";
50
- import {
51
- ActionBarPrimitive,
52
- BranchPickerPrimitive,
53
- ComposerPrimitive as ComposerPrimitive2,
54
- ErrorPrimitive,
55
- MessagePrimitive as MessagePrimitive2,
56
- ThreadPrimitive
57
- } from "@assistant-ui/react";
58
- import { useEffect as useEffect2 } from "react";
59
- import { LazyMotion, MotionConfig, domAnimation } from "motion/react";
60
- import * as m from "motion/react-m";
61
-
62
- // src/components/ui/button.tsx
63
- import { Slot } from "@radix-ui/react-slot";
64
- import { cva } from "class-variance-authority";
65
-
66
- // src/lib/utils.ts
67
- import { clsx } from "clsx";
68
- import { twMerge } from "tailwind-merge";
69
- function cn(...inputs) {
70
- return twMerge(clsx(inputs));
71
- }
72
-
73
- // src/components/ui/button.tsx
74
- import { jsx } from "react/jsx-runtime";
75
- var buttonVariants = cva(
76
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
77
- {
78
- variants: {
79
- variant: {
80
- default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
81
- destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
82
- outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
83
- secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
84
- ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
85
- link: "text-primary underline-offset-4 hover:underline"
86
- },
87
- size: {
88
- default: "h-9 px-4 py-2 has-[>svg]:px-3",
89
- sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
90
- lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
91
- icon: "size-9"
92
- }
93
- },
94
- defaultVariants: {
95
- variant: "default",
96
- size: "default"
97
- }
98
- }
99
- );
100
- function Button(_a) {
101
- var _b = _a, {
102
- className,
103
- variant,
104
- size,
105
- asChild = false
106
- } = _b, props = __objRest(_b, [
107
- "className",
108
- "variant",
109
- "size",
110
- "asChild"
111
- ]);
112
- const Comp = asChild ? Slot : "button";
113
- return /* @__PURE__ */ jsx(
114
- Comp,
115
- __spreadValues({
116
- "data-slot": "button",
117
- className: cn(buttonVariants({ variant, size, className }))
118
- }, props)
119
- );
120
- }
121
-
122
- // src/components/assistant-ui/markdown-text.tsx
123
- import "@assistant-ui/react-markdown/styles/dot.css";
124
- import {
125
- MarkdownTextPrimitive,
126
- unstable_memoizeMarkdownComponents as memoizeMarkdownComponents,
127
- useIsMarkdownCodeBlock
128
- } from "@assistant-ui/react-markdown";
129
- import remarkGfm from "remark-gfm";
130
- import { memo, useState } from "react";
131
- import { CheckIcon, CopyIcon } from "lucide-react";
132
-
133
- // src/components/assistant-ui/tooltip-icon-button.tsx
134
- import { forwardRef } from "react";
135
- import { Slottable } from "@radix-ui/react-slot";
136
-
137
- // src/components/ui/tooltip.tsx
138
- import * as TooltipPrimitive from "@radix-ui/react-tooltip";
139
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
140
- function TooltipProvider(_a) {
141
- var _b = _a, {
142
- delayDuration = 0
143
- } = _b, props = __objRest(_b, [
144
- "delayDuration"
145
- ]);
146
- return /* @__PURE__ */ jsx2(
147
- TooltipPrimitive.Provider,
148
- __spreadValues({
149
- "data-slot": "tooltip-provider",
150
- delayDuration
151
- }, props)
152
- );
153
- }
154
- function Tooltip(_a) {
155
- var props = __objRest(_a, []);
156
- return /* @__PURE__ */ jsx2(TooltipProvider, { children: /* @__PURE__ */ jsx2(TooltipPrimitive.Root, __spreadValues({ "data-slot": "tooltip" }, props)) });
157
- }
158
- function TooltipTrigger(_a) {
159
- var props = __objRest(_a, []);
160
- return /* @__PURE__ */ jsx2(TooltipPrimitive.Trigger, __spreadValues({ "data-slot": "tooltip-trigger" }, props));
161
- }
162
- function TooltipContent(_a) {
163
- var _b = _a, {
164
- className,
165
- sideOffset = 0,
166
- children
167
- } = _b, props = __objRest(_b, [
168
- "className",
169
- "sideOffset",
170
- "children"
171
- ]);
172
- return /* @__PURE__ */ jsx2(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
173
- TooltipPrimitive.Content,
174
- __spreadProps(__spreadValues({
175
- "data-slot": "tooltip-content",
176
- sideOffset,
177
- className: cn(
178
- "z-50 w-fit origin-(--radix-tooltip-content-transform-origin) animate-in rounded-md bg-primary px-3 py-1.5 text-xs text-balance text-primary-foreground fade-in-0 zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
179
- className
180
- )
181
- }, props), {
182
- children: [
183
- children,
184
- /* @__PURE__ */ jsx2(TooltipPrimitive.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-primary fill-primary" })
185
- ]
186
- })
187
- ) });
188
- }
189
-
190
- // src/components/assistant-ui/tooltip-icon-button.tsx
191
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
192
- var TooltipIconButton = forwardRef((_a, ref) => {
193
- var _b = _a, { children, tooltip, side = "bottom", className } = _b, rest = __objRest(_b, ["children", "tooltip", "side", "className"]);
194
- return /* @__PURE__ */ jsxs2(Tooltip, { children: [
195
- /* @__PURE__ */ jsx3(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs2(
196
- Button,
197
- __spreadProps(__spreadValues({
198
- variant: "ghost",
199
- size: "icon"
200
- }, rest), {
201
- className: cn("aui-button-icon size-6 p-1", className),
202
- ref,
203
- children: [
204
- /* @__PURE__ */ jsx3(Slottable, { children }),
205
- /* @__PURE__ */ jsx3("span", { className: "aui-sr-only sr-only", children: tooltip })
206
- ]
207
- })
208
- ) }),
209
- /* @__PURE__ */ jsx3(TooltipContent, { side, children: tooltip })
210
- ] });
211
- });
212
- TooltipIconButton.displayName = "TooltipIconButton";
213
-
214
- // src/components/assistant-ui/markdown-text.tsx
215
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
216
- var MarkdownTextImpl = () => {
217
- return /* @__PURE__ */ jsx4(
218
- MarkdownTextPrimitive,
219
- {
220
- remarkPlugins: [remarkGfm],
221
- className: "aui-md",
222
- components: defaultComponents
223
- }
224
- );
225
- };
226
- var MarkdownText = memo(MarkdownTextImpl);
227
- var CodeHeader = ({ language, code }) => {
228
- const { isCopied, copyToClipboard } = useCopyToClipboard();
229
- const onCopy = () => {
230
- if (!code || isCopied) return;
231
- copyToClipboard(code);
232
- };
233
- return /* @__PURE__ */ jsxs3("div", { className: "aui-code-header-root mt-4 flex items-center justify-between gap-4 rounded-t-lg bg-muted-foreground/15 px-4 py-2 text-sm font-semibold text-foreground dark:bg-muted-foreground/20", children: [
234
- /* @__PURE__ */ jsx4("span", { className: "aui-code-header-language lowercase [&>span]:text-xs", children: language }),
235
- /* @__PURE__ */ jsxs3(TooltipIconButton, { tooltip: "Copy", onClick: onCopy, children: [
236
- !isCopied && /* @__PURE__ */ jsx4(CopyIcon, {}),
237
- isCopied && /* @__PURE__ */ jsx4(CheckIcon, {})
238
- ] })
239
- ] });
240
- };
241
- var useCopyToClipboard = ({
242
- copiedDuration = 3e3
243
- } = {}) => {
244
- const [isCopied, setIsCopied] = useState(false);
245
- const copyToClipboard = (value) => {
246
- if (!value) return;
247
- navigator.clipboard.writeText(value).then(() => {
248
- setIsCopied(true);
249
- setTimeout(() => setIsCopied(false), copiedDuration);
250
- });
251
- };
252
- return { isCopied, copyToClipboard };
253
- };
254
- var defaultComponents = memoizeMarkdownComponents({
255
- h1: (_a) => {
256
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
257
- return /* @__PURE__ */ jsx4(
258
- "h1",
259
- __spreadValues({
260
- className: cn(
261
- "aui-md-h1 mb-8 scroll-m-20 text-4xl font-extrabold tracking-tight last:mb-0",
262
- className
263
- )
264
- }, props)
265
- );
266
- },
267
- h2: (_c) => {
268
- var _d = _c, { className } = _d, props = __objRest(_d, ["className"]);
269
- return /* @__PURE__ */ jsx4(
270
- "h2",
271
- __spreadValues({
272
- className: cn(
273
- "aui-md-h2 mt-8 mb-4 scroll-m-20 text-3xl font-semibold tracking-tight first:mt-0 last:mb-0",
274
- className
275
- )
276
- }, props)
277
- );
278
- },
279
- h3: (_e) => {
280
- var _f = _e, { className } = _f, props = __objRest(_f, ["className"]);
281
- return /* @__PURE__ */ jsx4(
282
- "h3",
283
- __spreadValues({
284
- className: cn(
285
- "aui-md-h3 mt-6 mb-4 scroll-m-20 text-2xl font-semibold tracking-tight first:mt-0 last:mb-0",
286
- className
287
- )
288
- }, props)
289
- );
290
- },
291
- h4: (_g) => {
292
- var _h = _g, { className } = _h, props = __objRest(_h, ["className"]);
293
- return /* @__PURE__ */ jsx4(
294
- "h4",
295
- __spreadValues({
296
- className: cn(
297
- "aui-md-h4 mt-6 mb-4 scroll-m-20 text-xl font-semibold tracking-tight first:mt-0 last:mb-0",
298
- className
299
- )
300
- }, props)
301
- );
302
- },
303
- h5: (_i) => {
304
- var _j = _i, { className } = _j, props = __objRest(_j, ["className"]);
305
- return /* @__PURE__ */ jsx4(
306
- "h5",
307
- __spreadValues({
308
- className: cn(
309
- "aui-md-h5 my-4 text-lg font-semibold first:mt-0 last:mb-0",
310
- className
311
- )
312
- }, props)
313
- );
314
- },
315
- h6: (_k) => {
316
- var _l = _k, { className } = _l, props = __objRest(_l, ["className"]);
317
- return /* @__PURE__ */ jsx4(
318
- "h6",
319
- __spreadValues({
320
- className: cn(
321
- "aui-md-h6 my-4 font-semibold first:mt-0 last:mb-0",
322
- className
323
- )
324
- }, props)
325
- );
326
- },
327
- p: (_m) => {
328
- var _n = _m, { className } = _n, props = __objRest(_n, ["className"]);
329
- return /* @__PURE__ */ jsx4(
330
- "p",
331
- __spreadValues({
332
- className: cn(
333
- "aui-md-p mt-5 mb-5 leading-7 first:mt-0 last:mb-0",
334
- className
335
- )
336
- }, props)
337
- );
338
- },
339
- a: (_o) => {
340
- var _p = _o, { className } = _p, props = __objRest(_p, ["className"]);
341
- return /* @__PURE__ */ jsx4(
342
- "a",
343
- __spreadValues({
344
- className: cn(
345
- "aui-md-a font-medium text-primary underline underline-offset-4",
346
- className
347
- )
348
- }, props)
349
- );
350
- },
351
- blockquote: (_q) => {
352
- var _r = _q, { className } = _r, props = __objRest(_r, ["className"]);
353
- return /* @__PURE__ */ jsx4(
354
- "blockquote",
355
- __spreadValues({
356
- className: cn("aui-md-blockquote border-l-2 pl-6 italic", className)
357
- }, props)
358
- );
359
- },
360
- ul: (_s) => {
361
- var _t = _s, { className } = _t, props = __objRest(_t, ["className"]);
362
- return /* @__PURE__ */ jsx4(
363
- "ul",
364
- __spreadValues({
365
- className: cn("aui-md-ul my-5 ml-6 list-disc [&>li]:mt-2", className)
366
- }, props)
367
- );
368
- },
369
- ol: (_u) => {
370
- var _v = _u, { className } = _v, props = __objRest(_v, ["className"]);
371
- return /* @__PURE__ */ jsx4(
372
- "ol",
373
- __spreadValues({
374
- className: cn("aui-md-ol my-5 ml-6 list-decimal [&>li]:mt-2", className)
375
- }, props)
376
- );
377
- },
378
- hr: (_w) => {
379
- var _x = _w, { className } = _x, props = __objRest(_x, ["className"]);
380
- return /* @__PURE__ */ jsx4("hr", __spreadValues({ className: cn("aui-md-hr my-5 border-b", className) }, props));
381
- },
382
- table: (_y) => {
383
- var _z = _y, { className } = _z, props = __objRest(_z, ["className"]);
384
- return /* @__PURE__ */ jsx4(
385
- "table",
386
- __spreadValues({
387
- className: cn(
388
- "aui-md-table my-5 w-full border-separate border-spacing-0 overflow-y-auto",
389
- className
390
- )
391
- }, props)
392
- );
393
- },
394
- th: (_A) => {
395
- var _B = _A, { className } = _B, props = __objRest(_B, ["className"]);
396
- return /* @__PURE__ */ jsx4(
397
- "th",
398
- __spreadValues({
399
- className: cn(
400
- "aui-md-th bg-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [&[align=center]]:text-center [&[align=right]]:text-right",
401
- className
402
- )
403
- }, props)
404
- );
405
- },
406
- td: (_C) => {
407
- var _D = _C, { className } = _D, props = __objRest(_D, ["className"]);
408
- return /* @__PURE__ */ jsx4(
409
- "td",
410
- __spreadValues({
411
- className: cn(
412
- "aui-md-td border-b border-l px-4 py-2 text-left last:border-r [&[align=center]]:text-center [&[align=right]]:text-right",
413
- className
414
- )
415
- }, props)
416
- );
417
- },
418
- tr: (_E) => {
419
- var _F = _E, { className } = _F, props = __objRest(_F, ["className"]);
420
- return /* @__PURE__ */ jsx4(
421
- "tr",
422
- __spreadValues({
423
- className: cn(
424
- "aui-md-tr m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg",
425
- className
426
- )
427
- }, props)
428
- );
429
- },
430
- sup: (_G) => {
431
- var _H = _G, { className } = _H, props = __objRest(_H, ["className"]);
432
- return /* @__PURE__ */ jsx4(
433
- "sup",
434
- __spreadValues({
435
- className: cn("aui-md-sup [&>a]:text-xs [&>a]:no-underline", className)
436
- }, props)
437
- );
438
- },
439
- pre: (_I) => {
440
- var _J = _I, { className } = _J, props = __objRest(_J, ["className"]);
441
- return /* @__PURE__ */ jsx4(
442
- "pre",
443
- __spreadValues({
444
- className: cn(
445
- "aui-md-pre overflow-x-auto !rounded-t-none rounded-b-lg bg-accent p-6 text-black text-[12px]",
446
- className
447
- )
448
- }, props)
449
- );
450
- },
451
- code: function Code(_K) {
452
- var _L = _K, { className } = _L, props = __objRest(_L, ["className"]);
453
- const isCodeBlock = useIsMarkdownCodeBlock();
454
- return /* @__PURE__ */ jsx4(
455
- "code",
456
- __spreadValues({
457
- className: cn(
458
- !isCodeBlock && "aui-md-inline-code rounded border bg-muted text-[12px]",
459
- className
460
- )
461
- }, props)
462
- );
463
- },
464
- CodeHeader
465
- });
466
-
467
- // src/components/assistant-ui/tool-fallback.tsx
468
- import { CheckIcon as CheckIcon2, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
469
- import { useState as useState2 } from "react";
470
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
471
- var ToolFallback = ({
472
- toolName,
473
- argsText,
474
- result
475
- }) => {
476
- const [isCollapsed, setIsCollapsed] = useState2(true);
477
- return /* @__PURE__ */ jsxs4("div", { className: "aui-tool-fallback-root mb-4 flex w-full flex-col gap-3 rounded-lg border py-3", children: [
478
- /* @__PURE__ */ jsxs4("div", { className: "aui-tool-fallback-header flex items-center gap-2 px-4", children: [
479
- /* @__PURE__ */ jsx5(CheckIcon2, { className: "aui-tool-fallback-icon size-4" }),
480
- /* @__PURE__ */ jsxs4("p", { className: "aui-tool-fallback-title flex-grow", children: [
481
- "Used tool: ",
482
- /* @__PURE__ */ jsx5("b", { children: toolName })
483
- ] }),
484
- /* @__PURE__ */ jsx5(Button, { onClick: () => setIsCollapsed(!isCollapsed), children: isCollapsed ? /* @__PURE__ */ jsx5(ChevronUpIcon, {}) : /* @__PURE__ */ jsx5(ChevronDownIcon, {}) })
485
- ] }),
486
- !isCollapsed && /* @__PURE__ */ jsxs4("div", { className: "aui-tool-fallback-content flex flex-col gap-2 border-t pt-2 bg-muted", children: [
487
- /* @__PURE__ */ jsx5("div", { className: "aui-tool-fallback-args-root px-4", children: /* @__PURE__ */ jsx5("pre", { className: "aui-tool-fallback-args-value whitespace-pre-wrap", children: argsText }) }),
488
- result !== void 0 && /* @__PURE__ */ jsxs4("div", { className: "aui-tool-fallback-result-root border-t border-dashed px-4 pt-2", children: [
489
- /* @__PURE__ */ jsx5("p", { className: "aui-tool-fallback-result-header font-semibold", children: "Result:" }),
490
- /* @__PURE__ */ jsx5("pre", { className: "aui-tool-fallback-result-content whitespace-pre-wrap text-[012px]", children: typeof result === "string" ? result : JSON.stringify(result, null, 2) })
491
- ] })
492
- ] })
493
- ] });
494
- };
495
-
496
- // src/components/assistant-ui/attachment.tsx
497
- import { useEffect, useState as useState3 } from "react";
498
- import Image2 from "next/image";
499
- import { XIcon as XIcon2, PlusIcon, FileText } from "lucide-react";
500
- import {
501
- AttachmentPrimitive,
502
- ComposerPrimitive,
503
- MessagePrimitive,
504
- useAssistantState,
505
- useAssistantApi
506
- } from "@assistant-ui/react";
507
- import { useShallow } from "zustand/shallow";
508
-
509
- // src/components/ui/dialog.tsx
510
- import * as DialogPrimitive from "@radix-ui/react-dialog";
511
- import { XIcon } from "lucide-react";
512
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
513
- function Dialog(_a) {
514
- var props = __objRest(_a, []);
515
- return /* @__PURE__ */ jsx6(DialogPrimitive.Root, __spreadValues({ "data-slot": "dialog" }, props));
516
- }
517
- function DialogTrigger(_a) {
518
- var props = __objRest(_a, []);
519
- return /* @__PURE__ */ jsx6(DialogPrimitive.Trigger, __spreadValues({ "data-slot": "dialog-trigger" }, props));
520
- }
521
- function DialogPortal(_a) {
522
- var props = __objRest(_a, []);
523
- return /* @__PURE__ */ jsx6(DialogPrimitive.Portal, __spreadValues({ "data-slot": "dialog-portal" }, props));
524
- }
525
- function DialogClose(_a) {
526
- var props = __objRest(_a, []);
527
- return /* @__PURE__ */ jsx6(DialogPrimitive.Close, __spreadValues({ "data-slot": "dialog-close" }, props));
528
- }
529
- function DialogOverlay(_a) {
530
- var _b = _a, {
531
- className
532
- } = _b, props = __objRest(_b, [
533
- "className"
534
- ]);
535
- return /* @__PURE__ */ jsx6(
536
- DialogPrimitive.Overlay,
537
- __spreadValues({
538
- "data-slot": "dialog-overlay",
539
- className: cn(
540
- "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
541
- className
542
- )
543
- }, props)
544
- );
545
- }
546
- function DialogContent(_a) {
547
- var _b = _a, {
548
- className,
549
- children,
550
- showCloseButton = true
551
- } = _b, props = __objRest(_b, [
552
- "className",
553
- "children",
554
- "showCloseButton"
555
- ]);
556
- return /* @__PURE__ */ jsxs5(DialogPortal, { "data-slot": "dialog-portal", children: [
557
- /* @__PURE__ */ jsx6(DialogOverlay, {}),
558
- /* @__PURE__ */ jsxs5(
559
- DialogPrimitive.Content,
560
- __spreadProps(__spreadValues({
561
- "data-slot": "dialog-content",
562
- className: cn(
563
- "fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg",
564
- className
565
- )
566
- }, props), {
567
- children: [
568
- children,
569
- showCloseButton && /* @__PURE__ */ jsxs5(
570
- DialogPrimitive.Close,
571
- {
572
- "data-slot": "dialog-close",
573
- className: "absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
574
- children: [
575
- /* @__PURE__ */ jsx6(XIcon, {}),
576
- /* @__PURE__ */ jsx6("span", { className: "sr-only", children: "Close" })
577
- ]
578
- }
579
- )
580
- ]
581
- })
582
- )
583
- ] });
584
- }
585
- function DialogHeader(_a) {
586
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
587
- return /* @__PURE__ */ jsx6(
588
- "div",
589
- __spreadValues({
590
- "data-slot": "dialog-header",
591
- className: cn("flex flex-col gap-2 text-center sm:text-left", className)
592
- }, props)
593
- );
594
- }
595
- function DialogFooter(_a) {
596
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
597
- return /* @__PURE__ */ jsx6(
598
- "div",
599
- __spreadValues({
600
- "data-slot": "dialog-footer",
601
- className: cn(
602
- "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
603
- className
604
- )
605
- }, props)
606
- );
607
- }
608
- function DialogTitle(_a) {
609
- var _b = _a, {
610
- className
611
- } = _b, props = __objRest(_b, [
612
- "className"
613
- ]);
614
- return /* @__PURE__ */ jsx6(
615
- DialogPrimitive.Title,
616
- __spreadValues({
617
- "data-slot": "dialog-title",
618
- className: cn("text-lg leading-none font-semibold", className)
619
- }, props)
620
- );
621
- }
622
- function DialogDescription(_a) {
623
- var _b = _a, {
624
- className
625
- } = _b, props = __objRest(_b, [
626
- "className"
627
- ]);
628
- return /* @__PURE__ */ jsx6(
629
- DialogPrimitive.Description,
630
- __spreadValues({
631
- "data-slot": "dialog-description",
632
- className: cn("text-sm text-muted-foreground", className)
633
- }, props)
634
- );
635
- }
636
-
637
- // src/components/ui/avatar.tsx
638
- import * as AvatarPrimitive from "@radix-ui/react-avatar";
639
- import { jsx as jsx7 } from "react/jsx-runtime";
640
- function Avatar(_a) {
641
- var _b = _a, {
642
- className
643
- } = _b, props = __objRest(_b, [
644
- "className"
645
- ]);
646
- return /* @__PURE__ */ jsx7(
647
- AvatarPrimitive.Root,
648
- __spreadValues({
649
- "data-slot": "avatar",
650
- className: cn(
651
- "relative flex size-8 shrink-0 overflow-hidden rounded-full",
652
- className
653
- )
654
- }, props)
655
- );
656
- }
657
- function AvatarImage(_a) {
658
- var _b = _a, {
659
- className
660
- } = _b, props = __objRest(_b, [
661
- "className"
662
- ]);
663
- return /* @__PURE__ */ jsx7(
664
- AvatarPrimitive.Image,
665
- __spreadValues({
666
- "data-slot": "avatar-image",
667
- className: cn("aspect-square size-full", className)
668
- }, props)
669
- );
670
- }
671
- function AvatarFallback(_a) {
672
- var _b = _a, {
673
- className
674
- } = _b, props = __objRest(_b, [
675
- "className"
676
- ]);
677
- return /* @__PURE__ */ jsx7(
678
- AvatarPrimitive.Fallback,
679
- __spreadValues({
680
- "data-slot": "avatar-fallback",
681
- className: cn(
682
- "flex size-full items-center justify-center rounded-full bg-muted",
683
- className
684
- )
685
- }, props)
686
- );
687
- }
688
-
689
- // src/components/assistant-ui/attachment.tsx
690
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
691
- var useFileSrc = (file) => {
692
- const [src, setSrc] = useState3(void 0);
693
- useEffect(() => {
694
- if (!file) {
695
- setSrc(void 0);
696
- return;
697
- }
698
- const objectUrl = URL.createObjectURL(file);
699
- setSrc(objectUrl);
700
- return () => {
701
- URL.revokeObjectURL(objectUrl);
702
- };
703
- }, [file]);
704
- return src;
705
- };
706
- var useAttachmentSrc = () => {
707
- var _a;
708
- const { file, src } = useAssistantState(
709
- useShallow(({ attachment }) => {
710
- var _a2, _b;
711
- if (attachment.type !== "image") return {};
712
- if (attachment.file) return { file: attachment.file };
713
- const src2 = (_b = (_a2 = attachment.content) == null ? void 0 : _a2.filter((c) => c.type === "image")[0]) == null ? void 0 : _b.image;
714
- if (!src2) return {};
715
- return { src: src2 };
716
- })
717
- );
718
- return (_a = useFileSrc(file)) != null ? _a : src;
719
- };
720
- var AttachmentPreview = ({ src }) => {
721
- const [isLoaded, setIsLoaded] = useState3(false);
722
- return /* @__PURE__ */ jsx8(
723
- Image2,
724
- {
725
- src,
726
- alt: "Image Preview",
727
- width: 1,
728
- height: 1,
729
- className: isLoaded ? "aui-attachment-preview-image-loaded block h-auto max-h-[80vh] w-auto max-w-full object-contain" : "aui-attachment-preview-image-loading hidden",
730
- onLoadingComplete: () => setIsLoaded(true),
731
- priority: false
732
- }
733
- );
734
- };
735
- var AttachmentPreviewDialog = ({ children }) => {
736
- const src = useAttachmentSrc();
737
- if (!src) return children;
738
- return /* @__PURE__ */ jsxs6(Dialog, { children: [
739
- /* @__PURE__ */ jsx8(
740
- DialogTrigger,
741
- {
742
- className: "aui-attachment-preview-trigger cursor-pointer transition-colors hover:bg-accent/50",
743
- asChild: true,
744
- children
745
- }
746
- ),
747
- /* @__PURE__ */ jsxs6(DialogContent, { className: "aui-attachment-preview-dialog-content p-2 sm:max-w-3xl [&_svg]:text-background [&>button]:rounded-full [&>button]:bg-foreground/60 [&>button]:p-1 [&>button]:opacity-100 [&>button]:!ring-0 [&>button]:hover:[&_svg]:text-destructive", children: [
748
- /* @__PURE__ */ jsx8(DialogTitle, { className: "aui-sr-only sr-only", children: "Image Attachment Preview" }),
749
- /* @__PURE__ */ jsx8("div", { className: "aui-attachment-preview relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden bg-background", children: /* @__PURE__ */ jsx8(AttachmentPreview, { src }) })
750
- ] })
751
- ] });
752
- };
753
- var AttachmentThumb = () => {
754
- const isImage = useAssistantState(
755
- ({ attachment }) => attachment.type === "image"
756
- );
757
- const src = useAttachmentSrc();
758
- return /* @__PURE__ */ jsxs6(Avatar, { className: "aui-attachment-tile-avatar h-full w-full rounded-none", children: [
759
- /* @__PURE__ */ jsx8(
760
- AvatarImage,
761
- {
762
- src,
763
- alt: "Attachment preview",
764
- className: "aui-attachment-tile-image object-cover"
765
- }
766
- ),
767
- /* @__PURE__ */ jsx8(AvatarFallback, { delayMs: isImage ? 200 : 0, children: /* @__PURE__ */ jsx8(FileText, { className: "aui-attachment-tile-fallback-icon size-8 text-muted-foreground" }) })
768
- ] });
769
- };
770
- var AttachmentUI = () => {
771
- const api = useAssistantApi();
772
- const isComposer = api.attachment.source === "composer";
773
- const isImage = useAssistantState(
774
- ({ attachment }) => attachment.type === "image"
775
- );
776
- const typeLabel = useAssistantState(({ attachment }) => {
777
- const type = attachment.type;
778
- switch (type) {
779
- case "image":
780
- return "Image";
781
- case "document":
782
- return "Document";
783
- case "file":
784
- return "File";
785
- default:
786
- const _exhaustiveCheck = type;
787
- throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);
788
- }
789
- });
790
- return /* @__PURE__ */ jsxs6(Tooltip, { children: [
791
- /* @__PURE__ */ jsxs6(
792
- AttachmentPrimitive.Root,
793
- {
794
- className: cn(
795
- "aui-attachment-root relative",
796
- isImage && "aui-attachment-root-composer only:[&>#attachment-tile]:size-24"
797
- ),
798
- children: [
799
- /* @__PURE__ */ jsx8(AttachmentPreviewDialog, { children: /* @__PURE__ */ jsx8(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx8(
800
- "div",
801
- {
802
- className: cn(
803
- "aui-attachment-tile size-14 cursor-pointer overflow-hidden rounded-[14px] border bg-muted transition-opacity hover:opacity-75",
804
- isComposer && "aui-attachment-tile-composer border-foreground/20"
805
- ),
806
- role: "button",
807
- id: "attachment-tile",
808
- "aria-label": `${typeLabel} attachment`,
809
- children: /* @__PURE__ */ jsx8(AttachmentThumb, {})
810
- }
811
- ) }) }),
812
- isComposer && /* @__PURE__ */ jsx8(AttachmentRemove, {})
813
- ]
814
- }
815
- ),
816
- /* @__PURE__ */ jsx8(TooltipContent, { side: "top", children: /* @__PURE__ */ jsx8(AttachmentPrimitive.Name, {}) })
817
- ] });
818
- };
819
- var AttachmentRemove = () => {
820
- return /* @__PURE__ */ jsx8(AttachmentPrimitive.Remove, { asChild: true, children: /* @__PURE__ */ jsx8(
821
- TooltipIconButton,
822
- {
823
- tooltip: "Remove file",
824
- className: "aui-attachment-tile-remove absolute top-1.5 right-1.5 size-3.5 rounded-full bg-white text-muted-foreground opacity-100 shadow-sm hover:!bg-white [&_svg]:text-black hover:[&_svg]:text-destructive",
825
- side: "top",
826
- children: /* @__PURE__ */ jsx8(XIcon2, { className: "aui-attachment-remove-icon size-3 dark:stroke-[2.5px]" })
827
- }
828
- ) });
829
- };
830
- var UserMessageAttachments = () => {
831
- return /* @__PURE__ */ jsx8("div", { className: "aui-user-message-attachments-end col-span-full col-start-1 row-start-1 flex w-full flex-row justify-end gap-2", children: /* @__PURE__ */ jsx8(MessagePrimitive.Attachments, { components: { Attachment: AttachmentUI } }) });
832
- };
833
- var ComposerAttachments = () => {
834
- return /* @__PURE__ */ jsx8("div", { className: "aui-composer-attachments mb-2 flex w-full flex-row items-center gap-2 overflow-x-auto px-1.5 pt-0.5 pb-1 empty:hidden", children: /* @__PURE__ */ jsx8(
835
- ComposerPrimitive.Attachments,
836
- {
837
- components: { Attachment: AttachmentUI }
838
- }
839
- ) });
840
- };
841
- var ComposerAddAttachment = () => {
842
- return /* @__PURE__ */ jsx8(ComposerPrimitive.AddAttachment, { asChild: true, children: /* @__PURE__ */ jsx8(
843
- TooltipIconButton,
844
- {
845
- tooltip: "Add Attachment",
846
- side: "bottom",
847
- variant: "ghost",
848
- size: "icon",
849
- className: "aui-composer-add-attachment size-[34px] rounded-full p-1 text-xs font-semibold hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30",
850
- "aria-label": "Add Attachment",
851
- children: /* @__PURE__ */ jsx8(PlusIcon, { className: "aui-attachment-add-icon size-5 stroke-[1.5px]" })
852
- }
853
- ) });
854
- };
855
-
856
- // src/lib/thread-context.tsx
857
- import { createContext, useContext, useState as useState4, useCallback } from "react";
858
- import { jsx as jsx9 } from "react/jsx-runtime";
859
- function generateSessionId() {
860
- return crypto.randomUUID();
861
- }
862
- var ThreadContext = createContext(null);
863
- function useThreadContext() {
864
- const context = useContext(ThreadContext);
865
- if (!context) {
866
- throw new Error(
867
- "useThreadContext must be used within ThreadContextProvider. Wrap your app with <ThreadContextProvider>...</ThreadContextProvider>"
868
- );
869
- }
870
- return context;
871
- }
872
- function ThreadContextProvider({
873
- children,
874
- initialThreadId
875
- }) {
876
- const [generateThreadId] = useState4(() => {
877
- const id = initialThreadId || generateSessionId();
878
- console.log("\u{1F535} [ThreadContext] Initialized with thread ID:", id);
879
- return id;
880
- });
881
- const [threadCnt, setThreadCnt] = useState4(1);
882
- const [threads, setThreads] = useState4(
883
- () => /* @__PURE__ */ new Map([[generateThreadId, []]])
884
- );
885
- const [threadMetadata, setThreadMetadata] = useState4(
886
- () => /* @__PURE__ */ new Map([
887
- [
888
- generateThreadId,
889
- { title: "New Chat", status: "pending", lastActiveAt: (/* @__PURE__ */ new Date()).toISOString() }
890
- ]
891
- ])
892
- );
893
- const ensureThreadExists = useCallback(
894
- (threadId) => {
895
- setThreadMetadata((prev) => {
896
- if (prev.has(threadId)) return prev;
897
- const next = new Map(prev);
898
- next.set(threadId, { title: "New Chat", status: "regular", lastActiveAt: (/* @__PURE__ */ new Date()).toISOString() });
899
- return next;
900
- });
901
- setThreads((prev) => {
902
- if (prev.has(threadId)) return prev;
903
- const next = new Map(prev);
904
- next.set(threadId, []);
905
- return next;
906
- });
907
- },
908
- []
909
- );
910
- const [currentThreadId, _setCurrentThreadId] = useState4(generateThreadId);
911
- const [threadViewKey, setThreadViewKey] = useState4(0);
912
- const bumpThreadViewKey = useCallback(() => {
913
- setThreadViewKey((prev) => prev + 1);
914
- }, []);
915
- const setCurrentThreadId = useCallback(
916
- (threadId) => {
917
- ensureThreadExists(threadId);
918
- _setCurrentThreadId(threadId);
919
- },
920
- [ensureThreadExists]
921
- );
922
- const getThreadMessages = useCallback(
923
- (threadId) => {
924
- return threads.get(threadId) || [];
925
- },
926
- [threads]
927
- );
928
- const setThreadMessages = useCallback(
929
- (threadId, messages) => {
930
- setThreads((prev) => {
931
- const next = new Map(prev);
932
- next.set(threadId, messages);
933
- return next;
934
- });
935
- },
936
- []
937
- );
938
- const getThreadMetadata = useCallback(
939
- (threadId) => {
940
- return threadMetadata.get(threadId);
941
- },
942
- [threadMetadata]
943
- );
944
- const updateThreadMetadata = useCallback(
945
- (threadId, updates) => {
946
- setThreadMetadata((prev) => {
947
- const existing = prev.get(threadId);
948
- if (!existing) {
949
- console.warn(`Thread metadata not found for threadId: ${threadId}`);
950
- return prev;
951
- }
952
- const next = new Map(prev);
953
- next.set(threadId, __spreadValues(__spreadValues({}, existing), updates));
954
- return next;
955
- });
956
- },
957
- []
958
- );
959
- const value = {
960
- currentThreadId,
961
- setCurrentThreadId,
962
- threadViewKey,
963
- bumpThreadViewKey,
964
- threads,
965
- setThreads,
966
- threadMetadata,
967
- setThreadMetadata,
968
- threadCnt,
969
- setThreadCnt,
970
- getThreadMessages,
971
- setThreadMessages,
972
- getThreadMetadata,
973
- updateThreadMetadata
974
- };
975
- return /* @__PURE__ */ jsx9(ThreadContext.Provider, { value, children });
976
- }
977
- function useCurrentThreadMetadata() {
978
- const { currentThreadId, getThreadMetadata } = useThreadContext();
979
- return getThreadMetadata(currentThreadId);
980
- }
981
-
982
- // src/components/assistant-ui/thread.tsx
983
- import { useAssistantApi as useAssistantApi2 } from "@assistant-ui/react";
984
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
985
- var Thread = () => {
986
- const api = useAssistantApi2();
987
- const { threadViewKey } = useThreadContext();
988
- useEffect2(() => {
989
- var _a;
990
- try {
991
- const composer = api.composer();
992
- composer.setText("");
993
- void ((_a = composer.clearAttachments) == null ? void 0 : _a.call(composer));
994
- } catch (error) {
995
- console.error("Failed to reset composer input:", error);
996
- }
997
- }, [api, threadViewKey]);
998
- return /* @__PURE__ */ jsx10(LazyMotion, { features: domAnimation, children: /* @__PURE__ */ jsx10(MotionConfig, { reducedMotion: "user", children: /* @__PURE__ */ jsx10(
999
- ThreadPrimitive.Root,
1000
- {
1001
- className: "aui-root aui-thread-root @container flex h-full flex-col bg-background",
1002
- style: {
1003
- ["--thread-max-width"]: "44rem"
1004
- },
1005
- children: /* @__PURE__ */ jsxs7(ThreadPrimitive.Viewport, { className: "aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll px-4", children: [
1006
- /* @__PURE__ */ jsx10(ThreadPrimitive.If, { empty: true, children: /* @__PURE__ */ jsx10(ThreadWelcome, {}) }),
1007
- /* @__PURE__ */ jsx10(
1008
- ThreadPrimitive.Messages,
1009
- {
1010
- components: {
1011
- UserMessage,
1012
- EditComposer,
1013
- AssistantMessage,
1014
- SystemMessage
1015
- }
1016
- }
1017
- ),
1018
- /* @__PURE__ */ jsx10(ThreadPrimitive.If, { empty: false, children: /* @__PURE__ */ jsx10("div", { className: "aui-thread-viewport-spacer min-h-8 grow" }) }),
1019
- /* @__PURE__ */ jsx10(Composer, {})
1020
- ] })
1021
- }
1022
- ) }) });
1023
- };
1024
- var ThreadScrollToBottom = () => {
1025
- return /* @__PURE__ */ jsx10(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx10(
1026
- TooltipIconButton,
1027
- {
1028
- tooltip: "Scroll to bottom",
1029
- variant: "outline",
1030
- className: "aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center rounded-full p-4 disabled:invisible dark:bg-background dark:hover:bg-accent",
1031
- children: /* @__PURE__ */ jsx10(ArrowDownIcon, {})
1032
- }
1033
- ) });
1034
- };
1035
- var ThreadWelcome = () => {
1036
- return /* @__PURE__ */ jsxs7("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-[var(--thread-max-width)] flex-grow flex-col", children: [
1037
- /* @__PURE__ */ jsx10("div", { className: "aui-thread-welcome-center flex w-full flex-grow flex-col items-center justify-center", children: /* @__PURE__ */ jsxs7("div", { className: "aui-thread-welcome-message flex size-full flex-col justify-center px-8", children: [
1038
- /* @__PURE__ */ jsx10(
1039
- m.div,
1040
- {
1041
- initial: { opacity: 0, y: 10 },
1042
- animate: { opacity: 1, y: 0 },
1043
- exit: { opacity: 0, y: 10 },
1044
- className: "aui-thread-welcome-message-motion-1 text-2xl font-semibold",
1045
- children: "Hello there!"
1046
- }
1047
- ),
1048
- /* @__PURE__ */ jsx10(
1049
- m.div,
1050
- {
1051
- initial: { opacity: 0, y: 10 },
1052
- animate: { opacity: 1, y: 0 },
1053
- exit: { opacity: 0, y: 10 },
1054
- transition: { delay: 0.1 },
1055
- className: "aui-thread-welcome-message-motion-2 text-2xl text-muted-foreground/65",
1056
- children: "How can I help you today?"
1057
- }
1058
- )
1059
- ] }) }),
1060
- /* @__PURE__ */ jsx10(ThreadSuggestions, {})
1061
- ] });
1062
- };
1063
- var ThreadSuggestions = () => {
1064
- return /* @__PURE__ */ jsx10("div", { className: "aui-thread-welcome-suggestions grid w-full gap-2 pb-4 @md:grid-cols-2", children: [
1065
- {
1066
- title: "Show my wallet balances",
1067
- label: "and positions",
1068
- action: "Show my wallet balances and positions"
1069
- },
1070
- {
1071
- title: "Swap 1 ETH to USDC",
1072
- label: "with the best price",
1073
- action: "Swap 1 ETH to USDC with the best price"
1074
- },
1075
- {
1076
- title: "Stake half of my ETH",
1077
- label: "in the highest yield pool",
1078
- action: "Stake half of my ETH in the highest yield pool"
1079
- },
1080
- {
1081
- title: "Bridge 100 USDC",
1082
- label: "from Ethereum to Arbitrum",
1083
- action: "Bridge 100 USDC from Ethereum to Arbitrum"
1084
- }
1085
- ].map((suggestedAction, index) => /* @__PURE__ */ jsx10(
1086
- m.div,
1087
- {
1088
- initial: { opacity: 0, y: 20 },
1089
- animate: { opacity: 1, y: 0 },
1090
- exit: { opacity: 0, y: 20 },
1091
- transition: { delay: 0.05 * index },
1092
- className: "aui-thread-welcome-suggestion-display [&:nth-child(n+3)]:hidden @md:[&:nth-child(n+3)]:block",
1093
- children: /* @__PURE__ */ jsx10(
1094
- ThreadPrimitive.Suggestion,
1095
- {
1096
- prompt: suggestedAction.action,
1097
- send: true,
1098
- asChild: true,
1099
- children: /* @__PURE__ */ jsxs7(
1100
- Button,
1101
- {
1102
- variant: "ghost",
1103
- className: "aui-thread-welcome-suggestion h-auto w-full flex-1 flex-wrap items-start justify-start gap-1 rounded-3xl border px-5 py-4 text-left text-sm @md:flex-col dark:hover:bg-accent/60",
1104
- "aria-label": suggestedAction.action,
1105
- children: [
1106
- /* @__PURE__ */ jsx10("span", { className: "aui-thread-welcome-suggestion-text-1 font-medium", children: suggestedAction.title }),
1107
- /* @__PURE__ */ jsx10("span", { className: "aui-thread-welcome-suggestion-text-2 text-muted-foreground", children: suggestedAction.label })
1108
- ]
1109
- }
1110
- )
1111
- }
1112
- )
1113
- },
1114
- `suggested-action-${suggestedAction.title}-${index}`
1115
- )) });
1116
- };
1117
- var Composer = () => {
1118
- return /* @__PURE__ */ jsxs7("div", { className: "aui-composer-wrapper sticky bottom-0 mx-auto flex w-full max-w-[var(--thread-max-width)] flex-col gap-4 overflow-visible rounded-t-3xl bg-background pb-4 md:pb-6", children: [
1119
- /* @__PURE__ */ jsx10(ThreadScrollToBottom, {}),
1120
- /* @__PURE__ */ jsxs7(ComposerPrimitive2.Root, { className: "aui-composer-root relative flex w-full flex-col rounded-4xl border bg-white px-1 pt-2 shadow-[0_9px_9px_0px_rgba(0,0,0,0.01),0_2px_5px_0px_rgba(0,0,0,0.06)] dark:border-muted-foreground/15", children: [
1121
- /* @__PURE__ */ jsx10(ComposerAttachments, {}),
1122
- /* @__PURE__ */ jsx10(
1123
- ComposerPrimitive2.Input,
1124
- {
1125
- placeholder: "Send a message...",
1126
- className: "aui-composer-input ml-3 mt-2 max-h-32 min-h-16 w-full resize-none bg-transparent px-3.5 pt-1.5 pb-3 text-sm outline-none placeholder:text-muted-foreground focus:outline-primary",
1127
- rows: 1,
1128
- autoFocus: true,
1129
- "aria-label": "Message input"
1130
- }
1131
- ),
1132
- /* @__PURE__ */ jsx10(ComposerAction, {})
1133
- ] })
1134
- ] });
1135
- };
1136
- var ComposerAction = () => {
1137
- return /* @__PURE__ */ jsxs7("div", { className: "aui-composer-action-wrapper relative mx-1 mt-2 mb-2 flex items-center justify-between", children: [
1138
- /* @__PURE__ */ jsx10(ComposerAddAttachment, {}),
1139
- /* @__PURE__ */ jsx10(ThreadPrimitive.If, { running: false, children: /* @__PURE__ */ jsx10(ComposerPrimitive2.Send, { asChild: true, children: /* @__PURE__ */ jsx10(
1140
- TooltipIconButton,
1141
- {
1142
- tooltip: "Send message",
1143
- side: "bottom",
1144
- type: "submit",
1145
- variant: "default",
1146
- size: "icon",
1147
- className: "aui-composer-send mr-3 mb-3 size-[34px] rounded-full p-1",
1148
- "aria-label": "Send message",
1149
- children: /* @__PURE__ */ jsx10(ArrowUpIcon, { className: "aui-composer-send-icon size-5" })
1150
- }
1151
- ) }) }),
1152
- /* @__PURE__ */ jsx10(ThreadPrimitive.If, { running: true, children: /* @__PURE__ */ jsx10(ComposerPrimitive2.Cancel, { asChild: true, children: /* @__PURE__ */ jsx10(
1153
- Button,
1154
- {
1155
- type: "button",
1156
- variant: "default",
1157
- size: "icon",
1158
- className: "aui-composer-cancel size-[34px] rounded-full border border-muted-foreground/60 hover:bg-primary/75 dark:border-muted-foreground/90",
1159
- "aria-label": "Stop generating",
1160
- children: /* @__PURE__ */ jsx10(Square, { className: "aui-composer-cancel-icon size-3.5 fill-white dark:fill-black" })
1161
- }
1162
- ) }) })
1163
- ] });
1164
- };
1165
- var MessageError = () => {
1166
- return /* @__PURE__ */ jsx10(MessagePrimitive2.Error, { children: /* @__PURE__ */ jsx10(ErrorPrimitive.Root, { className: "aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-sm text-destructive dark:bg-destructive/5 dark:text-red-200", children: /* @__PURE__ */ jsx10(ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
1167
- };
1168
- var AssistantMessage = () => {
1169
- return /* @__PURE__ */ jsx10(MessagePrimitive2.Root, { asChild: true, children: /* @__PURE__ */ jsxs7(
1170
- "div",
1171
- {
1172
- className: "aui-assistant-message-root relative mx-auto w-full max-w-[var(--thread-max-width)] animate-in py-4 duration-150 ease-out fade-in slide-in-from-bottom-1 last:mb-24",
1173
- "data-role": "assistant",
1174
- children: [
1175
- /* @__PURE__ */ jsxs7("div", { className: "aui-assistant-message-content text-sm mx-2 leading-5 break-words text-foreground", children: [
1176
- /* @__PURE__ */ jsx10(
1177
- MessagePrimitive2.Parts,
1178
- {
1179
- components: {
1180
- Text: MarkdownText,
1181
- tools: { Fallback: ToolFallback }
1182
- }
1183
- }
1184
- ),
1185
- /* @__PURE__ */ jsx10(MessageError, {})
1186
- ] }),
1187
- /* @__PURE__ */ jsxs7("div", { className: "aui-assistant-message-footer mt-2 ml-2 flex", children: [
1188
- /* @__PURE__ */ jsx10(BranchPicker, {}),
1189
- /* @__PURE__ */ jsx10(AssistantActionBar, {})
1190
- ] })
1191
- ]
1192
- }
1193
- ) });
1194
- };
1195
- var AssistantActionBar = () => {
1196
- return /* @__PURE__ */ jsxs7(
1197
- ActionBarPrimitive.Root,
1198
- {
1199
- hideWhenRunning: true,
1200
- autohide: "not-last",
1201
- autohideFloat: "single-branch",
1202
- className: "aui-assistant-action-bar-root col-start-3 row-start-2 -ml-1 flex gap-1 text-muted-foreground data-floating:absolute data-floating:rounded-md data-floating:border data-floating:bg-background data-floating:p-1 data-floating:shadow-sm",
1203
- children: [
1204
- /* @__PURE__ */ jsx10(ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ jsxs7(TooltipIconButton, { tooltip: "Copy", children: [
1205
- /* @__PURE__ */ jsx10(MessagePrimitive2.If, { copied: true, children: /* @__PURE__ */ jsx10(CheckIcon3, {}) }),
1206
- /* @__PURE__ */ jsx10(MessagePrimitive2.If, { copied: false, children: /* @__PURE__ */ jsx10(CopyIcon2, {}) })
1207
- ] }) }),
1208
- /* @__PURE__ */ jsx10(ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ jsx10(TooltipIconButton, { tooltip: "Refresh", children: /* @__PURE__ */ jsx10(RefreshCwIcon, {}) }) })
1209
- ]
1210
- }
1211
- );
1212
- };
1213
- var UserMessage = () => {
1214
- return /* @__PURE__ */ jsx10(MessagePrimitive2.Root, { asChild: true, children: /* @__PURE__ */ jsxs7(
1215
- "div",
1216
- {
1217
- className: "aui-user-message-root mx-auto grid w-full max-w-[var(--thread-max-width)] animate-in auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 px-2 py-4 duration-150 ease-out fade-in slide-in-from-bottom-1 first:mt-3 last:mb-5 [&:where(>*)]:col-start-2",
1218
- "data-role": "user",
1219
- children: [
1220
- /* @__PURE__ */ jsx10(UserMessageAttachments, {}),
1221
- /* @__PURE__ */ jsxs7("div", { className: "aui-user-message-content-wrapper relative col-start-2 min-w-0", children: [
1222
- /* @__PURE__ */ jsx10("div", { className: "aui-user-message-content text-sm rounded-3xl bg-muted px-5 py-2.5 break-words text-foreground", children: /* @__PURE__ */ jsx10(MessagePrimitive2.Parts, {}) }),
1223
- /* @__PURE__ */ jsx10("div", { className: "aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2", children: /* @__PURE__ */ jsx10(UserActionBar, {}) })
1224
- ] }),
1225
- /* @__PURE__ */ jsx10(BranchPicker, { className: "aui-user-branch-picker col-span-full col-start-1 row-start-3 -mr-1 justify-end" })
1226
- ]
1227
- }
1228
- ) });
1229
- };
1230
- var UserActionBar = () => {
1231
- return /* @__PURE__ */ jsx10(
1232
- ActionBarPrimitive.Root,
1233
- {
1234
- hideWhenRunning: true,
1235
- autohide: "not-last",
1236
- className: "aui-user-action-bar-root flex flex-col items-end",
1237
- children: /* @__PURE__ */ jsx10(ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ jsx10(TooltipIconButton, { tooltip: "Edit", className: "aui-user-action-edit p-4", children: /* @__PURE__ */ jsx10(PencilIcon, {}) }) })
1238
- }
1239
- );
1240
- };
1241
- var EditComposer = () => {
1242
- return /* @__PURE__ */ jsx10("div", { className: "aui-edit-composer-wrapper mx-auto flex w-full max-w-[var(--thread-max-width)] flex-col gap-4 px-2 first:mt-4", children: /* @__PURE__ */ jsxs7(ComposerPrimitive2.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-7/8 flex-col rounded-xl bg-muted", children: [
1243
- /* @__PURE__ */ jsx10(
1244
- ComposerPrimitive2.Input,
1245
- {
1246
- className: "aui-edit-composer-input flex min-h-[60px] w-full resize-none bg-transparent p-4 text-foreground outline-none",
1247
- autoFocus: true
1248
- }
1249
- ),
1250
- /* @__PURE__ */ jsxs7("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center justify-center gap-2 self-end", children: [
1251
- /* @__PURE__ */ jsx10(ComposerPrimitive2.Cancel, { asChild: true, children: /* @__PURE__ */ jsx10(Button, { variant: "ghost", size: "sm", "aria-label": "Cancel edit", children: "Cancel" }) }),
1252
- /* @__PURE__ */ jsx10(ComposerPrimitive2.Send, { asChild: true, children: /* @__PURE__ */ jsx10(Button, { size: "sm", "aria-label": "Update message", children: "Update" }) })
1253
- ] })
1254
- ] }) });
1255
- };
1256
- var BranchPicker = (_a) => {
1257
- var _b = _a, {
1258
- className
1259
- } = _b, rest = __objRest(_b, [
1260
- "className"
1261
- ]);
1262
- return /* @__PURE__ */ jsxs7(
1263
- BranchPickerPrimitive.Root,
1264
- __spreadProps(__spreadValues({
1265
- hideWhenSingleBranch: true,
1266
- className: cn(
1267
- "aui-branch-picker-root mr-2 -ml-2 inline-flex items-center text-xs text-muted-foreground",
1268
- className
1269
- )
1270
- }, rest), {
1271
- children: [
1272
- /* @__PURE__ */ jsx10(BranchPickerPrimitive.Previous, { asChild: true, children: /* @__PURE__ */ jsx10(TooltipIconButton, { tooltip: "Previous", children: /* @__PURE__ */ jsx10(ChevronLeftIcon, {}) }) }),
1273
- /* @__PURE__ */ jsxs7("span", { className: "aui-branch-picker-state font-medium", children: [
1274
- /* @__PURE__ */ jsx10(BranchPickerPrimitive.Number, {}),
1275
- " / ",
1276
- /* @__PURE__ */ jsx10(BranchPickerPrimitive.Count, {})
1277
- ] }),
1278
- /* @__PURE__ */ jsx10(BranchPickerPrimitive.Next, { asChild: true, children: /* @__PURE__ */ jsx10(TooltipIconButton, { tooltip: "Next", children: /* @__PURE__ */ jsx10(ChevronRightIcon, {}) }) })
1279
- ]
1280
- })
1281
- );
1282
- };
1283
- var SystemMessage = () => {
1284
- return /* @__PURE__ */ jsx10(MessagePrimitive2.Root, { asChild: true, children: /* @__PURE__ */ jsx10(
1285
- "div",
1286
- {
1287
- className: "aui-system-message-root mx-auto w-full max-w-[var(--thread-max-width)] px-2 py-4 animate-in fade-in slide-in-from-bottom-1",
1288
- "data-role": "system",
1289
- children: /* @__PURE__ */ jsxs7("div", { className: "aui-system-message-card flex w-full flex-wrap items-start gap-3 rounded-3xl border px-5 py-4 text-left text-sm bg-background/70 dark:bg-muted/30", children: [
1290
- /* @__PURE__ */ jsx10(AlertCircleIcon, { className: "aui-system-message-icon mt-0.5 size-4 shrink-0 text-blue-500 dark:text-blue-300" }),
1291
- /* @__PURE__ */ jsxs7("div", { className: "aui-system-message-body flex flex-col gap-1", children: [
1292
- /* @__PURE__ */ jsx10("span", { className: "aui-system-message-title font-medium text-foreground", children: "System notice" }),
1293
- /* @__PURE__ */ jsx10("div", { className: "aui-system-message-content leading-relaxed text-muted-foreground", children: /* @__PURE__ */ jsx10(MessagePrimitive2.Parts, { components: { Text: MarkdownText } }) })
1294
- ] })
1295
- ] })
1296
- }
1297
- ) });
1298
- };
1299
-
1300
- // src/components/assistant-ui/threadlist-sidebar.tsx
1301
- import Link from "next/link";
1302
- import Image3 from "next/image";
1303
-
1304
- // src/components/ui/sidebar.tsx
1305
- import * as React2 from "react";
1306
- import { Slot as Slot2 } from "@radix-ui/react-slot";
1307
- import { cva as cva2 } from "class-variance-authority";
1308
- import { PanelLeftIcon } from "lucide-react";
1309
-
1310
- // src/hooks/use-mobile.ts
1311
- import * as React from "react";
1312
- var MOBILE_BREAKPOINT = 768;
1313
- function useIsMobile() {
1314
- const [isMobile, setIsMobile] = React.useState(
1315
- void 0
1316
- );
1317
- React.useEffect(() => {
1318
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
1319
- const onChange = () => {
1320
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
1321
- };
1322
- mql.addEventListener("change", onChange);
1323
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
1324
- return () => mql.removeEventListener("change", onChange);
1325
- }, []);
1326
- return !!isMobile;
1327
- }
1328
-
1329
- // src/components/ui/input.tsx
1330
- import { jsx as jsx11 } from "react/jsx-runtime";
1331
- function Input(_a) {
1332
- var _b = _a, { className, type } = _b, props = __objRest(_b, ["className", "type"]);
1333
- return /* @__PURE__ */ jsx11(
1334
- "input",
1335
- __spreadValues({
1336
- type,
1337
- "data-slot": "input",
1338
- className: cn(
1339
- "flex h-9 w-full min-w-0 rounded-md border-sm border-input bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30",
1340
- "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
1341
- "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
1342
- className
1343
- )
1344
- }, props)
1345
- );
1346
- }
1347
-
1348
- // src/components/ui/separator.tsx
1349
- import * as SeparatorPrimitive from "@radix-ui/react-separator";
1350
- import { jsx as jsx12 } from "react/jsx-runtime";
1351
- function Separator(_a) {
1352
- var _b = _a, {
1353
- className,
1354
- orientation = "horizontal",
1355
- decorative = true
1356
- } = _b, props = __objRest(_b, [
1357
- "className",
1358
- "orientation",
1359
- "decorative"
1360
- ]);
1361
- return /* @__PURE__ */ jsx12(
1362
- SeparatorPrimitive.Root,
1363
- __spreadValues({
1364
- "data-slot": "separator",
1365
- decorative,
1366
- orientation,
1367
- className: cn(
1368
- "shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
1369
- className
1370
- )
1371
- }, props)
1372
- );
1373
- }
1374
-
1375
- // src/components/ui/sheet.tsx
1376
- import * as SheetPrimitive from "@radix-ui/react-dialog";
1377
- import { XIcon as XIcon3 } from "lucide-react";
1378
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1379
- function Sheet(_a) {
1380
- var props = __objRest(_a, []);
1381
- return /* @__PURE__ */ jsx13(SheetPrimitive.Root, __spreadValues({ "data-slot": "sheet" }, props));
1382
- }
1383
- function SheetTrigger(_a) {
1384
- var props = __objRest(_a, []);
1385
- return /* @__PURE__ */ jsx13(SheetPrimitive.Trigger, __spreadValues({ "data-slot": "sheet-trigger" }, props));
1386
- }
1387
- function SheetClose(_a) {
1388
- var props = __objRest(_a, []);
1389
- return /* @__PURE__ */ jsx13(SheetPrimitive.Close, __spreadValues({ "data-slot": "sheet-close" }, props));
1390
- }
1391
- function SheetPortal(_a) {
1392
- var props = __objRest(_a, []);
1393
- return /* @__PURE__ */ jsx13(SheetPrimitive.Portal, __spreadValues({ "data-slot": "sheet-portal" }, props));
1394
- }
1395
- function SheetOverlay(_a) {
1396
- var _b = _a, {
1397
- className
1398
- } = _b, props = __objRest(_b, [
1399
- "className"
1400
- ]);
1401
- return /* @__PURE__ */ jsx13(
1402
- SheetPrimitive.Overlay,
1403
- __spreadValues({
1404
- "data-slot": "sheet-overlay",
1405
- className: cn(
1406
- "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
1407
- className
1408
- )
1409
- }, props)
1410
- );
1411
- }
1412
- function SheetContent(_a) {
1413
- var _b = _a, {
1414
- className,
1415
- children,
1416
- side = "right"
1417
- } = _b, props = __objRest(_b, [
1418
- "className",
1419
- "children",
1420
- "side"
1421
- ]);
1422
- return /* @__PURE__ */ jsxs8(SheetPortal, { children: [
1423
- /* @__PURE__ */ jsx13(SheetOverlay, {}),
1424
- /* @__PURE__ */ jsxs8(
1425
- SheetPrimitive.Content,
1426
- __spreadProps(__spreadValues({
1427
- "data-slot": "sheet-content",
1428
- className: cn(
1429
- "fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:animate-in data-[state=open]:duration-500",
1430
- side === "right" && "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
1431
- side === "left" && "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
1432
- side === "top" && "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
1433
- side === "bottom" && "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
1434
- className
1435
- )
1436
- }, props), {
1437
- children: [
1438
- children,
1439
- /* @__PURE__ */ jsxs8(SheetPrimitive.Close, { className: "absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-secondary", children: [
1440
- /* @__PURE__ */ jsx13(XIcon3, { className: "size-4" }),
1441
- /* @__PURE__ */ jsx13("span", { className: "sr-only", children: "Close" })
1442
- ] })
1443
- ]
1444
- })
1445
- )
1446
- ] });
1447
- }
1448
- function SheetHeader(_a) {
1449
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1450
- return /* @__PURE__ */ jsx13(
1451
- "div",
1452
- __spreadValues({
1453
- "data-slot": "sheet-header",
1454
- className: cn("flex flex-col gap-1.5 p-4", className)
1455
- }, props)
1456
- );
1457
- }
1458
- function SheetFooter(_a) {
1459
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1460
- return /* @__PURE__ */ jsx13(
1461
- "div",
1462
- __spreadValues({
1463
- "data-slot": "sheet-footer",
1464
- className: cn("mt-auto flex flex-col gap-2 p-4", className)
1465
- }, props)
1466
- );
1467
- }
1468
- function SheetTitle(_a) {
1469
- var _b = _a, {
1470
- className
1471
- } = _b, props = __objRest(_b, [
1472
- "className"
1473
- ]);
1474
- return /* @__PURE__ */ jsx13(
1475
- SheetPrimitive.Title,
1476
- __spreadValues({
1477
- "data-slot": "sheet-title",
1478
- className: cn("font-semibold text-foreground", className)
1479
- }, props)
1480
- );
1481
- }
1482
- function SheetDescription(_a) {
1483
- var _b = _a, {
1484
- className
1485
- } = _b, props = __objRest(_b, [
1486
- "className"
1487
- ]);
1488
- return /* @__PURE__ */ jsx13(
1489
- SheetPrimitive.Description,
1490
- __spreadValues({
1491
- "data-slot": "sheet-description",
1492
- className: cn("text-sm text-muted-foreground", className)
1493
- }, props)
1494
- );
1495
- }
1496
-
1497
- // src/components/ui/skeleton.tsx
1498
- import { jsx as jsx14 } from "react/jsx-runtime";
1499
- function Skeleton(_a) {
1500
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1501
- return /* @__PURE__ */ jsx14(
1502
- "div",
1503
- __spreadValues({
1504
- "data-slot": "skeleton",
1505
- className: cn("animate-pulse rounded-md bg-accent", className)
1506
- }, props)
1507
- );
1508
- }
1509
-
1510
- // src/components/ui/sidebar.tsx
1511
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1512
- var SIDEBAR_COOKIE_NAME = "sidebar_state";
1513
- var SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
1514
- var SIDEBAR_WIDTH_MOBILE = "18rem";
1515
- var SIDEBAR_WIDTH_ICON = "3rem";
1516
- var SIDEBAR_KEYBOARD_SHORTCUT = "b";
1517
- var SIDEBAR_MIN_WIDTH = 100;
1518
- var SIDEBAR_MAX_WIDTH = 200;
1519
- var SidebarContext = React2.createContext(null);
1520
- function useSidebar() {
1521
- const context = React2.useContext(SidebarContext);
1522
- if (!context) {
1523
- throw new Error("useSidebar must be used within a SidebarProvider.");
1524
- }
1525
- return context;
1526
- }
1527
- function SidebarProvider(_a) {
1528
- var _b = _a, {
1529
- defaultOpen = true,
1530
- open: openProp,
1531
- onOpenChange: setOpenProp,
1532
- className,
1533
- style,
1534
- children
1535
- } = _b, props = __objRest(_b, [
1536
- "defaultOpen",
1537
- "open",
1538
- "onOpenChange",
1539
- "className",
1540
- "style",
1541
- "children"
1542
- ]);
1543
- const isMobile = useIsMobile();
1544
- const [openMobile, setOpenMobile] = React2.useState(false);
1545
- const [_open, _setOpen] = React2.useState(defaultOpen);
1546
- const open = openProp != null ? openProp : _open;
1547
- const [sidebarWidth, setSidebarWidth] = React2.useState(256);
1548
- const setOpen = React2.useCallback(
1549
- (value) => {
1550
- const openState = typeof value === "function" ? value(open) : value;
1551
- if (setOpenProp) {
1552
- setOpenProp(openState);
1553
- } else {
1554
- _setOpen(openState);
1555
- }
1556
- document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
1557
- },
1558
- [setOpenProp, open]
1559
- );
1560
- const toggleSidebar = React2.useCallback(() => {
1561
- return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
1562
- }, [isMobile, setOpen, setOpenMobile]);
1563
- React2.useEffect(() => {
1564
- const handleKeyDown = (event) => {
1565
- if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
1566
- event.preventDefault();
1567
- toggleSidebar();
1568
- }
1569
- };
1570
- window.addEventListener("keydown", handleKeyDown);
1571
- return () => window.removeEventListener("keydown", handleKeyDown);
1572
- }, [toggleSidebar]);
1573
- const state = open ? "expanded" : "collapsed";
1574
- const contextValue = React2.useMemo(
1575
- () => ({
1576
- state,
1577
- open,
1578
- setOpen,
1579
- isMobile,
1580
- openMobile,
1581
- setOpenMobile,
1582
- toggleSidebar,
1583
- sidebarWidth,
1584
- setSidebarWidth
1585
- }),
1586
- [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar, sidebarWidth]
1587
- );
1588
- return /* @__PURE__ */ jsx15(SidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx15(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx15(
1589
- "div",
1590
- __spreadProps(__spreadValues({
1591
- "data-slot": "sidebar-wrapper",
1592
- style: __spreadValues({
1593
- "--sidebar-width": `${sidebarWidth}px`,
1594
- "--sidebar-width-icon": SIDEBAR_WIDTH_ICON
1595
- }, style),
1596
- className: cn(
1597
- "group/sidebar-wrapper flex h-full w-full has-data-[variant=offcanvas]:bg-sidebar",
1598
- className
1599
- )
1600
- }, props), {
1601
- children
1602
- })
1603
- ) }) });
1604
- }
1605
- function Sidebar(_a) {
1606
- var _b = _a, {
1607
- side = "left",
1608
- variant = "sidebar",
1609
- collapsible = "offcanvas",
1610
- className,
1611
- children
1612
- } = _b, props = __objRest(_b, [
1613
- "side",
1614
- "variant",
1615
- "collapsible",
1616
- "className",
1617
- "children"
1618
- ]);
1619
- const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
1620
- if (collapsible === "none") {
1621
- return /* @__PURE__ */ jsx15(
1622
- "div",
1623
- __spreadProps(__spreadValues({
1624
- "data-slot": "sidebar",
1625
- className: cn(
1626
- "flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground",
1627
- className
1628
- )
1629
- }, props), {
1630
- children
1631
- })
1632
- );
1633
- }
1634
- if (isMobile) {
1635
- return /* @__PURE__ */ jsx15(Sheet, __spreadProps(__spreadValues({ open: openMobile, onOpenChange: setOpenMobile }, props), { children: /* @__PURE__ */ jsxs9(
1636
- SheetContent,
1637
- {
1638
- "data-sidebar": "sidebar",
1639
- "data-slot": "sidebar",
1640
- "data-mobile": "true",
1641
- className: "w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden",
1642
- style: {
1643
- "--sidebar-width": SIDEBAR_WIDTH_MOBILE
1644
- },
1645
- side,
1646
- children: [
1647
- /* @__PURE__ */ jsxs9(SheetHeader, { className: "sr-only", children: [
1648
- /* @__PURE__ */ jsx15(SheetTitle, { children: "Sidebar" }),
1649
- /* @__PURE__ */ jsx15(SheetDescription, { children: "Displays the mobile sidebar." })
1650
- ] }),
1651
- /* @__PURE__ */ jsx15("div", { className: "flex h-full w-full flex-col", children })
1652
- ]
1653
- }
1654
- ) }));
1655
- }
1656
- return /* @__PURE__ */ jsxs9(
1657
- "div",
1658
- {
1659
- className: cn(
1660
- "relative group peer hidden text-sidebar-foreground md:block",
1661
- "w-[var(--sidebar-width)]",
1662
- "data-[collapsible=offcanvas]:w-0",
1663
- "transition-[width] duration-200 ease-linear"
1664
- ),
1665
- "data-state": state,
1666
- "data-collapsible": state === "collapsed" ? collapsible : "",
1667
- "data-variant": variant,
1668
- "data-side": side,
1669
- "data-slot": "sidebar",
1670
- children: [
1671
- /* @__PURE__ */ jsx15(
1672
- "div",
1673
- {
1674
- "data-slot": "sidebar-gap",
1675
- className: cn(
1676
- "relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
1677
- "group-data-[collapsible=offcanvas]:w-0",
1678
- "group-data-[side=right]:rotate-180",
1679
- variant === "floating" || variant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
1680
- )
1681
- }
1682
- ),
1683
- /* @__PURE__ */ jsx15(
1684
- "div",
1685
- __spreadProps(__spreadValues({
1686
- "data-slot": "sidebar-container",
1687
- className: cn(
1688
- "fixed inset-y-0 z-10 hidden h-full w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
1689
- side === "left" ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
1690
- // Adjust the padding for floating and inset variants.
1691
- variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
1692
- className
1693
- )
1694
- }, props), {
1695
- children: /* @__PURE__ */ jsx15(
1696
- "div",
1697
- {
1698
- "data-sidebar": "sidebar",
1699
- "data-slot": "sidebar-inner",
1700
- className: "flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm",
1701
- children
1702
- }
1703
- )
1704
- })
1705
- )
1706
- ]
1707
- }
1708
- );
1709
- }
1710
- function SidebarTrigger(_a) {
1711
- var _b = _a, {
1712
- className,
1713
- onClick
1714
- } = _b, props = __objRest(_b, [
1715
- "className",
1716
- "onClick"
1717
- ]);
1718
- const { toggleSidebar } = useSidebar();
1719
- return /* @__PURE__ */ jsxs9(
1720
- Button,
1721
- __spreadProps(__spreadValues({
1722
- "data-sidebar": "trigger",
1723
- "data-slot": "sidebar-trigger",
1724
- variant: "ghost",
1725
- size: "icon",
1726
- className: cn("size-7", className),
1727
- onClick: (event) => {
1728
- onClick == null ? void 0 : onClick(event);
1729
- toggleSidebar();
1730
- }
1731
- }, props), {
1732
- children: [
1733
- /* @__PURE__ */ jsx15(PanelLeftIcon, {}),
1734
- /* @__PURE__ */ jsx15("span", { className: "sr-only", children: "Toggle Sidebar" })
1735
- ]
1736
- })
1737
- );
1738
- }
1739
- function SidebarRail(_a) {
1740
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1741
- const { toggleSidebar, sidebarWidth, setSidebarWidth, setOpen } = useSidebar();
1742
- const isDraggingRef = React2.useRef(false);
1743
- const startXRef = React2.useRef(0);
1744
- const startWidthRef = React2.useRef(0);
1745
- const hasDraggedRef = React2.useRef(false);
1746
- const rafRef = React2.useRef(null);
1747
- const handleMouseDown = React2.useCallback(
1748
- (e) => {
1749
- e.preventDefault();
1750
- isDraggingRef.current = true;
1751
- hasDraggedRef.current = false;
1752
- startXRef.current = e.clientX;
1753
- startWidthRef.current = sidebarWidth;
1754
- document.body.style.cursor = "ew-resize";
1755
- document.body.style.userSelect = "none";
1756
- },
1757
- [sidebarWidth]
1758
- );
1759
- React2.useEffect(() => {
1760
- const handleMouseMove = (e) => {
1761
- if (!isDraggingRef.current) return;
1762
- if (rafRef.current) {
1763
- cancelAnimationFrame(rafRef.current);
1764
- }
1765
- rafRef.current = requestAnimationFrame(() => {
1766
- const deltaX = e.clientX - startXRef.current;
1767
- if (Math.abs(deltaX) > 5) {
1768
- hasDraggedRef.current = true;
1769
- }
1770
- const rawWidth = startWidthRef.current + deltaX;
1771
- if (rawWidth < SIDEBAR_MIN_WIDTH) {
1772
- setOpen(false);
1773
- } else {
1774
- setOpen(true);
1775
- setSidebarWidth(Math.min(SIDEBAR_MAX_WIDTH, rawWidth));
1776
- }
1777
- });
1778
- };
1779
- const handleMouseUp = () => {
1780
- if (!isDraggingRef.current) return;
1781
- isDraggingRef.current = false;
1782
- document.body.style.cursor = "";
1783
- document.body.style.userSelect = "";
1784
- if (rafRef.current) {
1785
- cancelAnimationFrame(rafRef.current);
1786
- }
1787
- };
1788
- document.addEventListener("mousemove", handleMouseMove);
1789
- document.addEventListener("mouseup", handleMouseUp);
1790
- return () => {
1791
- document.removeEventListener("mousemove", handleMouseMove);
1792
- document.removeEventListener("mouseup", handleMouseUp);
1793
- };
1794
- }, [setSidebarWidth, setOpen]);
1795
- const handleClick = React2.useCallback(() => {
1796
- if (!hasDraggedRef.current) {
1797
- toggleSidebar();
1798
- }
1799
- }, [toggleSidebar]);
1800
- return /* @__PURE__ */ jsx15(
1801
- "button",
1802
- __spreadValues({
1803
- "data-sidebar": "rail",
1804
- "data-slot": "sidebar-rail",
1805
- "aria-label": "Toggle Sidebar",
1806
- tabIndex: -1,
1807
- onMouseDown: handleMouseDown,
1808
- onClick: handleClick,
1809
- title: "Drag to resize, click to toggle",
1810
- className: cn(
1811
- "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex",
1812
- "cursor-ew-resize",
1813
- "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar",
1814
- "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
1815
- "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
1816
- className
1817
- )
1818
- }, props)
1819
- );
1820
- }
1821
- function SidebarInset(_a) {
1822
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1823
- return /* @__PURE__ */ jsx15(
1824
- "main",
1825
- __spreadValues({
1826
- "data-slot": "sidebar-inset",
1827
- className: cn("relative flex w-full flex-1 flex-col bg-background", className)
1828
- }, props)
1829
- );
1830
- }
1831
- function SidebarHeader(_a) {
1832
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1833
- return /* @__PURE__ */ jsx15(
1834
- "div",
1835
- __spreadValues({
1836
- "data-slot": "sidebar-header",
1837
- "data-sidebar": "header",
1838
- className: cn("flex flex-col gap-2 p-2", className)
1839
- }, props)
1840
- );
1841
- }
1842
- function SidebarFooter(_a) {
1843
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1844
- return /* @__PURE__ */ jsx15(
1845
- "div",
1846
- __spreadValues({
1847
- "data-slot": "sidebar-footer",
1848
- "data-sidebar": "footer",
1849
- className: cn("flex mr-2 flex-col gap-2 p-2", className)
1850
- }, props)
1851
- );
1852
- }
1853
- function SidebarSeparator(_a) {
1854
- var _b = _a, {
1855
- className
1856
- } = _b, props = __objRest(_b, [
1857
- "className"
1858
- ]);
1859
- return /* @__PURE__ */ jsx15(
1860
- Separator,
1861
- __spreadValues({
1862
- "data-slot": "sidebar-separator",
1863
- "data-sidebar": "separator",
1864
- className: cn("mx-2 w-auto bg-sidebar-border", className)
1865
- }, props)
1866
- );
1867
- }
1868
- function SidebarContent(_a) {
1869
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1870
- return /* @__PURE__ */ jsx15(
1871
- "div",
1872
- __spreadValues({
1873
- "data-slot": "sidebar-content",
1874
- "data-sidebar": "content",
1875
- className: cn(
1876
- "flex mr-2 min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
1877
- className
1878
- )
1879
- }, props)
1880
- );
1881
- }
1882
- function SidebarGroup(_a) {
1883
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1884
- return /* @__PURE__ */ jsx15(
1885
- "div",
1886
- __spreadValues({
1887
- "data-slot": "sidebar-group",
1888
- "data-sidebar": "group",
1889
- className: cn("relative flex w-full min-w-0 flex-col p-2", className)
1890
- }, props)
1891
- );
1892
- }
1893
- function SidebarGroupLabel(_a) {
1894
- var _b = _a, {
1895
- className,
1896
- asChild = false
1897
- } = _b, props = __objRest(_b, [
1898
- "className",
1899
- "asChild"
1900
- ]);
1901
- const Comp = asChild ? Slot2 : "div";
1902
- return /* @__PURE__ */ jsx15(
1903
- Comp,
1904
- __spreadValues({
1905
- "data-slot": "sidebar-group-label",
1906
- "data-sidebar": "group-label",
1907
- className: cn(
1908
- "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
1909
- "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
1910
- className
1911
- )
1912
- }, props)
1913
- );
1914
- }
1915
- function SidebarGroupAction(_a) {
1916
- var _b = _a, {
1917
- className,
1918
- asChild = false
1919
- } = _b, props = __objRest(_b, [
1920
- "className",
1921
- "asChild"
1922
- ]);
1923
- const Comp = asChild ? Slot2 : "button";
1924
- return /* @__PURE__ */ jsx15(
1925
- Comp,
1926
- __spreadValues({
1927
- "data-slot": "sidebar-group-action",
1928
- "data-sidebar": "group-action",
1929
- className: cn(
1930
- "absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
1931
- // Increases the hit area of the button on mobile.
1932
- "after:absolute after:-inset-2 md:after:hidden",
1933
- "group-data-[collapsible=icon]:hidden",
1934
- className
1935
- )
1936
- }, props)
1937
- );
1938
- }
1939
- function SidebarGroupContent(_a) {
1940
- var _b = _a, {
1941
- className
1942
- } = _b, props = __objRest(_b, [
1943
- "className"
1944
- ]);
1945
- return /* @__PURE__ */ jsx15(
1946
- "div",
1947
- __spreadValues({
1948
- "data-slot": "sidebar-group-content",
1949
- "data-sidebar": "group-content",
1950
- className: cn("w-full text-sm", className)
1951
- }, props)
1952
- );
1953
- }
1954
- function SidebarMenu(_a) {
1955
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1956
- return /* @__PURE__ */ jsx15(
1957
- "ul",
1958
- __spreadValues({
1959
- "data-slot": "sidebar-menu",
1960
- "data-sidebar": "menu",
1961
- className: cn("flex w-full min-w-0 flex-col gap-1", className)
1962
- }, props)
1963
- );
1964
- }
1965
- function SidebarMenuItem(_a) {
1966
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1967
- return /* @__PURE__ */ jsx15(
1968
- "li",
1969
- __spreadValues({
1970
- "data-slot": "sidebar-menu-item",
1971
- "data-sidebar": "menu-item",
1972
- className: cn("group/menu-item relative", className)
1973
- }, props)
1974
- );
1975
- }
1976
- var sidebarMenuButtonVariants = cva2(
1977
- "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
1978
- {
1979
- variants: {
1980
- variant: {
1981
- default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
1982
- outline: "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]"
1983
- },
1984
- size: {
1985
- default: "h-8 text-sm",
1986
- sm: "h-7 text-xs",
1987
- lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!"
1988
- }
1989
- },
1990
- defaultVariants: {
1991
- variant: "default",
1992
- size: "default"
1993
- }
1994
- }
1995
- );
1996
- function SidebarMenuButton(_a) {
1997
- var _b = _a, {
1998
- asChild = false,
1999
- isActive = false,
2000
- variant = "default",
2001
- size = "default",
2002
- tooltip,
2003
- className
2004
- } = _b, props = __objRest(_b, [
2005
- "asChild",
2006
- "isActive",
2007
- "variant",
2008
- "size",
2009
- "tooltip",
2010
- "className"
2011
- ]);
2012
- const Comp = asChild ? Slot2 : "button";
2013
- const { isMobile, state } = useSidebar();
2014
- const button = /* @__PURE__ */ jsx15(
2015
- Comp,
2016
- __spreadValues({
2017
- "data-slot": "sidebar-menu-button",
2018
- "data-sidebar": "menu-button",
2019
- "data-size": size,
2020
- "data-active": isActive,
2021
- className: cn(sidebarMenuButtonVariants({ variant, size }), className)
2022
- }, props)
2023
- );
2024
- if (!tooltip) {
2025
- return button;
2026
- }
2027
- if (typeof tooltip === "string") {
2028
- tooltip = {
2029
- children: tooltip
2030
- };
2031
- }
2032
- return /* @__PURE__ */ jsxs9(Tooltip, { children: [
2033
- /* @__PURE__ */ jsx15(TooltipTrigger, { asChild: true, children: button }),
2034
- /* @__PURE__ */ jsx15(
2035
- TooltipContent,
2036
- __spreadValues({
2037
- side: "right",
2038
- align: "center",
2039
- hidden: state !== "collapsed" || isMobile
2040
- }, tooltip)
2041
- )
2042
- ] });
2043
- }
2044
- function SidebarMenuAction(_a) {
2045
- var _b = _a, {
2046
- className,
2047
- asChild = false,
2048
- showOnHover = false
2049
- } = _b, props = __objRest(_b, [
2050
- "className",
2051
- "asChild",
2052
- "showOnHover"
2053
- ]);
2054
- const Comp = asChild ? Slot2 : "button";
2055
- return /* @__PURE__ */ jsx15(
2056
- Comp,
2057
- __spreadValues({
2058
- "data-slot": "sidebar-menu-action",
2059
- "data-sidebar": "menu-action",
2060
- className: cn(
2061
- "absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform peer-hover/menu-button:text-sidebar-accent-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
2062
- // Increases the hit area of the button on mobile.
2063
- "after:absolute after:-inset-2 md:after:hidden",
2064
- "peer-data-[size=sm]/menu-button:top-1",
2065
- "peer-data-[size=default]/menu-button:top-1.5",
2066
- "peer-data-[size=lg]/menu-button:top-2.5",
2067
- "group-data-[collapsible=icon]:hidden",
2068
- showOnHover && "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground data-[state=open]:opacity-100 md:opacity-0",
2069
- className
2070
- )
2071
- }, props)
2072
- );
2073
- }
2074
- function SidebarMenuBadge(_a) {
2075
- var _b = _a, {
2076
- className
2077
- } = _b, props = __objRest(_b, [
2078
- "className"
2079
- ]);
2080
- return /* @__PURE__ */ jsx15(
2081
- "div",
2082
- __spreadValues({
2083
- "data-slot": "sidebar-menu-badge",
2084
- "data-sidebar": "menu-badge",
2085
- className: cn(
2086
- "pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none",
2087
- "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground",
2088
- "peer-data-[size=sm]/menu-button:top-1",
2089
- "peer-data-[size=default]/menu-button:top-1.5",
2090
- "peer-data-[size=lg]/menu-button:top-2.5",
2091
- "group-data-[collapsible=icon]:hidden",
2092
- className
2093
- )
2094
- }, props)
2095
- );
2096
- }
2097
- function SidebarMenuSub(_a) {
2098
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
2099
- return /* @__PURE__ */ jsx15(
2100
- "ul",
2101
- __spreadValues({
2102
- "data-slot": "sidebar-menu-sub",
2103
- "data-sidebar": "menu-sub",
2104
- className: cn(
2105
- "mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5",
2106
- "group-data-[collapsible=icon]:hidden",
2107
- className
2108
- )
2109
- }, props)
2110
- );
2111
- }
2112
- function SidebarMenuSubItem(_a) {
2113
- var _b = _a, {
2114
- className
2115
- } = _b, props = __objRest(_b, [
2116
- "className"
2117
- ]);
2118
- return /* @__PURE__ */ jsx15(
2119
- "li",
2120
- __spreadValues({
2121
- "data-slot": "sidebar-menu-sub-item",
2122
- "data-sidebar": "menu-sub-item",
2123
- className: cn("group/menu-sub-item relative", className)
2124
- }, props)
2125
- );
2126
- }
2127
- function SidebarMenuSubButton(_a) {
2128
- var _b = _a, {
2129
- asChild = false,
2130
- size = "md",
2131
- isActive = false,
2132
- className
2133
- } = _b, props = __objRest(_b, [
2134
- "asChild",
2135
- "size",
2136
- "isActive",
2137
- "className"
2138
- ]);
2139
- const Comp = asChild ? Slot2 : "a";
2140
- return /* @__PURE__ */ jsx15(
2141
- Comp,
2142
- __spreadValues({
2143
- "data-slot": "sidebar-menu-sub-button",
2144
- "data-sidebar": "menu-sub-button",
2145
- "data-size": size,
2146
- "data-active": isActive,
2147
- className: cn(
2148
- "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
2149
- "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
2150
- size === "sm" && "text-xs",
2151
- size === "md" && "text-sm",
2152
- "group-data-[collapsible=icon]:hidden",
2153
- className
2154
- )
2155
- }, props)
2156
- );
2157
- }
2158
-
2159
- // src/components/assistant-ui/thread-list.tsx
2160
- import {
2161
- ThreadListItemPrimitive,
2162
- ThreadListPrimitive,
2163
- useAssistantState as useAssistantState2
2164
- } from "@assistant-ui/react";
2165
- import { PlusIcon as PlusIcon2, TrashIcon } from "lucide-react";
2166
- import { Fragment, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
2167
- var ThreadList = () => {
2168
- return /* @__PURE__ */ jsxs10(ThreadListPrimitive.Root, { className: "aui-root aui-thread-list-root flex flex-col items-stretch gap-1.5", children: [
2169
- /* @__PURE__ */ jsx16(ThreadListNew, {}),
2170
- /* @__PURE__ */ jsx16(ThreadListItems, {})
2171
- ] });
2172
- };
2173
- var ThreadListNew = () => {
2174
- return /* @__PURE__ */ jsx16(ThreadListPrimitive.New, { asChild: true, children: /* @__PURE__ */ jsxs10(
2175
- Button,
2176
- {
2177
- className: "aui-thread-list-new flex items-center justify-start gap-1 rounded-lg px-2.5 py-2 text-start hover:bg-muted data-active:bg-muted",
2178
- variant: "ghost",
2179
- children: [
2180
- /* @__PURE__ */ jsx16(PlusIcon2, {}),
2181
- "New Chat"
2182
- ]
2183
- }
2184
- ) });
2185
- };
2186
- var ThreadListItems = () => {
2187
- const isLoading = useAssistantState2(({ threads }) => threads.isLoading);
2188
- if (isLoading) {
2189
- return /* @__PURE__ */ jsx16(ThreadListSkeleton, {});
2190
- }
2191
- return /* @__PURE__ */ jsx16(ThreadListPrimitive.Items, { components: { ThreadListItem } });
2192
- };
2193
- var ThreadListSkeleton = () => {
2194
- return /* @__PURE__ */ jsx16(Fragment, { children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx16(
2195
- "div",
2196
- {
2197
- role: "status",
2198
- "aria-label": "Loading threads",
2199
- "aria-live": "polite",
2200
- className: "aui-thread-list-skeleton-wrapper flex items-center gap-2 rounded-md px-3 py-2",
2201
- children: /* @__PURE__ */ jsx16(Skeleton, { className: "aui-thread-list-skeleton h-[22px] flex-grow" })
2202
- },
2203
- i
2204
- )) });
2205
- };
2206
- var ThreadListItem = () => {
2207
- return /* @__PURE__ */ jsxs10(ThreadListItemPrimitive.Root, { className: "aui-thread-list-item flex items-center gap-2 rounded-lg transition-all hover:bg-muted focus-visible:bg-muted focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none data-active:bg-muted", children: [
2208
- /* @__PURE__ */ jsx16(ThreadListItemPrimitive.Trigger, { className: "aui-thread-list-item-trigger flex-grow px-3 py-2 text-start", children: /* @__PURE__ */ jsx16(ThreadListItemTitle, {}) }),
2209
- /* @__PURE__ */ jsx16(ThreadListItemDelete, {})
2210
- ] });
2211
- };
2212
- var ThreadListItemTitle = () => {
2213
- return /* @__PURE__ */ jsx16("span", { className: "aui-thread-list-item-title text-sm", children: /* @__PURE__ */ jsx16(ThreadListItemPrimitive.Title, { fallback: "New Chat" }) });
2214
- };
2215
- var ThreadListItemDelete = () => {
2216
- return /* @__PURE__ */ jsx16(ThreadListItemPrimitive.Delete, { asChild: true, children: /* @__PURE__ */ jsx16(
2217
- TooltipIconButton,
2218
- {
2219
- className: "aui-thread-list-item-delete mr-3 ml-auto size-4 p-0 text-foreground hover:text-primary",
2220
- variant: "ghost",
2221
- tooltip: "Delete thread",
2222
- onClick: (event) => {
2223
- const confirmed = window.confirm(
2224
- "Delete this chat? This action cannot be undone."
2225
- );
2226
- if (!confirmed) {
2227
- event.preventDefault();
2228
- event.stopPropagation();
2229
- }
2230
- },
2231
- children: /* @__PURE__ */ jsx16(TrashIcon, {})
2232
- }
2233
- ) });
2234
- };
2235
-
2236
- // src/components/assistant-ui/threadlist-sidebar.tsx
2237
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2238
- function ThreadListSidebar(_a) {
2239
- var _b = _a, {
2240
- footer
2241
- } = _b, props = __objRest(_b, [
2242
- "footer"
2243
- ]);
2244
- return /* @__PURE__ */ jsxs11(
2245
- Sidebar,
2246
- __spreadProps(__spreadValues({
2247
- collapsible: "offcanvas",
2248
- variant: "inset",
2249
- className: "relative"
2250
- }, props), {
2251
- children: [
2252
- /* @__PURE__ */ jsx17(SidebarHeader, { className: "aomi-sidebar-header", children: /* @__PURE__ */ jsx17("div", { className: "aomi-sidebar-header-content flex items-center justify-between", children: /* @__PURE__ */ jsx17(SidebarMenu, { children: /* @__PURE__ */ jsx17(SidebarMenuItem, { children: /* @__PURE__ */ jsx17(SidebarMenuButton, { size: "lg", asChild: true, children: /* @__PURE__ */ jsx17(
2253
- Link,
2254
- {
2255
- href: "https://aomi.dev",
2256
- target: "_blank",
2257
- rel: "noopener noreferrer",
2258
- children: /* @__PURE__ */ jsx17("div", { className: "aomi-sidebar-header-icon-wrapper flex aspect-square size-8 items-center justify-center rounded-lg bg-white", children: /* @__PURE__ */ jsx17(
2259
- Image3,
2260
- {
2261
- src: "/assets/images/a.svg",
2262
- alt: "Logo",
2263
- width: 28,
2264
- height: 28,
2265
- className: "aomi-sidebar-header-icon size-7 ml-3",
2266
- priority: true
2267
- }
2268
- ) })
2269
- }
2270
- ) }) }) }) }) }),
2271
- /* @__PURE__ */ jsx17(SidebarContent, { className: "aomi-sidebar-content", children: /* @__PURE__ */ jsx17(ThreadList, {}) }),
2272
- /* @__PURE__ */ jsx17(SidebarRail, {}),
2273
- footer && /* @__PURE__ */ jsx17(SidebarFooter, { className: "aomi-sidebar-footer border-t border-sm py-4", children: footer })
2274
- ]
2275
- })
2276
- );
2277
- }
2278
-
2279
- // src/components/ui/breadcrumb.tsx
2280
- import { Slot as Slot3 } from "@radix-ui/react-slot";
2281
- import { ChevronRight, MoreHorizontal } from "lucide-react";
2282
- import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
2283
- function Breadcrumb(_a) {
2284
- var props = __objRest(_a, []);
2285
- return /* @__PURE__ */ jsx18("nav", __spreadValues({ "aria-label": "breadcrumb", "data-slot": "breadcrumb" }, props));
2286
- }
2287
- function BreadcrumbList(_a) {
2288
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
2289
- return /* @__PURE__ */ jsx18(
2290
- "ol",
2291
- __spreadValues({
2292
- "data-slot": "breadcrumb-list",
2293
- className: cn(
2294
- "flex flex-wrap items-center gap-1.5 text-sm break-words text-muted-foreground sm:gap-2.5",
2295
- className
2296
- )
2297
- }, props)
2298
- );
2299
- }
2300
- function BreadcrumbItem(_a) {
2301
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
2302
- return /* @__PURE__ */ jsx18(
2303
- "li",
2304
- __spreadValues({
2305
- "data-slot": "breadcrumb-item",
2306
- className: cn("inline-flex items-center gap-1.5", className)
2307
- }, props)
2308
- );
2309
- }
2310
- function BreadcrumbLink(_a) {
2311
- var _b = _a, {
2312
- asChild,
2313
- className
2314
- } = _b, props = __objRest(_b, [
2315
- "asChild",
2316
- "className"
2317
- ]);
2318
- const Comp = asChild ? Slot3 : "a";
2319
- return /* @__PURE__ */ jsx18(
2320
- Comp,
2321
- __spreadValues({
2322
- "data-slot": "breadcrumb-link",
2323
- className: cn("transition-colors hover:text-foreground", className)
2324
- }, props)
2325
- );
2326
- }
2327
- function BreadcrumbPage(_a) {
2328
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
2329
- return /* @__PURE__ */ jsx18(
2330
- "span",
2331
- __spreadValues({
2332
- "data-slot": "breadcrumb-page",
2333
- role: "link",
2334
- "aria-disabled": "true",
2335
- "aria-current": "page",
2336
- className: cn("font-normal text-foreground", className)
2337
- }, props)
2338
- );
2339
- }
2340
- function BreadcrumbSeparator(_a) {
2341
- var _b = _a, {
2342
- children,
2343
- className
2344
- } = _b, props = __objRest(_b, [
2345
- "children",
2346
- "className"
2347
- ]);
2348
- return /* @__PURE__ */ jsx18(
2349
- "li",
2350
- __spreadProps(__spreadValues({
2351
- "data-slot": "breadcrumb-separator",
2352
- role: "presentation",
2353
- "aria-hidden": "true",
2354
- className: cn("[&>svg]:size-3.5", className)
2355
- }, props), {
2356
- children: children != null ? children : /* @__PURE__ */ jsx18(ChevronRight, {})
2357
- })
2358
- );
2359
- }
2360
- function BreadcrumbEllipsis(_a) {
2361
- var _b = _a, {
2362
- className
2363
- } = _b, props = __objRest(_b, [
2364
- "className"
2365
- ]);
2366
- return /* @__PURE__ */ jsxs12(
2367
- "span",
2368
- __spreadProps(__spreadValues({
2369
- "data-slot": "breadcrumb-ellipsis",
2370
- role: "presentation",
2371
- "aria-hidden": "true",
2372
- className: cn("flex size-9 items-center justify-center", className)
2373
- }, props), {
2374
- children: [
2375
- /* @__PURE__ */ jsx18(MoreHorizontal, { className: "size-4" }),
2376
- /* @__PURE__ */ jsx18("span", { className: "sr-only", children: "More" })
2377
- ]
2378
- })
2379
- );
2380
- }
2381
-
2382
- // src/components/assistant-ui/runtime.tsx
2383
- import { createContext as createContext3, useCallback as useCallback3, useContext as useContext3, useEffect as useEffect5, useRef as useRef2, useState as useState7 } from "react";
2384
- import {
2385
- AssistantRuntimeProvider,
2386
- useExternalStoreRuntime
2387
- } from "@assistant-ui/react";
2388
-
2389
- // src/lib/backend-api.ts
2390
- function toQueryString(payload) {
2391
- const params = new URLSearchParams();
2392
- for (const [key, value] of Object.entries(payload)) {
2393
- if (value === void 0 || value === null) continue;
2394
- params.set(key, String(value));
2395
- }
2396
- const qs = params.toString();
2397
- return qs ? `?${qs}` : "";
2398
- }
2399
- async function postState(backendUrl, path, payload) {
2400
- const query = toQueryString(payload);
2401
- const url = `${backendUrl}${path}${query}`;
2402
- console.log("\u{1F535} [postState] URL:", url);
2403
- console.log("\u{1F535} [postState] Payload:", payload);
2404
- const response = await fetch(url, {
2405
- method: "POST"
2406
- });
2407
- console.log("\u{1F535} [postState] Response status:", response.status);
2408
- if (!response.ok) {
2409
- console.error("\u{1F534} [postState] Error:", response.status, response.statusText);
2410
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
2411
- }
2412
- const data = await response.json();
2413
- console.log("\u{1F7E2} [postState] Success:", data);
2414
- return data;
2415
- }
2416
- var BackendApi = class {
2417
- constructor(backendUrl) {
2418
- this.backendUrl = backendUrl;
2419
- this.connectionStatus = false;
2420
- this.eventSource = null;
2421
- this.updatesEventSource = null;
2422
- }
2423
- async fetchState(sessionId) {
2424
- console.log("\u{1F535} [fetchState] Called with sessionId:", sessionId);
2425
- const url = `${this.backendUrl}/api/state?session_id=${encodeURIComponent(sessionId)}`;
2426
- console.log("\u{1F535} [fetchState] URL:", url);
2427
- const response = await fetch(url);
2428
- console.log("\u{1F535} [fetchState] Response status:", response.status, response.statusText);
2429
- if (!response.ok) {
2430
- console.error("\u{1F534} [fetchState] Error:", response.status, response.statusText);
2431
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
2432
- }
2433
- const data = await response.json();
2434
- console.log("\u{1F7E2} [fetchState] Success:", data);
2435
- return data;
2436
- }
2437
- async postChatMessage(sessionId, message) {
2438
- console.log("\u{1F535} [postChatMessage] Called with sessionId:", sessionId, "message:", message);
2439
- const result = await postState(this.backendUrl, "/api/chat", { message, session_id: sessionId });
2440
- console.log("\u{1F7E2} [postChatMessage] Success:", result);
2441
- return result;
2442
- }
2443
- async postSystemMessage(sessionId, message) {
2444
- console.log("\u{1F535} [postSystemMessage] Called with sessionId:", sessionId, "message:", message);
2445
- const result = await postState(this.backendUrl, "/api/system", { message, session_id: sessionId });
2446
- console.log("\u{1F7E2} [postSystemMessage] Success:", result);
2447
- return result;
2448
- }
2449
- async postInterrupt(sessionId) {
2450
- console.log("\u{1F535} [postInterrupt] Called with sessionId:", sessionId);
2451
- const result = await postState(this.backendUrl, "/api/interrupt", { session_id: sessionId });
2452
- console.log("\u{1F7E2} [postInterrupt] Success:", result);
2453
- return result;
2454
- }
2455
- disconnectSSE() {
2456
- if (this.eventSource) {
2457
- this.eventSource.close();
2458
- this.eventSource = null;
2459
- }
2460
- this.setConnectionStatus(false);
2461
- }
2462
- setConnectionStatus(on) {
2463
- this.connectionStatus = on;
2464
- }
2465
- async connectSSE(sessionId, publicKey) {
2466
- this.disconnectSSE();
2467
- try {
2468
- const url = new URL(`${this.backendUrl}/api/chat/stream`);
2469
- url.searchParams.set("session_id", sessionId);
2470
- if (publicKey) {
2471
- url.searchParams.set("public_key", publicKey);
2472
- }
2473
- this.eventSource = new EventSource(url.toString());
2474
- this.eventSource.onopen = () => {
2475
- console.log("\u{1F310} SSE connection opened to:", url.toString());
2476
- this.setConnectionStatus(true);
2477
- };
2478
- this.eventSource.onmessage = (event) => {
2479
- try {
2480
- const data = JSON.parse(event.data);
2481
- } catch (error) {
2482
- console.error("Failed to parse SSE data:", error);
2483
- }
2484
- };
2485
- this.eventSource.onerror = (error) => {
2486
- console.error("SSE connection error:", error);
2487
- };
2488
- } catch (error) {
2489
- console.error("Failed to establish SSE connection:", error);
2490
- this.handleConnectionError(sessionId, publicKey);
2491
- }
2492
- }
2493
- handleConnectionError(sessionId, publicKey) {
2494
- this.setConnectionStatus(false);
2495
- let attempt = 0;
2496
- let total = 3;
2497
- if (attempt < total) {
2498
- attempt++;
2499
- console.log(`Attempting to reconnect (${attempt}/${total})...`);
2500
- setTimeout(() => {
2501
- this.connectSSE(sessionId, publicKey);
2502
- }, 100);
2503
- } else {
2504
- console.error("Max reconnection attempts reached");
2505
- this.setConnectionStatus(false);
2506
- }
2507
- }
2508
- subscribeToUpdates(onUpdate, onError) {
2509
- if (this.updatesEventSource) {
2510
- this.updatesEventSource.close();
2511
- }
2512
- const updatesUrl = new URL("/api/updates", this.backendUrl).toString();
2513
- this.updatesEventSource = new EventSource(updatesUrl);
2514
- this.updatesEventSource.onmessage = (event) => {
2515
- try {
2516
- const parsed = JSON.parse(event.data);
2517
- onUpdate(parsed);
2518
- } catch (error) {
2519
- console.error("Failed to parse system update SSE:", error);
2520
- onError == null ? void 0 : onError(error);
2521
- }
2522
- };
2523
- this.updatesEventSource.onerror = (error) => {
2524
- console.error("System updates SSE error:", error);
2525
- onError == null ? void 0 : onError(error);
2526
- };
2527
- return () => {
2528
- if (this.updatesEventSource) {
2529
- this.updatesEventSource.close();
2530
- this.updatesEventSource = null;
2531
- }
2532
- };
2533
- }
2534
- // ==================== Thread Management API ====================
2535
- /**
2536
- * Fetch all threads/sessions for a given public key
2537
- * @param publicKey - User's wallet address
2538
- * @returns Array of thread metadata
2539
- */
2540
- async fetchThreads(publicKey) {
2541
- console.log("\u{1F535} [fetchThreads] Called with publicKey:", publicKey);
2542
- const url = `${this.backendUrl}/api/sessions?public_key=${encodeURIComponent(publicKey)}`;
2543
- console.log("\u{1F535} [fetchThreads] URL:", url);
2544
- const response = await fetch(url);
2545
- console.log("\u{1F535} [fetchThreads] Response status:", response.status);
2546
- if (!response.ok) {
2547
- console.error("\u{1F534} [fetchThreads] Error:", response.status);
2548
- throw new Error(`Failed to fetch threads: HTTP ${response.status}`);
2549
- }
2550
- const data = await response.json();
2551
- console.log("\u{1F7E2} [fetchThreads] Success:", data);
2552
- return data;
2553
- }
2554
- /**
2555
- * Create a new thread/session
2556
- * @param publicKey - Optional user's wallet address
2557
- * @param title - Thread title (keep empty for backend to own the title)
2558
- * @returns Created thread information with backend-generated ID
2559
- */
2560
- async createThread(publicKey, title) {
2561
- console.log("\u{1F535} [createThread] Called with publicKey:", publicKey, "title:", title);
2562
- const body = {};
2563
- if (publicKey) {
2564
- body.public_key = publicKey;
2565
- }
2566
- if (title) {
2567
- body.title = title;
2568
- }
2569
- console.log("\u{1F535} [createThread] Request body:", body);
2570
- const url = `${this.backendUrl}/api/sessions`;
2571
- console.log("\u{1F535} [createThread] URL:", url);
2572
- const response = await fetch(url, {
2573
- method: "POST",
2574
- headers: { "Content-Type": "application/json" },
2575
- body: JSON.stringify(body)
2576
- });
2577
- console.log("\u{1F535} [createThread] Response status:", response.status);
2578
- if (!response.ok) {
2579
- console.error("\u{1F534} [createThread] Error:", response.status);
2580
- throw new Error(`Failed to create thread: HTTP ${response.status}`);
2581
- }
2582
- const data = await response.json();
2583
- console.log("\u{1F7E2} [createThread] Success:", data);
2584
- return data;
2585
- }
2586
- /**
2587
- * Archive a thread/session
2588
- * @param sessionId - The session ID to archive
2589
- */
2590
- async archiveThread(sessionId) {
2591
- console.log("\u{1F535} [archiveThread] Called with sessionId:", sessionId);
2592
- const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}/archive`;
2593
- console.log("\u{1F535} [archiveThread] URL:", url);
2594
- const response = await fetch(url, { method: "POST" });
2595
- console.log("\u{1F535} [archiveThread] Response status:", response.status);
2596
- if (!response.ok) {
2597
- console.error("\u{1F534} [archiveThread] Error:", response.status);
2598
- throw new Error(`Failed to archive thread: HTTP ${response.status}`);
2599
- }
2600
- console.log("\u{1F7E2} [archiveThread] Success");
2601
- }
2602
- /**
2603
- * Unarchive a thread/session
2604
- * @param sessionId - The session ID to unarchive
2605
- */
2606
- async unarchiveThread(sessionId) {
2607
- console.log("\u{1F535} [unarchiveThread] Called with sessionId:", sessionId);
2608
- const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}/unarchive`;
2609
- console.log("\u{1F535} [unarchiveThread] URL:", url);
2610
- const response = await fetch(url, { method: "POST" });
2611
- console.log("\u{1F535} [unarchiveThread] Response status:", response.status);
2612
- if (!response.ok) {
2613
- console.error("\u{1F534} [unarchiveThread] Error:", response.status);
2614
- throw new Error(`Failed to unarchive thread: HTTP ${response.status}`);
2615
- }
2616
- console.log("\u{1F7E2} [unarchiveThread] Success");
2617
- }
2618
- /**
2619
- * Delete a thread/session permanently
2620
- * @param sessionId - The session ID to delete
2621
- */
2622
- async deleteThread(sessionId) {
2623
- console.log("\u{1F535} [deleteThread] Called with sessionId:", sessionId);
2624
- const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}`;
2625
- console.log("\u{1F535} [deleteThread] URL:", url);
2626
- const response = await fetch(url, { method: "DELETE" });
2627
- console.log("\u{1F535} [deleteThread] Response status:", response.status);
2628
- if (!response.ok) {
2629
- console.error("\u{1F534} [deleteThread] Error:", response.status);
2630
- throw new Error(`Failed to delete thread: HTTP ${response.status}`);
2631
- }
2632
- console.log("\u{1F7E2} [deleteThread] Success");
2633
- }
2634
- /**
2635
- * Rename a thread/session
2636
- * @param sessionId - The session ID to rename
2637
- * @param newTitle - The new title for the thread
2638
- */
2639
- async renameThread(sessionId, newTitle) {
2640
- console.log("\u{1F535} [renameThread] Called with sessionId:", sessionId, "newTitle:", newTitle);
2641
- const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}`;
2642
- console.log("\u{1F535} [renameThread] URL:", url);
2643
- const response = await fetch(url, {
2644
- method: "PATCH",
2645
- headers: { "Content-Type": "application/json" },
2646
- body: JSON.stringify({ title: newTitle })
2647
- });
2648
- console.log("\u{1F535} [renameThread] Response status:", response.status);
2649
- if (!response.ok) {
2650
- console.error("\u{1F534} [renameThread] Error:", response.status);
2651
- throw new Error(`Failed to rename thread: HTTP ${response.status}`);
2652
- }
2653
- console.log("\u{1F7E2} [renameThread] Success");
2654
- }
2655
- };
2656
-
2657
- // src/lib/conversion.ts
2658
- function constructThreadMessage(msg) {
2659
- var _a;
2660
- if (msg.sender === "system") return null;
2661
- const content = [];
2662
- const role = msg.sender === "user" ? "user" : "assistant";
2663
- if (msg.content) {
2664
- content.push({ type: "text", text: msg.content });
2665
- }
2666
- const [topic, toolContent] = (_a = parseToolStream(msg.tool_stream)) != null ? _a : [];
2667
- if (topic && toolContent) {
2668
- content.push({
2669
- type: "tool-call",
2670
- toolCallId: `tool_${Date.now()}`,
2671
- toolName: topic,
2672
- args: void 0,
2673
- result: (() => {
2674
- try {
2675
- return JSON.parse(toolContent);
2676
- } catch (e) {
2677
- return { args: toolContent };
2678
- }
2679
- })()
2680
- });
2681
- }
2682
- const threadMessage = __spreadValues({
2683
- role,
2684
- content: content.length > 0 ? content : [{ type: "text", text: "" }]
2685
- }, msg.timestamp && { createdAt: new Date(msg.timestamp) });
2686
- return threadMessage;
2687
- }
2688
- function constructSystemMessage(msg) {
2689
- var _a;
2690
- const [topic] = (_a = parseToolStream(msg.tool_stream)) != null ? _a : [];
2691
- const messageText = topic || msg.content || "";
2692
- const timestamp = parseTimestamp(msg.timestamp);
2693
- if (!messageText.trim()) return null;
2694
- return __spreadValues({
2695
- role: "system",
2696
- content: [{ type: "text", text: messageText }]
2697
- }, timestamp && { createdAt: timestamp });
2698
- }
2699
- function parseTimestamp(timestamp) {
2700
- if (!timestamp) return void 0;
2701
- const parsed = new Date(timestamp);
2702
- return Number.isNaN(parsed.valueOf()) ? void 0 : parsed;
2703
- }
2704
- function parseToolStream(toolStream) {
2705
- if (!toolStream) return null;
2706
- if (Array.isArray(toolStream) && toolStream.length === 2) {
2707
- const [topic, content] = toolStream;
2708
- return [String(topic), content];
2709
- } else if (typeof toolStream === "object") {
2710
- const topic = toolStream.topic;
2711
- const content = toolStream.content;
2712
- return topic ? [String(topic), String(content)] : null;
2713
- }
2714
- return null;
2715
- }
2716
-
2717
- // src/components/assistant-ui/runtime.tsx
2718
- import { jsx as jsx19 } from "react/jsx-runtime";
2719
- var RuntimeActionsContext = createContext3(void 0);
2720
- var isTempThreadId = (id) => id.startsWith("temp-");
2721
- var parseTimestamp2 = (value) => {
2722
- if (value === void 0 || value === null) return 0;
2723
- if (typeof value === "number") {
2724
- return Number.isFinite(value) ? value < 1e12 ? value * 1e3 : value : 0;
2725
- }
2726
- const numeric = Number(value);
2727
- if (!Number.isNaN(numeric)) {
2728
- return numeric < 1e12 ? numeric * 1e3 : numeric;
2729
- }
2730
- const ts = Date.parse(value);
2731
- return Number.isNaN(ts) ? 0 : ts;
2732
- };
2733
- var isPlaceholderTitle = (title) => {
2734
- var _a;
2735
- const normalized = (_a = title == null ? void 0 : title.trim()) != null ? _a : "";
2736
- return !normalized || normalized.startsWith("#[");
2737
- };
2738
- var useRuntimeActions = () => {
2739
- const context = useContext3(RuntimeActionsContext);
2740
- if (!context) {
2741
- throw new Error("useRuntimeActions must be used within AomiRuntimeProvider");
2742
- }
2743
- return context;
2744
- };
2745
- function AomiRuntimeProvider({
2746
- children,
2747
- backendUrl = "http://localhost:8080",
2748
- publicKey
2749
- }) {
2750
- const {
2751
- currentThreadId,
2752
- setCurrentThreadId,
2753
- bumpThreadViewKey,
2754
- threads,
2755
- setThreads,
2756
- threadMetadata,
2757
- setThreadMetadata,
2758
- threadCnt,
2759
- setThreadCnt,
2760
- getThreadMessages,
2761
- setThreadMessages,
2762
- updateThreadMetadata
2763
- } = useThreadContext();
2764
- const [isRunning, setIsRunning] = useState7(false);
2765
- const backendApiRef = useRef2(new BackendApi(backendUrl));
2766
- const pollingIntervalRef = useRef2(null);
2767
- const pendingSystemMessagesRef = useRef2(/* @__PURE__ */ new Map());
2768
- const pendingChatMessagesRef = useRef2(/* @__PURE__ */ new Map());
2769
- const creatingThreadIdRef = useRef2(null);
2770
- const createThreadPromiseRef = useRef2(null);
2771
- const findPendingThreadId = useCallback3(() => {
2772
- if (creatingThreadIdRef.current) return creatingThreadIdRef.current;
2773
- for (const [id, meta] of threadMetadata.entries()) {
2774
- if (meta.status === "pending") return id;
2775
- }
2776
- return null;
2777
- }, [threadMetadata]);
2778
- const currentMessages = getThreadMessages(currentThreadId);
2779
- const currentThreadIdRef = useRef2(currentThreadId);
2780
- useEffect5(() => {
2781
- currentThreadIdRef.current = currentThreadId;
2782
- }, [currentThreadId]);
2783
- const skipInitialFetchRef = useRef2(/* @__PURE__ */ new Set());
2784
- const tempToBackendIdRef = useRef2(/* @__PURE__ */ new Map());
2785
- const resolveThreadId = useCallback3((threadId) => {
2786
- return tempToBackendIdRef.current.get(threadId) || threadId;
2787
- }, []);
2788
- const findTempIdForBackendId = useCallback3((backendId) => {
2789
- for (const [tempId, bId] of tempToBackendIdRef.current.entries()) {
2790
- if (bId === backendId) return tempId;
2791
- }
2792
- return void 0;
2793
- }, []);
2794
- const isThreadReady = useCallback3((threadId) => {
2795
- if (!isTempThreadId(threadId)) return true;
2796
- return tempToBackendIdRef.current.has(threadId);
2797
- }, []);
2798
- const applyMessages = useCallback3((msgs) => {
2799
- var _a, _b;
2800
- if (!msgs) return;
2801
- const hasPendingMessages = pendingChatMessagesRef.current.has(currentThreadId) && ((_b = (_a = pendingChatMessagesRef.current.get(currentThreadId)) == null ? void 0 : _a.length) != null ? _b : 0) > 0;
2802
- if (hasPendingMessages) {
2803
- console.log("Skipping applyMessages - pending messages exist for thread:", currentThreadId);
2804
- return;
2805
- }
2806
- const threadMessages = [];
2807
- for (const msg of msgs) {
2808
- if (msg.sender === "system") {
2809
- const systemMessage = constructSystemMessage(msg);
2810
- if (systemMessage) {
2811
- threadMessages.push(systemMessage);
2812
- }
2813
- continue;
2814
- }
2815
- const threadMessage = constructThreadMessage(msg);
2816
- if (threadMessage) {
2817
- threadMessages.push(threadMessage);
2818
- }
2819
- }
2820
- setThreadMessages(currentThreadId, threadMessages);
2821
- }, [currentThreadId, setThreadMessages]);
2822
- useEffect5(() => {
2823
- backendApiRef.current = new BackendApi(backendUrl);
2824
- }, [backendUrl]);
2825
- const stopPolling = useCallback3(() => {
2826
- if (pollingIntervalRef.current) {
2827
- clearInterval(pollingIntervalRef.current);
2828
- pollingIntervalRef.current = null;
2829
- }
2830
- }, []);
2831
- const startPolling = useCallback3(() => {
2832
- if (!isThreadReady(currentThreadId)) return;
2833
- if (pollingIntervalRef.current) return;
2834
- const backendThreadId = resolveThreadId(currentThreadId);
2835
- setIsRunning(true);
2836
- pollingIntervalRef.current = setInterval(async () => {
2837
- try {
2838
- const state = await backendApiRef.current.fetchState(backendThreadId);
2839
- if (state.session_exists === false) {
2840
- setIsRunning(false);
2841
- stopPolling();
2842
- return;
2843
- }
2844
- applyMessages(state.messages);
2845
- if (!state.is_processing) {
2846
- setIsRunning(false);
2847
- stopPolling();
2848
- }
2849
- } catch (error) {
2850
- console.error("Polling error:", error);
2851
- stopPolling();
2852
- setIsRunning(false);
2853
- }
2854
- }, 500);
2855
- }, [currentThreadId, applyMessages, stopPolling, isThreadReady, resolveThreadId]);
2856
- useEffect5(() => {
2857
- const fetchInitialState = async () => {
2858
- if (isTempThreadId(currentThreadId) && !tempToBackendIdRef.current.has(currentThreadId)) {
2859
- setIsRunning(false);
2860
- return;
2861
- }
2862
- if (skipInitialFetchRef.current.has(currentThreadId)) {
2863
- skipInitialFetchRef.current.delete(currentThreadId);
2864
- setIsRunning(false);
2865
- return;
2866
- }
2867
- const backendThreadId = resolveThreadId(currentThreadId);
2868
- try {
2869
- const state = await backendApiRef.current.fetchState(backendThreadId);
2870
- if (state.session_exists === false) {
2871
- setIsRunning(false);
2872
- return;
2873
- }
2874
- applyMessages(state.messages);
2875
- if (state.is_processing) {
2876
- setIsRunning(true);
2877
- startPolling();
2878
- } else {
2879
- setIsRunning(false);
2880
- }
2881
- } catch (error) {
2882
- console.error("Failed to fetch initial state:", error);
2883
- }
2884
- };
2885
- void fetchInitialState();
2886
- return () => {
2887
- stopPolling();
2888
- };
2889
- }, [currentThreadId, applyMessages, startPolling, stopPolling, resolveThreadId]);
2890
- useEffect5(() => {
2891
- if (!publicKey) return;
2892
- const fetchThreadList = async () => {
2893
- var _a, _b;
2894
- try {
2895
- const threadList = await backendApiRef.current.fetchThreads(publicKey);
2896
- const newMetadata = new Map(threadMetadata);
2897
- let maxChatNum = threadCnt;
2898
- for (const thread of threadList) {
2899
- const rawTitle = (_a = thread.title) != null ? _a : "";
2900
- const title = isPlaceholderTitle(rawTitle) ? "" : rawTitle;
2901
- const lastActive = thread.last_active_at || thread.updated_at || thread.created_at || ((_b = newMetadata.get(thread.session_id)) == null ? void 0 : _b.lastActiveAt) || (/* @__PURE__ */ new Date()).toISOString();
2902
- newMetadata.set(thread.session_id, {
2903
- title,
2904
- status: thread.is_archived ? "archived" : "regular",
2905
- lastActiveAt: lastActive
2906
- });
2907
- const match = title.match(/^Chat (\d+)$/);
2908
- if (match) {
2909
- const num = parseInt(match[1], 10);
2910
- if (num > maxChatNum) {
2911
- maxChatNum = num;
2912
- }
2913
- }
2914
- }
2915
- setThreadMetadata(newMetadata);
2916
- if (maxChatNum > threadCnt) {
2917
- setThreadCnt(maxChatNum);
2918
- }
2919
- } catch (error) {
2920
- console.error("Failed to fetch thread list:", error);
2921
- }
2922
- };
2923
- void fetchThreadList();
2924
- }, [publicKey]);
2925
- const threadListAdapter = (() => {
2926
- const sortByLastActiveDesc = ([, metaA], [, metaB]) => {
2927
- const tsA = parseTimestamp2(metaA.lastActiveAt);
2928
- const tsB = parseTimestamp2(metaB.lastActiveAt);
2929
- return tsB - tsA;
2930
- };
2931
- const regularThreads = Array.from(threadMetadata.entries()).filter(([_, meta]) => meta.status === "regular").filter(([_, meta]) => !isPlaceholderTitle(meta.title)).sort(sortByLastActiveDesc).map(([id, meta]) => ({
2932
- id,
2933
- title: meta.title || "New Chat",
2934
- status: "regular"
2935
- }));
2936
- const archivedThreadsArray = Array.from(threadMetadata.entries()).filter(([_, meta]) => meta.status === "archived").filter(([_, meta]) => !isPlaceholderTitle(meta.title)).sort(sortByLastActiveDesc).map(([id, meta]) => ({
2937
- id,
2938
- title: meta.title || "New Chat",
2939
- status: "archived"
2940
- }));
2941
- return {
2942
- threadId: currentThreadId,
2943
- threads: regularThreads,
2944
- archivedThreads: archivedThreadsArray,
2945
- // Create new thread
2946
- onSwitchToNewThread: async () => {
2947
- var _a;
2948
- const preparePendingThread = (newId) => {
2949
- const previousPendingId = creatingThreadIdRef.current;
2950
- if (previousPendingId && previousPendingId !== newId) {
2951
- setThreadMetadata((prev) => {
2952
- const next = new Map(prev);
2953
- next.delete(previousPendingId);
2954
- return next;
2955
- });
2956
- setThreads((prev) => {
2957
- const next = new Map(prev);
2958
- next.delete(previousPendingId);
2959
- return next;
2960
- });
2961
- pendingChatMessagesRef.current.delete(previousPendingId);
2962
- pendingSystemMessagesRef.current.delete(previousPendingId);
2963
- tempToBackendIdRef.current.delete(previousPendingId);
2964
- skipInitialFetchRef.current.delete(previousPendingId);
2965
- }
2966
- creatingThreadIdRef.current = newId;
2967
- pendingChatMessagesRef.current.delete(newId);
2968
- pendingSystemMessagesRef.current.delete(newId);
2969
- setThreadMetadata(
2970
- (prev) => new Map(prev).set(newId, {
2971
- title: "New Chat",
2972
- status: "pending",
2973
- lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
2974
- })
2975
- );
2976
- setThreadMessages(newId, []);
2977
- setCurrentThreadId(newId);
2978
- setIsRunning(false);
2979
- bumpThreadViewKey();
2980
- };
2981
- const existingPendingId = findPendingThreadId();
2982
- if (existingPendingId) {
2983
- preparePendingThread(existingPendingId);
2984
- return;
2985
- }
2986
- if (createThreadPromiseRef.current) {
2987
- preparePendingThread((_a = creatingThreadIdRef.current) != null ? _a : `temp-${crypto.randomUUID()}`);
2988
- return;
2989
- }
2990
- const tempId = `temp-${crypto.randomUUID()}`;
2991
- preparePendingThread(tempId);
2992
- const createPromise = backendApiRef.current.createThread(publicKey, void 0).then(async (newThread) => {
2993
- var _a2;
2994
- const uiThreadId = (_a2 = creatingThreadIdRef.current) != null ? _a2 : tempId;
2995
- const backendId = newThread.session_id;
2996
- tempToBackendIdRef.current.set(uiThreadId, backendId);
2997
- skipInitialFetchRef.current.add(uiThreadId);
2998
- const backendTitle = newThread.title;
2999
- if (backendTitle && !isPlaceholderTitle(backendTitle)) {
3000
- setThreadMetadata((prev) => {
3001
- var _a3;
3002
- const next = new Map(prev);
3003
- const existing = next.get(uiThreadId);
3004
- const nextStatus = (existing == null ? void 0 : existing.status) === "archived" ? "archived" : "regular";
3005
- next.set(uiThreadId, {
3006
- title: backendTitle,
3007
- status: nextStatus,
3008
- lastActiveAt: (_a3 = existing == null ? void 0 : existing.lastActiveAt) != null ? _a3 : (/* @__PURE__ */ new Date()).toISOString()
3009
- });
3010
- return next;
3011
- });
3012
- if (creatingThreadIdRef.current === uiThreadId) {
3013
- creatingThreadIdRef.current = null;
3014
- }
3015
- }
3016
- const pendingMessages = pendingChatMessagesRef.current.get(uiThreadId);
3017
- if (pendingMessages == null ? void 0 : pendingMessages.length) {
3018
- pendingChatMessagesRef.current.delete(uiThreadId);
3019
- for (const text of pendingMessages) {
3020
- try {
3021
- await backendApiRef.current.postChatMessage(backendId, text);
3022
- } catch (error) {
3023
- console.error("Failed to send queued message:", error);
3024
- }
3025
- }
3026
- if (currentThreadIdRef.current === uiThreadId) {
3027
- startPolling();
3028
- }
3029
- }
3030
- }).catch((error) => {
3031
- var _a2;
3032
- console.error("Failed to create new thread:", error);
3033
- const failedId = (_a2 = creatingThreadIdRef.current) != null ? _a2 : tempId;
3034
- setThreadMetadata((prev) => {
3035
- const next = new Map(prev);
3036
- next.delete(failedId);
3037
- return next;
3038
- });
3039
- setThreads((prev) => {
3040
- const next = new Map(prev);
3041
- next.delete(failedId);
3042
- return next;
3043
- });
3044
- if (creatingThreadIdRef.current === failedId) {
3045
- creatingThreadIdRef.current = null;
3046
- }
3047
- }).finally(() => {
3048
- createThreadPromiseRef.current = null;
3049
- });
3050
- createThreadPromiseRef.current = createPromise;
3051
- },
3052
- // Switch to existing thread
3053
- onSwitchToThread: (threadId) => {
3054
- setCurrentThreadId(threadId);
3055
- },
3056
- // Rename thread
3057
- onRename: async (threadId, newTitle) => {
3058
- updateThreadMetadata(threadId, { title: isPlaceholderTitle(newTitle) ? "" : newTitle });
3059
- try {
3060
- await backendApiRef.current.renameThread(threadId, newTitle);
3061
- } catch (error) {
3062
- console.error("Failed to rename thread:", error);
3063
- }
3064
- },
3065
- // Archive thread
3066
- onArchive: async (threadId) => {
3067
- updateThreadMetadata(threadId, { status: "archived" });
3068
- try {
3069
- await backendApiRef.current.archiveThread(threadId);
3070
- } catch (error) {
3071
- console.error("Failed to archive thread:", error);
3072
- updateThreadMetadata(threadId, { status: "regular" });
3073
- }
3074
- },
3075
- // Unarchive thread
3076
- onUnarchive: async (threadId) => {
3077
- updateThreadMetadata(threadId, { status: "regular" });
3078
- try {
3079
- await backendApiRef.current.unarchiveThread(threadId);
3080
- } catch (error) {
3081
- console.error("Failed to unarchive thread:", error);
3082
- updateThreadMetadata(threadId, { status: "archived" });
3083
- }
3084
- },
3085
- // Delete thread
3086
- onDelete: async (threadId) => {
3087
- try {
3088
- await backendApiRef.current.deleteThread(threadId);
3089
- setThreadMetadata((prev) => {
3090
- const next = new Map(prev);
3091
- next.delete(threadId);
3092
- return next;
3093
- });
3094
- setThreads((prev) => {
3095
- const next = new Map(prev);
3096
- next.delete(threadId);
3097
- return next;
3098
- });
3099
- if (currentThreadId === threadId) {
3100
- const firstRegularThread = Array.from(threadMetadata.entries()).find(([id, meta]) => meta.status === "regular" && id !== threadId);
3101
- if (firstRegularThread) {
3102
- setCurrentThreadId(firstRegularThread[0]);
3103
- } else {
3104
- const defaultId = "default-session";
3105
- setThreadMetadata(
3106
- (prev) => new Map(prev).set(defaultId, {
3107
- title: "New Chat",
3108
- status: "regular",
3109
- lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
3110
- })
3111
- );
3112
- setThreadMessages(defaultId, []);
3113
- setCurrentThreadId(defaultId);
3114
- }
3115
- }
3116
- } catch (error) {
3117
- console.error("Failed to delete thread:", error);
3118
- throw error;
3119
- }
3120
- }
3121
- };
3122
- })();
3123
- const sendSystemMessageNow = useCallback3(
3124
- async (threadId, message) => {
3125
- const backendThreadId = resolveThreadId(threadId);
3126
- setIsRunning(true);
3127
- try {
3128
- const response = await backendApiRef.current.postSystemMessage(backendThreadId, message);
3129
- if (response.res) {
3130
- const systemMessage = constructSystemMessage(response.res);
3131
- if (systemMessage) {
3132
- const updatedMessages = [...getThreadMessages(threadId), systemMessage];
3133
- setThreadMessages(threadId, updatedMessages);
3134
- }
3135
- }
3136
- await startPolling();
3137
- } catch (error) {
3138
- console.error("Failed to send system message:", error);
3139
- setIsRunning(false);
3140
- }
3141
- },
3142
- [getThreadMessages, setThreadMessages, startPolling, resolveThreadId]
3143
- );
3144
- const flushPendingSystemMessages = useCallback3(
3145
- async (threadId) => {
3146
- const pending = pendingSystemMessagesRef.current.get(threadId);
3147
- if (!(pending == null ? void 0 : pending.length)) return;
3148
- pendingSystemMessagesRef.current.delete(threadId);
3149
- for (const pendingMessage of pending) {
3150
- await sendSystemMessageNow(threadId, pendingMessage);
3151
- }
3152
- },
3153
- [sendSystemMessageNow]
3154
- );
3155
- const flushPendingChatMessages = useCallback3(
3156
- async (threadId) => {
3157
- const pending = pendingChatMessagesRef.current.get(threadId);
3158
- if (!(pending == null ? void 0 : pending.length)) return;
3159
- pendingChatMessagesRef.current.delete(threadId);
3160
- const backendThreadId = resolveThreadId(threadId);
3161
- for (const text of pending) {
3162
- try {
3163
- await backendApiRef.current.postChatMessage(backendThreadId, text);
3164
- } catch (error) {
3165
- console.error("Failed to send queued message:", error);
3166
- }
3167
- }
3168
- startPolling();
3169
- },
3170
- [resolveThreadId, startPolling]
3171
- );
3172
- const onNew = useCallback3(
3173
- async (message) => {
3174
- const text = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
3175
- if (!text) return;
3176
- const userMessage = {
3177
- role: "user",
3178
- content: [{ type: "text", text }],
3179
- createdAt: /* @__PURE__ */ new Date()
3180
- };
3181
- setThreadMessages(currentThreadId, [...currentMessages, userMessage]);
3182
- updateThreadMetadata(currentThreadId, { lastActiveAt: (/* @__PURE__ */ new Date()).toISOString() });
3183
- if (!isThreadReady(currentThreadId)) {
3184
- console.log("Thread not ready yet; queuing message for later delivery.");
3185
- setIsRunning(true);
3186
- const pending = pendingChatMessagesRef.current.get(currentThreadId) || [];
3187
- pendingChatMessagesRef.current.set(currentThreadId, [...pending, text]);
3188
- return;
3189
- }
3190
- const backendThreadId = resolveThreadId(currentThreadId);
3191
- try {
3192
- setIsRunning(true);
3193
- await backendApiRef.current.postChatMessage(backendThreadId, text);
3194
- await flushPendingSystemMessages(currentThreadId);
3195
- startPolling();
3196
- } catch (error) {
3197
- console.error("Failed to send message:", error);
3198
- setIsRunning(false);
3199
- }
3200
- },
3201
- [
3202
- currentThreadId,
3203
- currentMessages,
3204
- flushPendingSystemMessages,
3205
- setThreadMessages,
3206
- startPolling,
3207
- isThreadReady,
3208
- resolveThreadId,
3209
- updateThreadMetadata
3210
- ]
3211
- );
3212
- const sendSystemMessage = useCallback3(
3213
- async (message) => {
3214
- if (!isThreadReady(currentThreadId)) return;
3215
- const threadMessages = getThreadMessages(currentThreadId);
3216
- const hasUserMessages = threadMessages.some((msg) => msg.role === "user");
3217
- if (!hasUserMessages) {
3218
- const pending = pendingSystemMessagesRef.current.get(currentThreadId) || [];
3219
- pendingSystemMessagesRef.current.set(currentThreadId, [...pending, message]);
3220
- return;
3221
- }
3222
- await sendSystemMessageNow(currentThreadId, message);
3223
- },
3224
- [currentThreadId, getThreadMessages, sendSystemMessageNow, isThreadReady]
3225
- );
3226
- const onCancel = useCallback3(async () => {
3227
- if (!isThreadReady(currentThreadId)) return;
3228
- stopPolling();
3229
- const backendThreadId = resolveThreadId(currentThreadId);
3230
- try {
3231
- await backendApiRef.current.postInterrupt(backendThreadId);
3232
- setIsRunning(false);
3233
- } catch (error) {
3234
- console.error("Failed to cancel:", error);
3235
- }
3236
- }, [currentThreadId, stopPolling, isThreadReady, resolveThreadId]);
3237
- const runtime = useExternalStoreRuntime({
3238
- messages: currentMessages,
3239
- setMessages: (msgs) => setThreadMessages(currentThreadId, [...msgs]),
3240
- isRunning,
3241
- onNew,
3242
- onCancel,
3243
- convertMessage: (msg) => msg,
3244
- adapters: {
3245
- threadList: threadListAdapter
3246
- // 🎯 Thread list adapter enabled!
3247
- }
3248
- });
3249
- useEffect5(() => {
3250
- if (isTempThreadId(currentThreadId)) return;
3251
- const hasUserMessages = currentMessages.some((msg) => msg.role === "user");
3252
- if (hasUserMessages) {
3253
- void flushPendingSystemMessages(currentThreadId);
3254
- }
3255
- }, [currentMessages, currentThreadId, flushPendingSystemMessages]);
3256
- useEffect5(() => {
3257
- const unsubscribe = backendApiRef.current.subscribeToUpdates(
3258
- (update) => {
3259
- if (update.type !== "TitleChanged") return;
3260
- const sessionId = update.data.session_id;
3261
- const newTitle = update.data.new_title;
3262
- const tempId = findTempIdForBackendId(sessionId);
3263
- const threadIdToUpdate = tempId || sessionId;
3264
- setThreadMetadata((prev) => {
3265
- var _a;
3266
- const next = new Map(prev);
3267
- const existing = next.get(threadIdToUpdate);
3268
- const normalizedTitle = isPlaceholderTitle(newTitle) ? "" : newTitle;
3269
- const nextStatus = (existing == null ? void 0 : existing.status) === "archived" ? "archived" : "regular";
3270
- next.set(threadIdToUpdate, {
3271
- title: normalizedTitle,
3272
- status: nextStatus,
3273
- lastActiveAt: (_a = existing == null ? void 0 : existing.lastActiveAt) != null ? _a : (/* @__PURE__ */ new Date()).toISOString()
3274
- });
3275
- return next;
3276
- });
3277
- if (!isPlaceholderTitle(newTitle) && creatingThreadIdRef.current === threadIdToUpdate) {
3278
- creatingThreadIdRef.current = null;
3279
- }
3280
- },
3281
- (error) => {
3282
- console.error("Failed to handle system update SSE:", error);
3283
- }
3284
- );
3285
- return () => {
3286
- unsubscribe();
3287
- };
3288
- }, [backendUrl, setThreadMetadata, findTempIdForBackendId]);
3289
- return /* @__PURE__ */ jsx19(RuntimeActionsContext.Provider, { value: { sendSystemMessage }, children: /* @__PURE__ */ jsx19(AssistantRuntimeProvider, { runtime, children }) });
3290
- }
3291
-
3292
- // src/utils/wallet.ts
3293
- import { useEffect as useEffect6, useRef as useRef3 } from "react";
3294
- var getNetworkName = (chainId) => {
3295
- if (chainId === void 0) return "";
3296
- const id = typeof chainId === "string" ? Number(chainId) : chainId;
3297
- switch (id) {
3298
- case 1:
3299
- return "ethereum";
3300
- case 137:
3301
- return "polygon";
3302
- case 42161:
3303
- return "arbitrum";
3304
- case 8453:
3305
- return "base";
3306
- case 10:
3307
- return "optimism";
3308
- case 11155111:
3309
- return "sepolia";
3310
- case 1337:
3311
- case 31337:
3312
- return "testnet";
3313
- case 59140:
3314
- return "linea-sepolia";
3315
- case 59144:
3316
- return "linea";
3317
- default:
3318
- return "testnet";
3319
- }
3320
- };
3321
- var formatAddress = (addr) => addr ? `${addr.slice(0, 6)}...${addr.slice(-4)}` : "Connect Wallet";
3322
- function WalletSystemMessageEmitter({ wallet }) {
3323
- const { sendSystemMessage } = useRuntimeActions();
3324
- const lastWalletRef = useRef3({ isConnected: false });
3325
- useEffect6(() => {
3326
- const prev = lastWalletRef.current;
3327
- const { address, chainId, isConnected } = wallet;
3328
- const normalizedAddress = address == null ? void 0 : address.toLowerCase();
3329
- if (isConnected && normalizedAddress && chainId && (!prev.isConnected || prev.address !== normalizedAddress)) {
3330
- const networkName = getNetworkName(chainId);
3331
- const message = `User connected wallet with address ${normalizedAddress} on ${networkName} network (Chain ID: ${chainId}). Ready to help with transactions.`;
3332
- console.log(message);
3333
- void sendSystemMessage(message);
3334
- lastWalletRef.current = { isConnected: true, address: normalizedAddress, chainId };
3335
- return;
3336
- }
3337
- if (!isConnected && prev.isConnected) {
3338
- void sendSystemMessage("Wallet disconnected by user.");
3339
- console.log("Wallet disconnected by user.");
3340
- lastWalletRef.current = { isConnected: false };
3341
- return;
3342
- }
3343
- if (isConnected && normalizedAddress && chainId && prev.isConnected && prev.address === normalizedAddress && prev.chainId !== chainId) {
3344
- const networkName = getNetworkName(chainId);
3345
- const message = `User switched wallet to ${networkName} network (Chain ID: ${chainId}).`;
3346
- console.log(message);
3347
- void sendSystemMessage(message);
3348
- lastWalletRef.current = { isConnected: true, address: normalizedAddress, chainId };
3349
- }
3350
- }, [wallet, sendSystemMessage]);
3351
- return null;
3352
- }
3353
-
3354
- // src/components/aomi-frame.tsx
3355
- import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
3356
- var AomiFrame = ({
3357
- width = "100%",
3358
- height = "80vh",
3359
- className,
3360
- style,
3361
- walletFooter,
3362
- children
3363
- }) => {
3364
- var _a;
3365
- const backendUrl = (_a = process.env.NEXT_PUBLIC_BACKEND_URL) != null ? _a : "http://localhost:8080";
3366
- const frameStyle = __spreadValues({ width, height }, style);
3367
- const [wallet, setWalletState] = useState8({
3368
- isConnected: false,
3369
- address: void 0,
3370
- chainId: void 0,
3371
- ensName: void 0
3372
- });
3373
- const setWallet = useCallback4((data) => {
3374
- setWalletState((prev) => __spreadValues(__spreadValues({}, prev), data));
3375
- }, []);
3376
- return /* @__PURE__ */ jsx20(ThreadContextProvider, { children: /* @__PURE__ */ jsxs13(AomiRuntimeProvider, { backendUrl, publicKey: wallet.address, children: [
3377
- /* @__PURE__ */ jsx20(WalletSystemMessageEmitter, { wallet }),
3378
- /* @__PURE__ */ jsx20(
3379
- FrameShell,
3380
- {
3381
- className,
3382
- frameStyle,
3383
- walletFooter,
3384
- wallet,
3385
- setWallet,
3386
- children
3387
- }
3388
- )
3389
- ] }) });
3390
- };
3391
- var FrameShell = ({
3392
- className,
3393
- frameStyle,
3394
- walletFooter,
3395
- wallet,
3396
- setWallet,
3397
- children
3398
- }) => {
3399
- var _a, _b;
3400
- const currentTitle = (_b = (_a = useCurrentThreadMetadata()) == null ? void 0 : _a.title) != null ? _b : "New Chat";
3401
- const { currentThreadId, threadViewKey } = useThreadContext();
3402
- return /* @__PURE__ */ jsxs13(SidebarProvider, { children: [
3403
- children,
3404
- /* @__PURE__ */ jsxs13(
3405
- "div",
3406
- {
3407
- className: cn(
3408
- "flex h-full w-full overflow-hidden rounded-2xl bg-white shadow-2xl dark:bg-neutral-950",
3409
- className
3410
- ),
3411
- style: frameStyle,
3412
- children: [
3413
- /* @__PURE__ */ jsx20(ThreadListSidebar, { footer: walletFooter == null ? void 0 : walletFooter({ wallet, setWallet }) }),
3414
- /* @__PURE__ */ jsxs13(SidebarInset, { className: "relative", children: [
3415
- /* @__PURE__ */ jsxs13("header", { className: "flex h-14 mt-1 shrink-0 items-center gap-2 border-b px-3", children: [
3416
- /* @__PURE__ */ jsx20(SidebarTrigger, {}),
3417
- /* @__PURE__ */ jsx20(Separator, { orientation: "vertical", className: "mr-2 h-4" }),
3418
- /* @__PURE__ */ jsx20(Breadcrumb, { children: /* @__PURE__ */ jsxs13(BreadcrumbList, { children: [
3419
- /* @__PURE__ */ jsx20(BreadcrumbItem, { className: "hidden md:block", children: currentTitle }),
3420
- /* @__PURE__ */ jsx20(BreadcrumbSeparator, { className: "hidden md:block" })
3421
- ] }) })
3422
- ] }),
3423
- /* @__PURE__ */ jsx20("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx20(Thread, {}, `${currentThreadId}-${threadViewKey}`) })
3424
- ] })
3425
- ]
3426
- }
3427
- )
3428
- ] });
3429
- };
3430
-
3431
- // src/components/assistant-ui/base-sidebar.tsx
3432
- import Link2 from "next/link";
3433
- import Image4 from "next/image";
3434
- import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
3435
- function BaseSidebar(_a) {
3436
- var _b = _a, {
3437
- footerLabel = "Connect Wallet",
3438
- footerSecondaryLabel,
3439
- onFooterClick,
3440
- logoUrl = "/assets/images/a.svg",
3441
- logoHref = "https://aomi.dev"
3442
- } = _b, props = __objRest(_b, [
3443
- "footerLabel",
3444
- "footerSecondaryLabel",
3445
- "onFooterClick",
3446
- "logoUrl",
3447
- "logoHref"
3448
- ]);
3449
- return /* @__PURE__ */ jsxs14(
3450
- Sidebar,
3451
- __spreadProps(__spreadValues({
3452
- collapsible: "offcanvas",
3453
- variant: "inset",
3454
- className: "relative"
3455
- }, props), {
3456
- children: [
3457
- /* @__PURE__ */ jsx21(SidebarHeader, { className: "aomi-sidebar-header", children: /* @__PURE__ */ jsx21("div", { className: "aomi-sidebar-header-content flex items-center justify-between", children: /* @__PURE__ */ jsx21(SidebarMenu, { children: /* @__PURE__ */ jsx21(SidebarMenuItem, { children: /* @__PURE__ */ jsx21(SidebarMenuButton, { size: "lg", asChild: true, children: /* @__PURE__ */ jsx21(
3458
- Link2,
3459
- {
3460
- href: logoHref,
3461
- target: "_blank",
3462
- rel: "noopener noreferrer",
3463
- children: /* @__PURE__ */ jsx21("div", { className: "aomi-sidebar-header-icon-wrapper flex aspect-square size-8 items-center justify-center rounded-lg bg-white", children: /* @__PURE__ */ jsx21(
3464
- Image4,
3465
- {
3466
- src: logoUrl,
3467
- alt: "Logo",
3468
- width: 28,
3469
- height: 28,
3470
- className: "aomi-sidebar-header-icon size-7 ml-3",
3471
- priority: true
3472
- }
3473
- ) })
3474
- }
3475
- ) }) }) }) }) }),
3476
- /* @__PURE__ */ jsx21(SidebarContent, { className: "aomi-sidebar-content", children: /* @__PURE__ */ jsx21(ThreadList, {}) }),
3477
- /* @__PURE__ */ jsx21(SidebarRail, {}),
3478
- /* @__PURE__ */ jsx21(SidebarFooter, { className: "aomi-sidebar-footer border-t border-sm py-4", children: /* @__PURE__ */ jsx21(SidebarMenu, { children: /* @__PURE__ */ jsx21(SidebarMenuItem, { children: /* @__PURE__ */ jsx21(SidebarMenuButton, { size: "lg", asChild: true, children: /* @__PURE__ */ jsx21(
3479
- Button,
3480
- {
3481
- className: "w-full justify-center rounded-full text-white shadow-lg hover:bg-[var(--muted-foreground)] hover:text-white",
3482
- onClick: onFooterClick,
3483
- children: /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
3484
- /* @__PURE__ */ jsx21("span", { className: "text-sm", children: footerLabel }),
3485
- footerSecondaryLabel ? /* @__PURE__ */ jsxs14("span", { className: "text-[11px] text-white/80", children: [
3486
- "\u2022 ",
3487
- footerSecondaryLabel
3488
- ] }) : null
3489
- ] })
3490
- }
3491
- ) }) }) }) })
3492
- ]
3493
- })
3494
- );
3495
- }
3496
-
3497
- // src/components/ui/card.tsx
3498
- import * as React3 from "react";
3499
- import { jsx as jsx22 } from "react/jsx-runtime";
3500
- var Card = React3.forwardRef((_a, ref) => {
3501
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
3502
- return /* @__PURE__ */ jsx22(
3503
- "div",
3504
- __spreadValues({
3505
- ref,
3506
- className: cn(
3507
- "rounded-lg border bg-card text-card-foreground shadow-sm",
3508
- className
3509
- )
3510
- }, props)
3511
- );
3512
- });
3513
- Card.displayName = "Card";
3514
- var CardHeader = React3.forwardRef((_a, ref) => {
3515
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
3516
- return /* @__PURE__ */ jsx22(
3517
- "div",
3518
- __spreadValues({
3519
- ref,
3520
- className: cn("flex flex-col space-y-1.5 p-6", className)
3521
- }, props)
3522
- );
3523
- });
3524
- CardHeader.displayName = "CardHeader";
3525
- var CardTitle = React3.forwardRef((_a, ref) => {
3526
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
3527
- return /* @__PURE__ */ jsx22(
3528
- "h3",
3529
- __spreadValues({
3530
- ref,
3531
- className: cn(
3532
- "text-2xl font-semibold leading-none tracking-tight",
3533
- className
3534
- )
3535
- }, props)
3536
- );
3537
- });
3538
- CardTitle.displayName = "CardTitle";
3539
- var CardDescription = React3.forwardRef((_a, ref) => {
3540
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
3541
- return /* @__PURE__ */ jsx22(
3542
- "p",
3543
- __spreadValues({
3544
- ref,
3545
- className: cn("text-sm text-muted-foreground", className)
3546
- }, props)
3547
- );
3548
- });
3549
- CardDescription.displayName = "CardDescription";
3550
- var CardContent = React3.forwardRef((_a, ref) => {
3551
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
3552
- return /* @__PURE__ */ jsx22("div", __spreadValues({ ref, className: cn("p-6 pt-0", className) }, props));
3553
- });
3554
- CardContent.displayName = "CardContent";
3555
- var CardFooter = React3.forwardRef((_a, ref) => {
3556
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
3557
- return /* @__PURE__ */ jsx22(
3558
- "div",
3559
- __spreadValues({
3560
- ref,
3561
- className: cn("flex items-center p-6 pt-0", className)
3562
- }, props)
3563
- );
3564
- });
3565
- CardFooter.displayName = "CardFooter";
3566
-
3567
- // src/components/ui/badge.tsx
3568
- import { cva as cva3 } from "class-variance-authority";
3569
- import { jsx as jsx23 } from "react/jsx-runtime";
3570
- var badgeVariants = cva3(
3571
- "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
3572
- {
3573
- variants: {
3574
- variant: {
3575
- default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
3576
- secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
3577
- destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
3578
- outline: "text-foreground"
3579
- }
3580
- },
3581
- defaultVariants: {
3582
- variant: "default"
3583
- }
3584
- }
3585
- );
3586
- function Badge(_a) {
3587
- var _b = _a, { className, variant } = _b, props = __objRest(_b, ["className", "variant"]);
3588
- return /* @__PURE__ */ jsx23("div", __spreadValues({ className: cn(badgeVariants({ variant }), className) }, props));
3589
- }
3590
-
3591
- // src/components/ui/label.tsx
3592
- import * as React4 from "react";
3593
- import { jsx as jsx24 } from "react/jsx-runtime";
3594
- var Label = React4.forwardRef((_a, ref) => {
3595
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
3596
- return /* @__PURE__ */ jsx24(
3597
- "label",
3598
- __spreadValues({
3599
- ref,
3600
- className: cn(
3601
- "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
3602
- className
3603
- )
3604
- }, props)
3605
- );
3606
- });
3607
- Label.displayName = "Label";
3608
- export {
3609
- AomiFrame,
3610
- AomiRuntimeProvider,
3611
- Avatar,
3612
- AvatarFallback,
3613
- AvatarImage,
3614
- Badge,
3615
- BaseSidebar,
3616
- Breadcrumb,
3617
- BreadcrumbEllipsis,
3618
- BreadcrumbItem,
3619
- BreadcrumbLink,
3620
- BreadcrumbList,
3621
- BreadcrumbPage,
3622
- BreadcrumbSeparator,
3623
- Button,
3624
- Card,
3625
- CardContent,
3626
- CardDescription,
3627
- CardFooter,
3628
- CardHeader,
3629
- CardTitle,
3630
- ComposerAttachments,
3631
- Dialog,
3632
- DialogClose,
3633
- DialogContent,
3634
- DialogDescription,
3635
- DialogFooter,
3636
- DialogHeader,
3637
- DialogOverlay,
3638
- DialogPortal,
3639
- DialogTitle,
3640
- DialogTrigger,
3641
- Input,
3642
- Label,
3643
- MarkdownText,
3644
- Separator,
3645
- Sheet,
3646
- SheetClose,
3647
- SheetContent,
3648
- SheetDescription,
3649
- SheetFooter,
3650
- SheetHeader,
3651
- SheetTitle,
3652
- SheetTrigger,
3653
- Sidebar,
3654
- SidebarContent,
3655
- SidebarFooter,
3656
- SidebarGroup,
3657
- SidebarGroupAction,
3658
- SidebarGroupContent,
3659
- SidebarGroupLabel,
3660
- SidebarHeader,
3661
- SidebarInset,
3662
- SidebarMenu,
3663
- SidebarMenuAction,
3664
- SidebarMenuBadge,
3665
- SidebarMenuButton,
3666
- SidebarMenuItem,
3667
- SidebarMenuSub,
3668
- SidebarMenuSubButton,
3669
- SidebarMenuSubItem,
3670
- SidebarProvider,
3671
- SidebarRail,
3672
- SidebarSeparator,
3673
- SidebarTrigger,
3674
- Skeleton,
3675
- Thread,
3676
- ThreadContextProvider,
3677
- ThreadList,
3678
- ThreadListSidebar,
3679
- ToolFallback,
3680
- Tooltip,
3681
- TooltipContent,
3682
- TooltipIconButton,
3683
- TooltipProvider,
3684
- TooltipTrigger,
3685
- UserMessageAttachments,
3686
- badgeVariants,
3687
- buttonVariants,
3688
- cn,
3689
- formatAddress,
3690
- getNetworkName,
3691
- useIsMobile,
3692
- useRuntimeActions,
3693
- useSidebar,
3694
- useThreadContext
3695
- };
3696
- //# sourceMappingURL=index.js.map