@timbal-ai/timbal-react 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -32,11 +32,13 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  ARTIFACT_AGENT_INSTRUCTIONS: () => ARTIFACT_AGENT_INSTRUCTIONS,
34
34
  ARTIFACT_FENCE_LANGUAGES: () => ARTIFACT_FENCE_LANGUAGES,
35
- ActionBarPrimitive: () => import_react26.ActionBarPrimitive,
35
+ ActionBarMorePrimitive: () => import_react29.ActionBarMorePrimitive,
36
+ ActionBarPrimitive: () => import_react29.ActionBarPrimitive,
36
37
  ArtifactCard: () => ArtifactCard,
37
38
  ArtifactRegistryProvider: () => ArtifactRegistryProvider,
38
39
  ArtifactView: () => ArtifactView,
39
- AssistantRuntimeProvider: () => import_react26.AssistantRuntimeProvider,
40
+ AssistantRuntimeProvider: () => import_react29.AssistantRuntimeProvider,
41
+ AuiIf: () => import_react29.AuiIf,
40
42
  AuthGuard: () => AuthGuard,
41
43
  Avatar: () => Avatar,
42
44
  AvatarFallback: () => AvatarFallback,
@@ -46,7 +48,7 @@ __export(index_exports, {
46
48
  Composer: () => Composer,
47
49
  ComposerAddAttachment: () => ComposerAddAttachment,
48
50
  ComposerAttachments: () => ComposerAttachments,
49
- ComposerPrimitive: () => import_react26.ComposerPrimitive,
51
+ ComposerPrimitive: () => import_react29.ComposerPrimitive,
50
52
  DEFAULT_UPLOAD_ACCEPT: () => DEFAULT_UPLOAD_ACCEPT,
51
53
  Dialog: () => Dialog,
52
54
  DialogClose: () => DialogClose,
@@ -55,23 +57,44 @@ __export(index_exports, {
55
57
  DialogPortal: () => DialogPortal,
56
58
  DialogTitle: () => DialogTitle,
57
59
  DialogTrigger: () => DialogTrigger,
60
+ ErrorPrimitive: () => import_react29.ErrorPrimitive,
58
61
  HtmlArtifactView: () => HtmlArtifactView,
59
62
  JsonArtifactView: () => JsonArtifactView,
60
63
  MarkdownText: () => MarkdownText,
61
- MessagePrimitive: () => import_react26.MessagePrimitive,
64
+ MessagePartPrimitive: () => import_react29.MessagePartPrimitive,
65
+ MessagePrimitive: () => import_react29.MessagePrimitive,
62
66
  QuestionArtifactView: () => QuestionArtifactView,
67
+ STUDIO_INSET_LEFT: () => STUDIO_INSET_LEFT,
68
+ STUDIO_PILL_HEIGHT: () => STUDIO_PILL_HEIGHT,
69
+ STUDIO_SIDEBAR_GAP: () => STUDIO_SIDEBAR_GAP,
70
+ STUDIO_SIDEBAR_WIDTH: () => STUDIO_SIDEBAR_WIDTH,
71
+ STUDIO_TOPBAR_GAP: () => STUDIO_TOPBAR_GAP,
72
+ STUDIO_TOPBAR_HEIGHT: () => STUDIO_TOPBAR_HEIGHT,
63
73
  SessionProvider: () => SessionProvider,
64
74
  Shimmer: () => Shimmer,
65
75
  Suggestions: () => Suggestions,
66
76
  SyntaxHighlighter: () => syntax_highlighter_default,
77
+ TIMBAL_V2_BORDER: () => TIMBAL_V2_BORDER,
78
+ TIMBAL_V2_FILL: () => TIMBAL_V2_FILL,
79
+ TIMBAL_V2_LABEL: () => TIMBAL_V2_LABEL,
80
+ TIMBAL_V2_PILL_SURFACE: () => TIMBAL_V2_PILL_SURFACE,
81
+ TIMBAL_V2_SECONDARY_CHROME: () => TIMBAL_V2_SECONDARY_CHROME,
82
+ TIMBAL_V2_SHADOW: () => TIMBAL_V2_SHADOW,
83
+ TIMBAL_V2_SIZE_HEIGHT: () => TIMBAL_V2_SIZE_HEIGHT,
84
+ TIMBAL_V2_SIZE_ICON: () => TIMBAL_V2_SIZE_ICON,
85
+ TIMBAL_V2_SIZE_LABEL_PX: () => TIMBAL_V2_SIZE_LABEL_PX,
67
86
  TableArtifactView: () => TableArtifactView,
68
87
  Thread: () => Thread,
69
- ThreadPrimitive: () => import_react26.ThreadPrimitive,
88
+ ThreadPrimitive: () => import_react29.ThreadPrimitive,
70
89
  TimbalChat: () => TimbalChat,
71
90
  TimbalChatShell: () => TimbalChatShell,
72
91
  TimbalRuntimeProvider: () => TimbalRuntimeProvider,
92
+ TimbalV2Button: () => TimbalV2Button,
73
93
  ToolArtifactFallback: () => ToolArtifactFallback,
94
+ ToolBodyPresence: () => ToolBodyPresence,
74
95
  ToolFallback: () => ToolFallback,
96
+ ToolMotion: () => ToolMotion,
97
+ ToolPresence: () => ToolPresence,
75
98
  Tooltip: () => Tooltip,
76
99
  TooltipContent: () => TooltipContent,
77
100
  TooltipIconButton: () => TooltipIconButton,
@@ -98,6 +121,7 @@ __export(index_exports, {
98
121
  isArtifact: () => isArtifact,
99
122
  isArtifactFenceLanguage: () => isArtifactFenceLanguage,
100
123
  isUiBinding: () => isUiBinding,
124
+ luxuryEase: () => luxuryEase,
101
125
  parseArtifactFromToolResult: () => parseArtifactFromToolResult,
102
126
  parseSSELine: () => import_timbal_sdk2.parseSSELine,
103
127
  refreshAccessToken: () => refreshAccessToken,
@@ -107,15 +131,42 @@ __export(index_exports, {
107
131
  setPath: () => setPath,
108
132
  setRefreshToken: () => setRefreshToken,
109
133
  splitMarkdownByArtifacts: () => splitMarkdownByArtifacts,
134
+ studioArtifactShellClass: () => studioArtifactShellClass,
135
+ studioChromeShellStyle: () => studioChromeShellStyle,
136
+ studioComposeInputShellClass: () => studioComposeInputShellClass,
137
+ studioComposerIoWellClass: () => studioComposerIoWellClass,
138
+ studioIntegrationBorder: () => studioIntegrationBorder,
139
+ studioIntegrationCardClass: () => studioIntegrationCardClass,
140
+ studioIntegrationIconTileClass: () => studioIntegrationIconTileClass,
141
+ studioIntegrationSurfaceSolid: () => studioIntegrationSurfaceSolid,
142
+ studioListRowButtonClass: () => studioListRowButtonClass,
143
+ studioPillSurfaceClass: () => studioPillSurfaceClass,
144
+ studioPlaygroundGradientClass: () => studioPlaygroundGradientClass,
145
+ studioQuestionOptionClass: () => studioQuestionOptionClass,
146
+ studioQuestionOptionSelectedClass: () => studioQuestionOptionSelectedClass,
147
+ studioSecondaryChromeClass: () => studioSecondaryChromeClass,
148
+ studioTimelineActionClass: () => studioTimelineActionClass,
149
+ studioTimelineBodyPadClass: () => studioTimelineBodyPadClass,
150
+ studioTimelineChevronClass: () => studioTimelineChevronClass,
151
+ studioTimelineDetailClass: () => studioTimelineDetailClass,
152
+ studioTimelineRowButtonClass: () => studioTimelineRowButtonClass,
153
+ studioTimelineShimmerActionClass: () => studioTimelineShimmerActionClass,
154
+ studioTimelineTextClass: () => studioTimelineTextClass,
155
+ studioToolCardShellClass: () => studioToolCardShellClass,
156
+ studioTopbarIconPillClass: () => studioTopbarIconPillClass,
157
+ studioTopbarPillHeightClass: () => studioTopbarPillHeightClass,
158
+ toolPresenceTransition: () => toolPresenceTransition,
110
159
  useArtifactRegistry: () => useArtifactRegistry,
111
- useComposerRuntime: () => import_react26.useComposerRuntime,
112
- useMessageRuntime: () => import_react26.useMessageRuntime,
160
+ useAuiState: () => import_react29.useAuiState,
161
+ useComposerRuntime: () => import_react29.useComposerRuntime,
162
+ useMessageRuntime: () => import_react29.useMessageRuntime,
113
163
  useResolvedSuggestions: () => useResolvedSuggestions,
114
164
  useSession: () => useSession,
115
- useThread: () => import_react26.useThread,
116
- useThreadRuntime: () => import_react26.useThreadRuntime,
165
+ useThread: () => import_react29.useThread,
166
+ useThreadRuntime: () => import_react29.useThreadRuntime,
117
167
  useTimbalRuntime: () => useTimbalRuntime,
118
168
  useTimbalStream: () => useTimbalStream,
169
+ useToolRunning: () => useToolRunning,
119
170
  useUiCustomNodeRegistry: () => useUiCustomNodeRegistry,
120
171
  useUiDispatch: () => useUiDispatch,
121
172
  useUiEventEmitter: () => useUiEventEmitter,
@@ -982,6 +1033,11 @@ function findParentIdFromAuiParent(messages, auiParentId) {
982
1033
  // src/index.ts
983
1034
  var import_timbal_sdk2 = require("@timbal-ai/timbal-sdk");
984
1035
 
1036
+ // src/components/thread.tsx
1037
+ var import_react25 = require("@assistant-ui/react");
1038
+ var import_lucide_react8 = require("lucide-react");
1039
+ var import_react26 = require("motion/react");
1040
+
985
1041
  // src/components/attachment.tsx
986
1042
  var import_react4 = require("react");
987
1043
  var import_lucide_react2 = require("lucide-react");
@@ -1189,83 +1245,143 @@ function AvatarFallback({
1189
1245
 
1190
1246
  // src/components/tooltip-icon-button.tsx
1191
1247
  var import_react3 = require("react");
1192
- var import_react_slot = require("@radix-ui/react-slot");
1193
1248
 
1194
- // src/ui/button.tsx
1195
- var import_class_variance_authority = require("class-variance-authority");
1249
+ // src/ui/timbal-v2-button.tsx
1250
+ var React = __toESM(require("react"), 1);
1196
1251
  var import_radix_ui4 = require("radix-ui");
1252
+
1253
+ // src/ui/timbal-v2-button-tokens.ts
1254
+ var TIMBAL_V2_SIZE_HEIGHT = {
1255
+ xs: "min-h-8 h-8",
1256
+ sm: "min-h-9 h-9",
1257
+ md: "min-h-10 h-10",
1258
+ lg: "min-h-11 h-11"
1259
+ };
1260
+ var TIMBAL_V2_SIZE_ICON = {
1261
+ xs: "min-h-8 min-w-8 size-8",
1262
+ sm: "min-h-8 min-w-8 size-8",
1263
+ md: "min-h-10 min-w-10 size-10",
1264
+ lg: "min-h-11 min-w-11 size-11"
1265
+ };
1266
+ var TIMBAL_V2_SIZE_LABEL_PX = {
1267
+ xs: "px-3",
1268
+ sm: "px-4",
1269
+ md: "px-5",
1270
+ lg: "px-6"
1271
+ };
1272
+ var TIMBAL_V2_FILL = {
1273
+ primary: "bg-gradient-to-b from-neutral-800 to-black group-hover/tbv2:from-neutral-700 group-hover/tbv2:to-neutral-900 group-active/tbv2:from-black group-active/tbv2:to-black dark:from-white dark:to-neutral-200 dark:group-hover/tbv2:from-white dark:group-hover/tbv2:to-neutral-100 dark:group-active/tbv2:from-neutral-200 dark:group-active/tbv2:to-neutral-400",
1274
+ informative: "bg-blue-600 group-active/tbv2:[background-image:linear-gradient(to_top,rgba(0,0,0,0.08),transparent_55%)]",
1275
+ destructive: "bg-gradient-to-b from-white to-neutral-50/75 group-hover/tbv2:from-red-50/90 group-hover/tbv2:to-red-100/70 group-active/tbv2:from-red-100/90 group-active/tbv2:to-red-200/65 dark:from-white/[0.05] dark:to-white/[0.025] dark:group-hover/tbv2:from-red-500/12 dark:group-hover/tbv2:to-red-500/8 dark:group-active/tbv2:from-red-500/20 dark:group-active/tbv2:to-red-500/12",
1276
+ secondary: "bg-gradient-to-b from-white to-neutral-50/70 group-hover/tbv2:from-neutral-50/50 group-hover/tbv2:to-neutral-100/65 group-active/tbv2:from-neutral-100/70 group-active/tbv2:to-neutral-200/65 dark:from-white/[0.05] dark:to-white/[0.025] dark:group-hover/tbv2:from-white/[0.07] dark:group-hover/tbv2:to-white/[0.045] dark:group-active/tbv2:from-white/[0.10] dark:group-active/tbv2:to-white/[0.07]",
1277
+ ghost: "bg-transparent group-hover/tbv2:bg-neutral-100/70 group-active/tbv2:bg-neutral-200/70 dark:group-hover/tbv2:bg-white/10 dark:group-active/tbv2:bg-white/15",
1278
+ link: "bg-transparent"
1279
+ };
1280
+ var TIMBAL_V2_LABEL = {
1281
+ primary: "text-white dark:text-neutral-900",
1282
+ informative: "text-white",
1283
+ destructive: "text-destructive dark:text-red-400",
1284
+ secondary: "text-foreground",
1285
+ ghost: "text-foreground",
1286
+ link: "text-foreground underline decoration-black/25 underline-offset-2 group-hover/tbv2:decoration-black/45 dark:decoration-white/25 dark:group-hover/tbv2:decoration-white/45"
1287
+ };
1288
+ var TIMBAL_V2_BORDER = {
1289
+ primary: "",
1290
+ informative: "border border-white/15 dark:border-white/10",
1291
+ destructive: "border border-destructive/45 dark:border-red-500/55",
1292
+ secondary: "border border-neutral-200/80 dark:border-white/[0.08]",
1293
+ ghost: "",
1294
+ link: ""
1295
+ };
1296
+ var TIMBAL_V2_SHADOW = {
1297
+ primary: "shadow-sm shadow-black/15 dark:shadow-black/40",
1298
+ informative: "shadow-sm shadow-blue-900/20 dark:shadow-black/40",
1299
+ destructive: "shadow-[0_1px_2px_-0.5px_rgba(0,0,0,0.05)] dark:shadow-[0_1px_3px_rgba(0,0,0,0.22)]",
1300
+ secondary: "shadow-[0_1px_2px_-0.5px_rgba(0,0,0,0.05)] dark:shadow-[0_1px_3px_rgba(0,0,0,0.22)]",
1301
+ ghost: "",
1302
+ link: ""
1303
+ };
1304
+ var TIMBAL_V2_PILL_SURFACE = "bg-gradient-to-b from-white to-neutral-50/70 border border-neutral-200/80 shadow-[0_1px_2px_-0.5px_rgba(0,0,0,0.05)] dark:from-white/[0.05] dark:to-white/[0.025] dark:border-white/[0.08] dark:shadow-[0_1px_3px_rgba(0,0,0,0.22)]";
1305
+ var TIMBAL_V2_SECONDARY_CHROME = "bg-gradient-to-b from-white to-neutral-50/70 border border-neutral-200/80 shadow-[0_1px_2px_-0.5px_rgba(0,0,0,0.05)] transition-[background-color,box-shadow,border-color] duration-200 ease-in-out hover:from-neutral-50/40 hover:to-neutral-100/60 active:from-neutral-100/65 active:to-neutral-200/65 dark:from-white/[0.05] dark:to-white/[0.025] dark:border-white/[0.08] dark:shadow-[0_1px_3px_rgba(0,0,0,0.22)] dark:hover:from-white/[0.07] dark:hover:to-white/[0.045] dark:active:from-white/[0.10] dark:active:to-white/[0.07]";
1306
+
1307
+ // src/ui/timbal-v2-button.tsx
1197
1308
  var import_jsx_runtime5 = require("react/jsx-runtime");
1198
- var buttonVariants = (0, import_class_variance_authority.cva)(
1199
- "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",
1200
- {
1201
- variants: {
1202
- variant: {
1203
- default: "bg-primary text-primary-foreground hover:bg-primary/90",
1204
- destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
1205
- 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",
1206
- secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
1207
- ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
1208
- link: "text-primary underline-offset-4 hover:underline"
1209
- },
1210
- size: {
1211
- default: "h-9 px-4 py-2 has-[>svg]:px-3",
1212
- xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
1213
- sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
1214
- lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
1215
- icon: "size-9",
1216
- "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
1217
- "icon-sm": "size-8",
1218
- "icon-lg": "size-10"
1219
- }
1220
- },
1221
- defaultVariants: {
1222
- variant: "default",
1223
- size: "default"
1224
- }
1225
- }
1226
- );
1227
- function Button({
1228
- className,
1229
- variant = "default",
1230
- size = "default",
1309
+ var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
1310
+ variant = "secondary",
1311
+ size = "sm",
1312
+ isIconOnly = false,
1313
+ isLoading = false,
1314
+ fullWidth = false,
1231
1315
  asChild = false,
1316
+ className,
1317
+ disabled,
1318
+ type = "button",
1319
+ children,
1232
1320
  ...props
1233
- }) {
1321
+ }, ref) {
1322
+ const isDisabled = disabled || isLoading;
1234
1323
  const Comp = asChild ? import_radix_ui4.Slot.Root : "button";
1235
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1324
+ const sizeClass = isIconOnly ? TIMBAL_V2_SIZE_ICON[size] : TIMBAL_V2_SIZE_HEIGHT[size];
1325
+ const radiusClass = variant === "link" || variant === "ghost" ? "rounded-md" : "rounded-full";
1326
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1236
1327
  Comp,
1237
1328
  {
1238
- "data-slot": "button",
1329
+ ref,
1330
+ type: asChild ? void 0 : type,
1331
+ disabled: asChild ? void 0 : isDisabled,
1332
+ "aria-disabled": asChild && isDisabled ? true : void 0,
1333
+ "data-slot": "timbal-v2-button",
1239
1334
  "data-variant": variant,
1240
- "data-size": size,
1241
- className: cn(buttonVariants({ variant, size, className })),
1242
- ...props
1335
+ className: cn(
1336
+ "group/tbv2 relative box-border inline-flex flex-col items-stretch overflow-hidden border-0 bg-transparent p-0 text-sm font-normal shadow-none transition duration-200 ease-in-out",
1337
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-400/60 focus-visible:ring-offset-1 focus-visible:ring-offset-background",
1338
+ sizeClass,
1339
+ radiusClass,
1340
+ TIMBAL_V2_BORDER[variant],
1341
+ TIMBAL_V2_SHADOW[variant],
1342
+ fullWidth && "w-full",
1343
+ isDisabled && "pointer-events-none opacity-50",
1344
+ className
1345
+ ),
1346
+ ...props,
1347
+ children: [
1348
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1349
+ "span",
1350
+ {
1351
+ "aria-hidden": true,
1352
+ className: cn(
1353
+ "pointer-events-none absolute inset-0 transition duration-200 ease-in-out",
1354
+ TIMBAL_V2_FILL[variant]
1355
+ )
1356
+ }
1357
+ ),
1358
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1359
+ "span",
1360
+ {
1361
+ className: cn(
1362
+ "relative z-10 flex min-h-0 flex-1 items-center justify-center gap-1 leading-tight",
1363
+ !isIconOnly && TIMBAL_V2_SIZE_LABEL_PX[size],
1364
+ TIMBAL_V2_LABEL[variant]
1365
+ ),
1366
+ children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "size-4 animate-spin rounded-full border-2 border-current border-t-transparent" }) : children
1367
+ }
1368
+ )
1369
+ ]
1243
1370
  }
1244
1371
  );
1245
- }
1372
+ });
1246
1373
 
1247
1374
  // src/components/tooltip-icon-button.tsx
1248
1375
  var import_jsx_runtime6 = require("react/jsx-runtime");
1249
- var TooltipIconButton = (0, import_react3.forwardRef)(({ children, tooltip, side = "bottom", className, ...rest }, ref) => {
1376
+ var TooltipIconButton = (0, import_react3.forwardRef)(function TooltipIconButton2({ tooltip, side = "bottom", variant = "secondary", children, ...props }, ref) {
1250
1377
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Tooltip, { children: [
1251
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1252
- Button,
1253
- {
1254
- variant: "ghost",
1255
- size: "icon",
1256
- ...rest,
1257
- className: cn("aui-button-icon size-6 p-1", className),
1258
- ref,
1259
- children: [
1260
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_slot.Slottable, { children }),
1261
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "aui-sr-only sr-only", children: tooltip })
1262
- ]
1263
- }
1264
- ) }),
1378
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(TimbalV2Button, { ref, variant, size: "sm", isIconOnly: true, ...props, children: [
1379
+ children,
1380
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "sr-only", children: tooltip })
1381
+ ] }) }),
1265
1382
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TooltipContent, { side, children: tooltip })
1266
1383
  ] });
1267
1384
  });
1268
- TooltipIconButton.displayName = "TooltipIconButton";
1269
1385
 
1270
1386
  // src/components/attachment.tsx
1271
1387
  var import_jsx_runtime7 = require("react/jsx-runtime");
@@ -1418,11 +1534,10 @@ var ComposerAddAttachment = () => {
1418
1534
  {
1419
1535
  tooltip: "Add Attachment",
1420
1536
  side: "bottom",
1421
- variant: "ghost",
1422
- size: "icon",
1423
- className: "aui-composer-add-attachment size-8.5 rounded-full p-1 font-semibold text-xs hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30",
1537
+ variant: "secondary",
1538
+ className: "aui-composer-add-attachment shrink-0 text-neutral-500 dark:text-muted-foreground",
1424
1539
  "aria-label": "Add Attachment",
1425
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.PlusIcon, { className: "aui-attachment-add-icon size-5 stroke-[1.5px]" })
1540
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.PlusIcon, { className: "aui-attachment-add-icon size-4 stroke-[1.5]" })
1426
1541
  }
1427
1542
  ) });
1428
1543
  };
@@ -1769,86 +1884,179 @@ function formatTick(v, unit) {
1769
1884
  var import_react7 = require("react");
1770
1885
  var import_react8 = require("@assistant-ui/react");
1771
1886
  var import_lucide_react3 = require("lucide-react");
1887
+
1888
+ // src/ui/chrome.ts
1889
+ var STUDIO_TOPBAR_GAP = "0.5rem";
1890
+ var STUDIO_TOPBAR_HEIGHT = "3rem";
1891
+ var STUDIO_PILL_HEIGHT = "2.5rem";
1892
+ var STUDIO_SIDEBAR_GAP = "0.5rem";
1893
+ var STUDIO_SIDEBAR_WIDTH = "3rem";
1894
+ var STUDIO_INSET_LEFT = `calc(${STUDIO_SIDEBAR_GAP} + ${STUDIO_SIDEBAR_WIDTH})`;
1895
+ var studioChromeShellStyle = {
1896
+ "--studio-topbar-gap": STUDIO_TOPBAR_GAP,
1897
+ "--studio-topbar-height": STUDIO_TOPBAR_HEIGHT,
1898
+ "--studio-chrome-pill-height": STUDIO_PILL_HEIGHT,
1899
+ "--studio-inset-top": `calc(${STUDIO_TOPBAR_GAP} + ${STUDIO_TOPBAR_HEIGHT})`,
1900
+ "--studio-sidebar-gap": STUDIO_SIDEBAR_GAP,
1901
+ "--studio-sidebar-width": STUDIO_SIDEBAR_WIDTH,
1902
+ "--studio-inset-left": STUDIO_INSET_LEFT
1903
+ };
1904
+ var studioTopbarPillHeightClass = "h-[var(--studio-chrome-pill-height)] min-h-[var(--studio-chrome-pill-height)]";
1905
+ var studioTopbarIconPillClass = "shrink-0 flex-none size-[var(--studio-chrome-pill-height)] min-h-[var(--studio-chrome-pill-height)] min-w-[var(--studio-chrome-pill-height)]";
1906
+ var studioPlaygroundGradientClass = "bg-gradient-to-b from-neutral-200/60 via-neutral-100/30 to-background dark:from-zinc-800 dark:via-zinc-900 dark:to-zinc-950";
1907
+ var studioComposeInputShellClass = "flex w-full flex-col rounded-2xl border border-neutral-200/60 bg-background shadow-lg shadow-black/5 outline-none transition-[box-shadow,border-color] focus-within:border-neutral-400/80 focus-within:ring-2 focus-within:ring-foreground/5 focus-within:shadow-xl focus-within:shadow-black/10 dark:border-white/12 dark:bg-zinc-900 dark:shadow-black/20 dark:focus-within:border-white/22 dark:focus-within:ring-0";
1908
+ var studioPillSurfaceClass = TIMBAL_V2_PILL_SURFACE;
1909
+ var studioSecondaryChromeClass = TIMBAL_V2_SECONDARY_CHROME;
1910
+ var studioIntegrationSurfaceSolid = "bg-white bg-gradient-to-b from-white to-neutral-50/70 shadow-[0_1px_2px_-0.5px_rgba(0,0,0,0.05)] dark:bg-zinc-900 dark:from-white/[0.05] dark:to-white/[0.025] dark:shadow-[0_1px_3px_rgba(0,0,0,0.22)]";
1911
+ var studioIntegrationBorder = "border border-neutral-200/80 dark:border-white/[0.08]";
1912
+ var studioIntegrationCardClass = cn(
1913
+ "rounded-xl",
1914
+ studioIntegrationSurfaceSolid,
1915
+ studioIntegrationBorder
1916
+ );
1917
+ var studioIntegrationIconTileClass = cn(
1918
+ "flex size-9 shrink-0 items-center justify-center rounded-lg",
1919
+ studioIntegrationSurfaceSolid,
1920
+ studioIntegrationBorder
1921
+ );
1922
+ var studioListRowButtonClass = cn(
1923
+ "flex w-full cursor-pointer items-center gap-3 rounded-xl px-3 py-2.5 text-left",
1924
+ studioIntegrationCardClass,
1925
+ "transition-[background-color,box-shadow,border-color] duration-200 ease-in-out",
1926
+ "hover:border-neutral-300 dark:hover:border-white/15",
1927
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2 focus-visible:ring-offset-background dark:focus-visible:ring-white/20"
1928
+ );
1929
+ var studioComposerIoWellClass = cn(
1930
+ "rounded-lg",
1931
+ studioIntegrationSurfaceSolid,
1932
+ studioIntegrationBorder
1933
+ );
1934
+ var studioToolCardShellClass = cn(
1935
+ studioIntegrationCardClass,
1936
+ "my-2 min-h-0 overflow-hidden"
1937
+ );
1938
+ var studioTimelineRowButtonClass = "group flex w-full min-w-0 cursor-pointer items-center justify-start rounded-md border-0 bg-transparent py-1 text-left shadow-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2";
1939
+ var studioTimelineTextClass = "text-xs font-normal leading-snug";
1940
+ var studioTimelineActionClass = cn(
1941
+ studioTimelineTextClass,
1942
+ "shrink-0 text-foreground/70 transition-colors duration-150 group-hover:text-foreground/80"
1943
+ );
1944
+ var studioTimelineShimmerActionClass = cn(
1945
+ studioTimelineTextClass,
1946
+ "shrink-0"
1947
+ );
1948
+ var studioTimelineDetailClass = cn(
1949
+ studioTimelineTextClass,
1950
+ "min-w-0 truncate text-muted-foreground transition-colors duration-150"
1951
+ );
1952
+ function studioTimelineChevronClass(expanded) {
1953
+ return cn(
1954
+ "ml-0.5 size-3 min-h-3 min-w-3 shrink-0 transition-all duration-150",
1955
+ expanded ? "rotate-90 text-foreground opacity-60" : "text-muted-foreground opacity-0 group-hover:opacity-70"
1956
+ );
1957
+ }
1958
+ var studioTimelineBodyPadClass = "flex flex-col gap-2 pt-0.5 pb-0.5";
1959
+ var studioArtifactShellClass = cn(
1960
+ studioIntegrationCardClass,
1961
+ "my-2 w-full min-w-0 overflow-hidden"
1962
+ );
1963
+ var studioQuestionOptionClass = "flex w-full items-center gap-2 rounded-lg border border-transparent px-2 py-1.5 text-left text-sm transition-[background-color,border-color,box-shadow] duration-200 hover:bg-neutral-100/80 dark:hover:bg-white/[0.05] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2";
1964
+ var studioQuestionOptionSelectedClass = cn(
1965
+ studioQuestionOptionClass,
1966
+ "border-neutral-200/80 bg-neutral-50/90 ring-1 ring-foreground/10 dark:border-white/[0.12] dark:bg-white/[0.06] dark:ring-white/10"
1967
+ );
1968
+
1969
+ // src/artifacts/question-artifact.tsx
1772
1970
  var import_jsx_runtime10 = require("react/jsx-runtime");
1971
+ function optionKey(option, index) {
1972
+ const id = option.id?.trim();
1973
+ return id ? id : `__option-${index}`;
1974
+ }
1975
+ var OptionRadio = ({ selected }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1976
+ "span",
1977
+ {
1978
+ className: cn(
1979
+ "flex size-4 shrink-0 items-center justify-center rounded-full border-2 transition-colors",
1980
+ selected ? "border-foreground bg-foreground text-background" : "border-neutral-300 bg-background dark:border-white/20"
1981
+ ),
1982
+ "aria-hidden": true,
1983
+ children: selected ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.CheckIcon, { className: "size-2.5 stroke-[3]" }) : null
1984
+ }
1985
+ );
1773
1986
  var QuestionArtifactView = ({
1774
1987
  artifact
1775
1988
  }) => {
1776
1989
  const runtime = (0, import_react8.useThreadRuntime)();
1777
1990
  const [selected, setSelected] = (0, import_react7.useState)([]);
1778
- const [submitted, setSubmitted] = (0, import_react7.useState)(null);
1991
+ const [submittedIds, setSubmittedIds] = (0, import_react7.useState)(null);
1779
1992
  const isMulti = artifact.multi === true;
1780
- const send = (labels) => {
1781
- if (labels.length === 0) return;
1782
- const text = labels.join(", ");
1783
- setSubmitted(text);
1784
- runtime.append({ role: "user", content: [{ type: "text", text }] });
1785
- };
1786
- const onPick = (option) => {
1787
- if (submitted) return;
1788
- if (!isMulti) {
1789
- send([option.label]);
1790
- return;
1791
- }
1792
- setSelected(
1793
- (prev) => prev.includes(option.id) ? prev.filter((id) => id !== option.id) : [...prev, option.id]
1794
- );
1795
- };
1796
- const onConfirm = () => {
1797
- const labels = artifact.options.filter((o) => selected.includes(o.id)).map((o) => o.label);
1798
- send(labels);
1799
- };
1800
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ArtifactCard, { kind: "question", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "aui-artifact-question p-3", children: [
1801
- artifact.prompt && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "aui-artifact-question-prompt mb-2 text-sm text-foreground/85", children: artifact.prompt }),
1802
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "aui-artifact-question-options flex flex-col gap-1.5", children: artifact.options.map((option) => {
1803
- const isSelected = isMulti && selected.includes(option.id);
1804
- const isDisabled = Boolean(submitted);
1993
+ const isDisabled = submittedIds !== null;
1994
+ const send = (0, import_react7.useCallback)(
1995
+ (keys) => {
1996
+ if (keys.length === 0) return;
1997
+ const labels = artifact.options.map((option, index) => ({ option, key: optionKey(option, index) })).filter(({ key }) => keys.includes(key)).map(({ option }) => option.label);
1998
+ setSubmittedIds(keys);
1999
+ runtime.append({
2000
+ role: "user",
2001
+ content: [{ type: "text", text: labels.join(", ") }]
2002
+ });
2003
+ },
2004
+ [artifact.options, runtime]
2005
+ );
2006
+ const onPick = (0, import_react7.useCallback)(
2007
+ (key) => {
2008
+ if (isDisabled) return;
2009
+ if (!isMulti) {
2010
+ send([key]);
2011
+ return;
2012
+ }
2013
+ setSelected(
2014
+ (prev) => prev.includes(key) ? prev.filter((id) => id !== key) : [...prev, key]
2015
+ );
2016
+ },
2017
+ [isDisabled, isMulti, send]
2018
+ );
2019
+ const onConfirm = (0, import_react7.useCallback)(() => {
2020
+ send(selected);
2021
+ }, [selected, send]);
2022
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: studioArtifactShellClass, "data-artifact-kind": "question", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "px-2.5 py-2", children: [
2023
+ artifact.prompt ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "mb-2 text-sm font-normal leading-snug text-foreground", children: artifact.prompt }) : null,
2024
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex flex-col gap-0.5", role: "list", children: artifact.options.map((option, index) => {
2025
+ const key = optionKey(option, index);
2026
+ const isSelected = submittedIds ? submittedIds.includes(key) : isMulti && selected.includes(key);
1805
2027
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1806
2028
  "button",
1807
2029
  {
1808
2030
  type: "button",
2031
+ role: "listitem",
1809
2032
  disabled: isDisabled,
1810
- onClick: () => onPick(option),
2033
+ onClick: () => onPick(key),
1811
2034
  className: cn(
1812
- "aui-artifact-question-option flex items-center gap-2 rounded-lg border px-3 py-2 text-left text-sm transition-colors",
1813
- "border-border/60 hover:border-primary/40 hover:bg-muted/40",
1814
- isSelected && "border-primary/60 bg-primary/5",
1815
- isDisabled && "cursor-not-allowed opacity-60 hover:border-border/60 hover:bg-transparent"
2035
+ isSelected ? studioQuestionOptionSelectedClass : studioQuestionOptionClass,
2036
+ isDisabled && (isSelected ? "cursor-default" : "cursor-not-allowed opacity-50")
1816
2037
  ),
1817
2038
  children: [
1818
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1819
- "span",
1820
- {
1821
- className: cn(
1822
- "flex size-4 shrink-0 items-center justify-center rounded-full border",
1823
- isSelected ? "border-primary bg-primary text-primary-foreground" : "border-border"
1824
- ),
1825
- "aria-hidden": true,
1826
- children: isSelected && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.CheckIcon, { className: "size-3" })
1827
- }
1828
- ),
1829
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "aui-artifact-question-option-text flex-1", children: [
1830
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "font-medium text-foreground/90", children: option.label }),
1831
- option.description && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-xs text-muted-foreground", children: option.description })
2039
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(OptionRadio, { selected: isSelected }),
2040
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "min-w-0 flex-1 text-left", children: [
2041
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "block font-normal text-foreground", children: option.label }),
2042
+ option.description ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: option.description }) : null
1832
2043
  ] })
1833
2044
  ]
1834
2045
  },
1835
- option.id
2046
+ key
1836
2047
  );
1837
2048
  }) }),
1838
- isMulti && !submitted && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1839
- Button,
2049
+ isMulti && !submittedIds ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2050
+ TimbalV2Button,
1840
2051
  {
1841
2052
  type: "button",
2053
+ variant: "primary",
1842
2054
  size: "sm",
1843
2055
  disabled: selected.length === 0,
1844
2056
  onClick: onConfirm,
1845
2057
  children: "Confirm"
1846
2058
  }
1847
- ) }),
1848
- submitted && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("p", { className: "aui-artifact-question-submitted mt-2 text-xs text-muted-foreground", children: [
1849
- "Sent: ",
1850
- submitted
1851
- ] })
2059
+ ) }) : null
1852
2060
  ] }) });
1853
2061
  };
1854
2062
 
@@ -2019,29 +2227,84 @@ function useUiCustomNodeRegistry() {
2019
2227
  var import_react10 = require("react");
2020
2228
  var import_react11 = require("motion/react");
2021
2229
  var import_react12 = require("@assistant-ui/react");
2230
+
2231
+ // src/ui/button.tsx
2232
+ var import_class_variance_authority = require("class-variance-authority");
2233
+ var import_radix_ui5 = require("radix-ui");
2022
2234
  var import_jsx_runtime15 = require("react/jsx-runtime");
2235
+ var buttonVariants = (0, import_class_variance_authority.cva)(
2236
+ "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",
2237
+ {
2238
+ variants: {
2239
+ variant: {
2240
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
2241
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
2242
+ 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",
2243
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
2244
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
2245
+ link: "text-primary underline-offset-4 hover:underline"
2246
+ },
2247
+ size: {
2248
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
2249
+ xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
2250
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
2251
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
2252
+ icon: "size-9",
2253
+ "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
2254
+ "icon-sm": "size-8",
2255
+ "icon-lg": "size-10"
2256
+ }
2257
+ },
2258
+ defaultVariants: {
2259
+ variant: "default",
2260
+ size: "default"
2261
+ }
2262
+ }
2263
+ );
2264
+ function Button({
2265
+ className,
2266
+ variant = "default",
2267
+ size = "default",
2268
+ asChild = false,
2269
+ ...props
2270
+ }) {
2271
+ const Comp = asChild ? import_radix_ui5.Slot.Root : "button";
2272
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2273
+ Comp,
2274
+ {
2275
+ "data-slot": "button",
2276
+ "data-variant": variant,
2277
+ "data-size": size,
2278
+ className: cn(buttonVariants({ variant, size, className })),
2279
+ ...props
2280
+ }
2281
+ );
2282
+ }
2283
+
2284
+ // src/artifacts/ui/nodes.tsx
2285
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2023
2286
  var UiNodeView = ({ node }) => {
2024
2287
  switch (node.kind) {
2025
2288
  case "box":
2026
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(BoxNode, { node });
2289
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(BoxNode, { node });
2027
2290
  case "text":
2028
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TextNode, { node });
2291
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TextNode, { node });
2029
2292
  case "heading":
2030
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(HeadingNode, { node });
2293
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(HeadingNode, { node });
2031
2294
  case "badge":
2032
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(BadgeNode, { node });
2295
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(BadgeNode, { node });
2033
2296
  case "button":
2034
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ButtonNode, { node });
2297
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ButtonNode, { node });
2035
2298
  case "toggle":
2036
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ToggleNode, { node });
2299
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ToggleNode, { node });
2037
2300
  case "slider":
2038
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SliderNode, { node });
2301
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SliderNode, { node });
2039
2302
  case "tooltip":
2040
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TooltipNode, { node });
2303
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipNode, { node });
2041
2304
  case "draggable":
2042
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DraggableNode, { node });
2305
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DraggableNode, { node });
2043
2306
  case "custom":
2044
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CustomNode, { node });
2307
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CustomNode, { node });
2045
2308
  default:
2046
2309
  return null;
2047
2310
  }
@@ -2101,7 +2364,7 @@ var JUSTIFY_CLS = {
2101
2364
  };
2102
2365
  var BoxNode = ({ node }) => {
2103
2366
  const dir = node.direction ?? "col";
2104
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2367
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2105
2368
  "div",
2106
2369
  {
2107
2370
  className: cn(
@@ -2116,7 +2379,7 @@ var BoxNode = ({ node }) => {
2116
2379
  gap: node.gap !== void 0 ? `${node.gap * 0.25}rem` : void 0,
2117
2380
  padding: node.padding !== void 0 ? `${node.padding * 0.25}rem` : void 0
2118
2381
  },
2119
- children: node.children?.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(UiNodeView, { node: child }, child.id ?? i))
2382
+ children: node.children?.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(UiNodeView, { node: child }, child.id ?? i))
2120
2383
  }
2121
2384
  );
2122
2385
  };
@@ -2135,7 +2398,7 @@ var TEXT_WEIGHT = {
2135
2398
  var TextNode = ({ node }) => {
2136
2399
  const state = useUiState();
2137
2400
  const value = resolveBindable(node.value, state);
2138
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2401
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2139
2402
  "span",
2140
2403
  {
2141
2404
  className: cn(
@@ -2166,13 +2429,13 @@ var HeadingNode = ({ node }) => {
2166
2429
  );
2167
2430
  switch (level) {
2168
2431
  case 1:
2169
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h1", { className: cls, children: value });
2432
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h1", { className: cls, children: value });
2170
2433
  case 2:
2171
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { className: cls, children: value });
2434
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h2", { className: cls, children: value });
2172
2435
  case 3:
2173
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { className: cls, children: value });
2436
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h3", { className: cls, children: value });
2174
2437
  case 4:
2175
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h4", { className: cls, children: value });
2438
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h4", { className: cls, children: value });
2176
2439
  }
2177
2440
  };
2178
2441
  var BADGE_TONE = {
@@ -2185,7 +2448,7 @@ var BADGE_TONE = {
2185
2448
  var BadgeNode = ({ node }) => {
2186
2449
  const state = useUiState();
2187
2450
  const value = String(resolveBindable(node.value, state) ?? "");
2188
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2451
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2189
2452
  "span",
2190
2453
  {
2191
2454
  className: cn(
@@ -2202,7 +2465,7 @@ var ButtonNode = ({ node }) => {
2202
2465
  const run = useActionRunner();
2203
2466
  const label = String(resolveBindable(node.label, state) ?? "");
2204
2467
  const disabled = node.disabled !== void 0 ? Boolean(resolveBindable(node.disabled, state)) : false;
2205
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2468
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2206
2469
  Button,
2207
2470
  {
2208
2471
  variant: node.variant ?? "default",
@@ -2224,7 +2487,7 @@ var ToggleNode = ({ node }) => {
2224
2487
  dispatch({ type: "toggle", path: node.binding });
2225
2488
  run(node.onChange);
2226
2489
  };
2227
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2490
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
2228
2491
  "label",
2229
2492
  {
2230
2493
  className: cn(
@@ -2232,7 +2495,7 @@ var ToggleNode = ({ node }) => {
2232
2495
  node.className
2233
2496
  ),
2234
2497
  children: [
2235
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2498
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2236
2499
  "button",
2237
2500
  {
2238
2501
  type: "button",
@@ -2243,7 +2506,7 @@ var ToggleNode = ({ node }) => {
2243
2506
  "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border transition-colors",
2244
2507
  value ? "border-primary bg-primary" : "border-border bg-muted hover:bg-muted/80"
2245
2508
  ),
2246
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2509
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2247
2510
  "span",
2248
2511
  {
2249
2512
  className: cn(
@@ -2255,7 +2518,7 @@ var ToggleNode = ({ node }) => {
2255
2518
  )
2256
2519
  }
2257
2520
  ),
2258
- label && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-foreground/85", children: label })
2521
+ label && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-foreground/85", children: label })
2259
2522
  ]
2260
2523
  }
2261
2524
  );
@@ -2275,12 +2538,12 @@ var SliderNode = ({ node }) => {
2275
2538
  const next = Number(e.target.value);
2276
2539
  dispatch({ type: "set", path: node.binding, value: next });
2277
2540
  };
2278
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: cn("aui-ui-slider flex flex-col gap-1", node.className), children: [
2279
- (label || showValue) && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
2280
- label && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: label }),
2281
- showValue && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "font-mono", children: value })
2541
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: cn("aui-ui-slider flex flex-col gap-1", node.className), children: [
2542
+ (label || showValue) && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
2543
+ label && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: label }),
2544
+ showValue && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-mono", children: value })
2282
2545
  ] }),
2283
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2546
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2284
2547
  "input",
2285
2548
  {
2286
2549
  type: "range",
@@ -2302,9 +2565,9 @@ var SliderNode = ({ node }) => {
2302
2565
  var TooltipNode = ({ node }) => {
2303
2566
  const state = useUiState();
2304
2567
  const content = String(resolveBindable(node.content, state) ?? "");
2305
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Tooltip, { children: [
2306
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: cn("aui-ui-tooltip-trigger inline-flex", node.className), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(UiNodeView, { node: node.child }) }) }),
2307
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TooltipContent, { side: node.side ?? "top", children: content })
2568
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Tooltip, { children: [
2569
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: cn("aui-ui-tooltip-trigger inline-flex", node.className), children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(UiNodeView, { node: node.child }) }) }),
2570
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipContent, { side: node.side ?? "top", children: content })
2308
2571
  ] }) });
2309
2572
  };
2310
2573
  var DraggableNode = ({ node }) => {
@@ -2312,7 +2575,7 @@ var DraggableNode = ({ node }) => {
2312
2575
  const snapBack = node.snapBack ?? true;
2313
2576
  const axis = node.axis ?? "both";
2314
2577
  const dragProp = axis === "both" ? true : axis;
2315
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2578
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2316
2579
  import_react11.motion.div,
2317
2580
  {
2318
2581
  drag: dragProp,
@@ -2324,7 +2587,7 @@ var DraggableNode = ({ node }) => {
2324
2587
  "aui-ui-draggable inline-block cursor-grab touch-none",
2325
2588
  node.className
2326
2589
  ),
2327
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(UiNodeView, { node: node.child })
2590
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(UiNodeView, { node: node.child })
2328
2591
  }
2329
2592
  );
2330
2593
  };
@@ -2334,8 +2597,8 @@ var CustomNode = ({ node }) => {
2334
2597
  const Renderer = registry[node.name];
2335
2598
  if (!Renderer) return null;
2336
2599
  const resolvedProps = resolveProps(node.props ?? {}, state);
2337
- const children = node.children?.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(UiNodeView, { node: child }, child.id ?? i));
2338
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Renderer, { props: resolvedProps, children });
2600
+ const children = node.children?.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(UiNodeView, { node: child }, child.id ?? i));
2601
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Renderer, { props: resolvedProps, children });
2339
2602
  };
2340
2603
  function resolveProps(props, state) {
2341
2604
  const out = {};
@@ -2346,17 +2609,17 @@ function resolveProps(props, state) {
2346
2609
  }
2347
2610
 
2348
2611
  // src/artifacts/ui/ui-artifact.tsx
2349
- var import_jsx_runtime16 = require("react/jsx-runtime");
2612
+ var import_jsx_runtime17 = require("react/jsx-runtime");
2350
2613
  var UiArtifactView = ({ artifact }) => {
2351
2614
  const [state, dispatch] = (0, import_react13.useReducer)(
2352
2615
  uiStateReducer,
2353
2616
  artifact.initialState ?? {}
2354
2617
  );
2355
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ArtifactCard, { title: artifact.title, kind: "ui", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(UiStateProvider, { state, dispatch, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "aui-ui-root p-3", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(UiNodeView, { node: artifact.root }) }) }) });
2618
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ArtifactCard, { title: artifact.title, kind: "ui", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(UiStateProvider, { state, dispatch, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "aui-ui-root p-3", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(UiNodeView, { node: artifact.root }) }) }) });
2356
2619
  };
2357
2620
 
2358
2621
  // src/artifacts/registry.tsx
2359
- var import_jsx_runtime17 = require("react/jsx-runtime");
2622
+ var import_jsx_runtime18 = require("react/jsx-runtime");
2360
2623
  var defaultArtifactRenderers = {
2361
2624
  chart: ChartArtifactView,
2362
2625
  question: QuestionArtifactView,
@@ -2374,7 +2637,7 @@ var ArtifactRegistryProvider = ({ renderers, override, children }) => {
2374
2637
  if (override) return renderers;
2375
2638
  return { ...defaultArtifactRenderers, ...renderers };
2376
2639
  }, [renderers, override]);
2377
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ArtifactRegistryContext.Provider, { value: merged, children });
2640
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ArtifactRegistryContext.Provider, { value: merged, children });
2378
2641
  };
2379
2642
  function useArtifactRegistry() {
2380
2643
  return (0, import_react14.useContext)(ArtifactRegistryContext);
@@ -2383,7 +2646,7 @@ var ArtifactView = ({ artifact }) => {
2383
2646
  const registry = useArtifactRegistry();
2384
2647
  const Renderer = registry[artifact.type] ?? registry.json;
2385
2648
  if (!Renderer) return null;
2386
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Renderer, { artifact });
2649
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Renderer, { artifact });
2387
2650
  };
2388
2651
 
2389
2652
  // src/artifacts/parse.ts
@@ -2499,7 +2762,7 @@ var import_c = __toESM(require("shiki/langs/c.mjs"), 1);
2499
2762
  var import_cpp = __toESM(require("shiki/langs/cpp.mjs"), 1);
2500
2763
  var import_vitesse_dark = __toESM(require("shiki/themes/vitesse-dark.mjs"), 1);
2501
2764
  var import_vitesse_light = __toESM(require("shiki/themes/vitesse-light.mjs"), 1);
2502
- var import_jsx_runtime18 = require("react/jsx-runtime");
2765
+ var import_jsx_runtime19 = require("react/jsx-runtime");
2503
2766
  var SHIKI_THEME_DARK = "vitesse-dark";
2504
2767
  var SHIKI_THEME_LIGHT = "vitesse-light";
2505
2768
  var highlighterPromise = null;
@@ -2568,13 +2831,13 @@ var ShikiSyntaxHighlighter = ({
2568
2831
  try {
2569
2832
  const parsed = JSON.parse(code);
2570
2833
  if (isArtifact(parsed)) {
2571
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ArtifactView, { artifact: parsed });
2834
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ArtifactView, { artifact: parsed });
2572
2835
  }
2573
2836
  } catch {
2574
2837
  }
2575
2838
  }
2576
2839
  if (html) {
2577
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2840
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2578
2841
  "div",
2579
2842
  {
2580
2843
  className: "shiki-wrapper [&>pre]:!m-0 [&>pre]:!rounded-t-none [&>pre]:!rounded-b-lg [&>pre]:!border [&>pre]:!border-t-0 [&>pre]:!border-border/50 [&>pre]:!p-3 [&>pre]:!text-xs [&>pre]:!leading-relaxed [&>pre]:overflow-x-auto",
@@ -2582,14 +2845,14 @@ var ShikiSyntaxHighlighter = ({
2582
2845
  }
2583
2846
  );
2584
2847
  }
2585
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Pre, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Code2, { children: code }) });
2848
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Pre, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Code2, { children: code }) });
2586
2849
  };
2587
2850
  var syntax_highlighter_default = ShikiSyntaxHighlighter;
2588
2851
 
2589
2852
  // src/components/markdown-text.tsx
2590
- var import_jsx_runtime19 = require("react/jsx-runtime");
2853
+ var import_jsx_runtime20 = require("react/jsx-runtime");
2591
2854
  var MarkdownTextImpl = () => {
2592
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2855
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2593
2856
  import_react_markdown.MarkdownTextPrimitive,
2594
2857
  {
2595
2858
  remarkPlugins: [import_remark_gfm.default, import_remark_math.default],
@@ -2610,20 +2873,20 @@ var CodeHeader = ({ language, code }) => {
2610
2873
  if (!code || isCopied) return;
2611
2874
  copyToClipboard(code);
2612
2875
  };
2613
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "aui-code-header flex items-center justify-between rounded-t-lg border border-b-0 border-border/50 bg-zinc-100 px-4 py-2 dark:bg-zinc-800/80", children: [
2614
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "flex items-center gap-2 text-xs font-semibold tracking-wide text-muted-foreground/80 uppercase", children: [
2615
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "inline-block h-2 w-2 rounded-full bg-primary/40" }),
2876
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "aui-code-header flex items-center justify-between rounded-t-lg border border-b-0 border-border/50 bg-zinc-100 px-4 py-2 dark:bg-zinc-800/80", children: [
2877
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "flex items-center gap-2 text-xs font-semibold tracking-wide text-muted-foreground/80 uppercase", children: [
2878
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "inline-block h-2 w-2 rounded-full bg-primary/40" }),
2616
2879
  language
2617
2880
  ] }),
2618
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
2881
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2619
2882
  TooltipIconButton,
2620
2883
  {
2621
2884
  tooltip: isCopied ? "Copied!" : "Copy",
2622
2885
  onClick: onCopy,
2623
2886
  className: "transition-colors hover:text-foreground",
2624
2887
  children: [
2625
- !isCopied && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react4.CopyIcon, { className: "h-3.5 w-3.5" }),
2626
- isCopied && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react4.CheckIcon, { className: "h-3.5 w-3.5 text-emerald-500" })
2888
+ !isCopied && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react4.CopyIcon, { className: "h-3.5 w-3.5" }),
2889
+ isCopied && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react4.CheckIcon, { className: "h-3.5 w-3.5 text-emerald-500" })
2627
2890
  ]
2628
2891
  }
2629
2892
  )
@@ -2643,7 +2906,7 @@ var useCopyToClipboard = ({
2643
2906
  return { isCopied, copyToClipboard };
2644
2907
  };
2645
2908
  var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownComponents)({
2646
- h1: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2909
+ h1: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2647
2910
  "h1",
2648
2911
  {
2649
2912
  className: cn(
@@ -2653,7 +2916,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2653
2916
  ...props
2654
2917
  }
2655
2918
  ),
2656
- h2: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2919
+ h2: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2657
2920
  "h2",
2658
2921
  {
2659
2922
  className: cn(
@@ -2663,7 +2926,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2663
2926
  ...props
2664
2927
  }
2665
2928
  ),
2666
- h3: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2929
+ h3: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2667
2930
  "h3",
2668
2931
  {
2669
2932
  className: cn(
@@ -2673,7 +2936,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2673
2936
  ...props
2674
2937
  }
2675
2938
  ),
2676
- h4: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2939
+ h4: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2677
2940
  "h4",
2678
2941
  {
2679
2942
  className: cn(
@@ -2683,7 +2946,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2683
2946
  ...props
2684
2947
  }
2685
2948
  ),
2686
- h5: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2949
+ h5: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2687
2950
  "h5",
2688
2951
  {
2689
2952
  className: cn(
@@ -2693,7 +2956,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2693
2956
  ...props
2694
2957
  }
2695
2958
  ),
2696
- h6: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2959
+ h6: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2697
2960
  "h6",
2698
2961
  {
2699
2962
  className: cn(
@@ -2703,7 +2966,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2703
2966
  ...props
2704
2967
  }
2705
2968
  ),
2706
- p: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2969
+ p: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2707
2970
  "p",
2708
2971
  {
2709
2972
  className: cn(
@@ -2713,7 +2976,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2713
2976
  ...props
2714
2977
  }
2715
2978
  ),
2716
- a: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2979
+ a: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2717
2980
  "a",
2718
2981
  {
2719
2982
  className: cn(
@@ -2725,7 +2988,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2725
2988
  ...props
2726
2989
  }
2727
2990
  ),
2728
- blockquote: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2991
+ blockquote: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2729
2992
  "blockquote",
2730
2993
  {
2731
2994
  className: cn(
@@ -2735,7 +2998,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2735
2998
  ...props
2736
2999
  }
2737
3000
  ),
2738
- ul: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3001
+ ul: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2739
3002
  "ul",
2740
3003
  {
2741
3004
  className: cn(
@@ -2745,7 +3008,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2745
3008
  ...props
2746
3009
  }
2747
3010
  ),
2748
- ol: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3011
+ ol: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2749
3012
  "ol",
2750
3013
  {
2751
3014
  className: cn(
@@ -2755,7 +3018,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2755
3018
  ...props
2756
3019
  }
2757
3020
  ),
2758
- hr: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3021
+ hr: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2759
3022
  "hr",
2760
3023
  {
2761
3024
  className: cn(
@@ -2765,14 +3028,14 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2765
3028
  ...props
2766
3029
  }
2767
3030
  ),
2768
- table: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "my-4 w-full overflow-x-auto rounded-lg border border-border/50", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3031
+ table: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "my-4 w-full overflow-x-auto rounded-lg border border-border/50", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2769
3032
  "table",
2770
3033
  {
2771
3034
  className: cn("aui-md-table w-full border-collapse text-sm", className),
2772
3035
  ...props
2773
3036
  }
2774
3037
  ) }),
2775
- th: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3038
+ th: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2776
3039
  "th",
2777
3040
  {
2778
3041
  className: cn(
@@ -2782,7 +3045,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2782
3045
  ...props
2783
3046
  }
2784
3047
  ),
2785
- td: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3048
+ td: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2786
3049
  "td",
2787
3050
  {
2788
3051
  className: cn(
@@ -2792,7 +3055,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2792
3055
  ...props
2793
3056
  }
2794
3057
  ),
2795
- tr: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3058
+ tr: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2796
3059
  "tr",
2797
3060
  {
2798
3061
  className: cn(
@@ -2802,8 +3065,8 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2802
3065
  ...props
2803
3066
  }
2804
3067
  ),
2805
- li: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("li", { className: cn("aui-md-li leading-[1.7]", className), ...props }),
2806
- sup: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3068
+ li: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("li", { className: cn("aui-md-li leading-[1.7]", className), ...props }),
3069
+ sup: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2807
3070
  "sup",
2808
3071
  {
2809
3072
  className: cn(
@@ -2813,7 +3076,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2813
3076
  ...props
2814
3077
  }
2815
3078
  ),
2816
- pre: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3079
+ pre: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2817
3080
  "pre",
2818
3081
  {
2819
3082
  className: cn(
@@ -2825,7 +3088,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2825
3088
  ),
2826
3089
  code: function Code({ className, ...props }) {
2827
3090
  const isCodeBlock = (0, import_react_markdown.useIsMarkdownCodeBlock)();
2828
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3091
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2829
3092
  "code",
2830
3093
  {
2831
3094
  className: cn(
@@ -2836,19 +3099,20 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2836
3099
  }
2837
3100
  );
2838
3101
  },
2839
- strong: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("strong", { className: cn("font-semibold text-foreground", className), ...props }),
2840
- em: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("em", { className: cn("italic", className), ...props }),
3102
+ strong: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("strong", { className: cn("font-semibold text-foreground", className), ...props }),
3103
+ em: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("em", { className: cn("italic", className), ...props }),
2841
3104
  CodeHeader
2842
3105
  });
2843
3106
 
2844
3107
  // src/components/tool-fallback.tsx
2845
- var import_react19 = require("react");
3108
+ var import_react20 = require("react");
2846
3109
  var import_lucide_react5 = require("lucide-react");
3110
+ var import_react21 = require("@assistant-ui/react");
2847
3111
 
2848
3112
  // src/ui/shimmer.tsx
2849
3113
  var import_react17 = require("motion/react");
2850
3114
  var import_react18 = require("react");
2851
- var import_jsx_runtime20 = require("react/jsx-runtime");
3115
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2852
3116
  var ShimmerComponent = ({
2853
3117
  children,
2854
3118
  as: Component = "p",
@@ -2863,7 +3127,7 @@ var ShimmerComponent = ({
2863
3127
  () => (children?.length ?? 0) * spread,
2864
3128
  [children, spread]
2865
3129
  );
2866
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3130
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2867
3131
  MotionComponent,
2868
3132
  {
2869
3133
  animate: { backgroundPosition: "0% center" },
@@ -2888,78 +3152,130 @@ var ShimmerComponent = ({
2888
3152
  };
2889
3153
  var Shimmer = (0, import_react18.memo)(ShimmerComponent);
2890
3154
 
2891
- // src/components/tool-fallback.tsx
2892
- var import_jsx_runtime21 = require("react/jsx-runtime");
2893
- var ToolFallbackImpl = ({
2894
- toolName,
2895
- argsText,
2896
- result,
2897
- status
2898
- }) => {
2899
- const isRunning = status?.type === "running";
2900
- const isError = status?.type === "incomplete" && status.reason !== "cancelled";
2901
- if (isRunning) {
2902
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "aui-tool-fallback-running flex items-center gap-2 py-1 text-sm text-muted-foreground", children: [
2903
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react5.WrenchIcon, { className: "size-4" }),
2904
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Shimmer, { as: "span", duration: 1.8, spread: 2.5, children: `Using tool: ${toolName}` })
2905
- ] });
3155
+ // src/components/motion.tsx
3156
+ var import_react19 = require("motion/react");
3157
+ var import_jsx_runtime22 = require("react/jsx-runtime");
3158
+ var luxuryEase = [0.16, 1, 0.3, 1];
3159
+ var TOOL_ENTER_MS = 0.78;
3160
+ var TOOL_EXIT_MS = 0.28;
3161
+ function toolPresenceTransition(reduced) {
3162
+ return {
3163
+ enter: {
3164
+ duration: reduced ? 0.35 : TOOL_ENTER_MS,
3165
+ ease: luxuryEase
3166
+ },
3167
+ exit: {
3168
+ duration: reduced ? 0.2 : TOOL_EXIT_MS,
3169
+ ease: [0.4, 0, 1, 1]
3170
+ }
3171
+ };
3172
+ }
3173
+ function toolMotionState(reduced, entering, variant) {
3174
+ if (reduced) {
3175
+ return entering ? { opacity: 0, y: variant === "executing" ? 8 : 10 } : { opacity: 1, y: 0 };
2906
3176
  }
2907
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2908
- ToolPanel,
3177
+ if (variant === "executing") {
3178
+ return entering ? { opacity: 0, y: 12 } : { opacity: 1, y: 0 };
3179
+ }
3180
+ return entering ? { opacity: 0, y: 14, filter: "blur(10px)" } : { opacity: 1, y: 0, filter: "blur(0px)" };
3181
+ }
3182
+ function ToolMotion({ children, className, motionKey }) {
3183
+ const reduced = (0, import_react19.useReducedMotion)() ?? false;
3184
+ const { enter, exit } = toolPresenceTransition(reduced);
3185
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3186
+ import_react19.motion.div,
2909
3187
  {
2910
- toolName,
2911
- argsText,
2912
- result,
2913
- isError
2914
- }
3188
+ className: cn("aui-tool-motion w-full min-w-0", className),
3189
+ initial: toolMotionState(reduced, true, "settled"),
3190
+ animate: toolMotionState(reduced, false, "settled"),
3191
+ exit: reduced ? { opacity: 0, y: 6, transition: exit } : { opacity: 0, y: 8, filter: "blur(6px)", transition: exit },
3192
+ transition: enter,
3193
+ style: { willChange: "opacity, transform, filter" },
3194
+ children
3195
+ },
3196
+ motionKey
2915
3197
  );
2916
- };
2917
- var ToolPanel = ({ toolName, argsText, result, isError }) => {
2918
- const [open, setOpen] = (0, import_react19.useState)(false);
2919
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
3198
+ }
3199
+ function ToolPresence({
3200
+ presenceKey,
3201
+ children,
3202
+ className,
3203
+ variant = "settled"
3204
+ }) {
3205
+ const reduced = (0, import_react19.useReducedMotion)() ?? false;
3206
+ const { enter, exit } = toolPresenceTransition(reduced);
3207
+ const enterTransition = variant === "executing" ? { duration: reduced ? 0.3 : 0.52, ease: luxuryEase } : enter;
3208
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react19.AnimatePresence, { mode: "wait", initial: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3209
+ import_react19.motion.div,
3210
+ {
3211
+ className: cn("aui-tool-presence w-full min-w-0", className),
3212
+ initial: toolMotionState(reduced, true, variant),
3213
+ animate: toolMotionState(reduced, false, variant),
3214
+ exit: reduced ? { opacity: 0, y: 6, transition: exit } : { opacity: 0, y: 8, filter: "blur(6px)", transition: exit },
3215
+ transition: enterTransition,
3216
+ style: {
3217
+ willChange: variant === "executing" ? "opacity, transform" : "opacity, transform, filter"
3218
+ },
3219
+ children
3220
+ },
3221
+ presenceKey
3222
+ ) });
3223
+ }
3224
+ function ToolBodyPresence({
3225
+ open,
3226
+ children,
3227
+ className
3228
+ }) {
3229
+ const reduced = (0, import_react19.useReducedMotion)() ?? false;
3230
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2920
3231
  "div",
2921
3232
  {
2922
3233
  className: cn(
2923
- "aui-tool-fallback-root my-2 overflow-hidden rounded-lg border border-border/60 bg-muted/30 text-sm",
2924
- isError && "border-destructive/50 bg-destructive/5"
3234
+ "aui-tool-body grid min-h-0 transition-[grid-template-rows]",
3235
+ open ? reduced ? "duration-200 ease-out" : "duration-[340ms] ease-[cubic-bezier(0.16,1,0.3,1)]" : reduced ? "duration-150 ease-[cubic-bezier(0.4,0,0.2,1)]" : "duration-200 ease-[cubic-bezier(0.4,0,0.2,1)]"
2925
3236
  ),
2926
- children: [
2927
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2928
- "button",
2929
- {
2930
- type: "button",
2931
- onClick: () => setOpen((v) => !v),
2932
- className: "aui-tool-fallback-header flex w-full items-center gap-2 px-3 py-2 text-left text-muted-foreground transition-colors hover:bg-muted/50",
2933
- "aria-expanded": open,
2934
- children: [
2935
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react5.WrenchIcon, { className: "size-3.5" }),
2936
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "aui-tool-fallback-name flex-1 truncate font-mono text-xs font-medium text-foreground/80", children: toolName }),
2937
- isError && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "aui-tool-fallback-status text-xs font-medium text-destructive", children: "error" }),
2938
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2939
- import_lucide_react5.ChevronDownIcon,
2940
- {
2941
- className: cn(
2942
- "size-3.5 shrink-0 transition-transform",
2943
- open && "rotate-180"
2944
- )
2945
- }
2946
- )
2947
- ]
2948
- }
2949
- ),
2950
- open && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "aui-tool-fallback-body grid gap-2 border-t border-border/40 bg-background/50 px-3 py-2.5 text-xs", children: [
2951
- argsText && argsText !== "{}" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Section, { label: "Input", value: argsText }),
2952
- result !== void 0 && result !== null && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Section, { label: "Output", value: formatResult(result) })
2953
- ] })
2954
- ]
3237
+ style: { gridTemplateRows: open ? "1fr" : "0fr" },
3238
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3239
+ "div",
3240
+ {
3241
+ className: cn(
3242
+ className,
3243
+ "transition-opacity",
3244
+ open ? reduced ? "opacity-100 duration-200 ease-out" : "opacity-100 duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] delay-75" : reduced ? "opacity-0 duration-100 ease-in" : "opacity-0 duration-150 ease-[cubic-bezier(0.4,0,0.2,1)]"
3245
+ ),
3246
+ children
3247
+ }
3248
+ ) })
2955
3249
  }
2956
3250
  );
2957
- };
2958
- var Section = ({ label, value }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "aui-tool-fallback-section", children: [
2959
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "aui-tool-fallback-section-label mb-0.5 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: label }),
2960
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "aui-tool-fallback-section-value overflow-x-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground/85", children: value })
2961
- ] });
2962
- function formatResult(result) {
3251
+ }
3252
+
3253
+ // src/components/tool-fallback.tsx
3254
+ var import_jsx_runtime23 = require("react/jsx-runtime");
3255
+ function detectRunning({
3256
+ status,
3257
+ result,
3258
+ streamRunning
3259
+ }) {
3260
+ const isError = status?.type === "incomplete" && status.reason !== "cancelled";
3261
+ if (isError) return false;
3262
+ if (status?.type === "running") return true;
3263
+ if (status?.type === "complete") return false;
3264
+ return streamRunning && result === void 0;
3265
+ }
3266
+ function useToolRunning(props) {
3267
+ const { isRunning: streamRunning } = useTimbalRuntime();
3268
+ const partStatus = (0, import_react21.useAuiState)((s) => s.part.status);
3269
+ return detectRunning({
3270
+ status: partStatus ?? props.status,
3271
+ result: props.result,
3272
+ streamRunning
3273
+ });
3274
+ }
3275
+ function formatToolLabel(toolName) {
3276
+ return toolName.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
3277
+ }
3278
+ function formatToolResult(result) {
2963
3279
  if (typeof result === "string") return result;
2964
3280
  try {
2965
3281
  return JSON.stringify(result, null, 2);
@@ -2967,32 +3283,172 @@ function formatResult(result) {
2967
3283
  return String(result);
2968
3284
  }
2969
3285
  }
2970
- var ToolFallback = (0, import_react19.memo)(
3286
+ var TimelineActionLabel = ({ action, detail, shimmer = false }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "inline-flex min-w-0 max-w-full items-baseline gap-1", children: [
3287
+ action ? shimmer ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3288
+ Shimmer,
3289
+ {
3290
+ as: "span",
3291
+ className: cn(studioTimelineShimmerActionClass, "aui-tool-shimmer"),
3292
+ duration: 1.8,
3293
+ spread: 2.5,
3294
+ children: action
3295
+ }
3296
+ ) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: studioTimelineActionClass, children: action }) : null,
3297
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: studioTimelineDetailClass, children: detail }) : null
3298
+ ] });
3299
+ var TimelineHoverChevron = ({ expanded }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3300
+ import_lucide_react5.ChevronRightIcon,
3301
+ {
3302
+ className: studioTimelineChevronClass(expanded),
3303
+ "aria-hidden": true
3304
+ }
3305
+ );
3306
+ var ToolPanel = ({ toolName, argsText, result, isError }) => {
3307
+ const [open, setOpen] = (0, import_react20.useState)(false);
3308
+ const detail = formatToolLabel(toolName);
3309
+ const formattedArgs = (0, import_react20.useMemo)(() => {
3310
+ if (!argsText || argsText === "{}") return null;
3311
+ try {
3312
+ return JSON.stringify(JSON.parse(argsText), null, 2);
3313
+ } catch {
3314
+ return argsText;
3315
+ }
3316
+ }, [argsText]);
3317
+ const formattedResult = (0, import_react20.useMemo)(() => {
3318
+ if (result === void 0 || result === null) return null;
3319
+ return formatToolResult(result);
3320
+ }, [result]);
3321
+ const hasBody = Boolean(formattedArgs || formattedResult);
3322
+ const action = isError ? "Failed" : "Used";
3323
+ if (!hasBody) {
3324
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "aui-tool-row w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TimelineActionLabel, { action, detail }) });
3325
+ }
3326
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "aui-tool-row w-full min-w-0", children: [
3327
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3328
+ "button",
3329
+ {
3330
+ type: "button",
3331
+ onClick: () => setOpen((v) => !v),
3332
+ "aria-expanded": open,
3333
+ "aria-label": `${action} ${detail}`,
3334
+ className: studioTimelineRowButtonClass,
3335
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3336
+ "span",
3337
+ {
3338
+ className: cn(
3339
+ "inline-flex min-w-0 max-w-full items-center gap-0.5",
3340
+ studioTimelineTextClass,
3341
+ "text-foreground"
3342
+ ),
3343
+ children: [
3344
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TimelineActionLabel, { action, detail }),
3345
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TimelineHoverChevron, { expanded: open })
3346
+ ]
3347
+ }
3348
+ )
3349
+ }
3350
+ ),
3351
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3352
+ ToolBodyPresence,
3353
+ {
3354
+ open,
3355
+ className: cn(studioTimelineBodyPadClass, "gap-2"),
3356
+ children: [
3357
+ formattedArgs ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3358
+ "div",
3359
+ {
3360
+ className: cn(
3361
+ studioComposerIoWellClass,
3362
+ "max-h-48 overflow-auto px-2.5 py-2"
3363
+ ),
3364
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedArgs })
3365
+ }
3366
+ ) : null,
3367
+ formattedResult ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3368
+ "div",
3369
+ {
3370
+ className: cn(
3371
+ studioComposerIoWellClass,
3372
+ "max-h-48 overflow-auto px-2.5 py-2"
3373
+ ),
3374
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedResult })
3375
+ }
3376
+ ) : null
3377
+ ]
3378
+ }
3379
+ )
3380
+ ] });
3381
+ };
3382
+ var ToolFallbackImpl = ({
3383
+ toolName,
3384
+ argsText,
3385
+ result,
3386
+ status
3387
+ }) => {
3388
+ const isRunning = useToolRunning({ status, result });
3389
+ const isError = status?.type === "incomplete" && status.reason !== "cancelled";
3390
+ const presenceKey = isRunning ? "running" : isError ? "error" : "complete";
3391
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3392
+ ToolPresence,
3393
+ {
3394
+ presenceKey,
3395
+ variant: isRunning ? "executing" : "settled",
3396
+ className: "py-0.5",
3397
+ children: isRunning ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "aui-tool-running", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3398
+ TimelineActionLabel,
3399
+ {
3400
+ action: "Using",
3401
+ detail: formatToolLabel(toolName),
3402
+ shimmer: true
3403
+ }
3404
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3405
+ ToolPanel,
3406
+ {
3407
+ toolName,
3408
+ argsText,
3409
+ result,
3410
+ isError
3411
+ }
3412
+ )
3413
+ }
3414
+ );
3415
+ };
3416
+ var ToolFallback = (0, import_react20.memo)(
2971
3417
  ToolFallbackImpl
2972
3418
  );
2973
3419
  ToolFallback.displayName = "ToolFallback";
2974
3420
 
2975
3421
  // src/artifacts/tool-artifact.tsx
2976
- var import_jsx_runtime22 = require("react/jsx-runtime");
3422
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2977
3423
  var ToolArtifactFallback = (props) => {
2978
3424
  const registry = useArtifactRegistry();
2979
- const isRunning = props.status?.type === "running";
3425
+ const isRunning = useToolRunning({
3426
+ status: props.status,
3427
+ result: props.result
3428
+ });
2980
3429
  if (!isRunning) {
2981
3430
  const artifact = parseArtifactFromToolResult(props.result);
2982
3431
  if (artifact) {
2983
3432
  const Renderer = registry[artifact.type];
2984
3433
  if (Renderer) {
2985
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Renderer, { artifact });
3434
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3435
+ ToolMotion,
3436
+ {
3437
+ motionKey: `artifact-${artifact.type}`,
3438
+ className: "aui-tool-artifact",
3439
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Renderer, { artifact })
3440
+ }
3441
+ );
2986
3442
  }
2987
3443
  }
2988
3444
  }
2989
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolFallback, { ...props });
3445
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ToolFallback, { ...props });
2990
3446
  };
2991
3447
 
2992
3448
  // src/components/composer.tsx
2993
- var import_react20 = require("@assistant-ui/react");
3449
+ var import_react22 = require("@assistant-ui/react");
2994
3450
  var import_lucide_react6 = require("lucide-react");
2995
- var import_jsx_runtime23 = require("react/jsx-runtime");
3451
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2996
3452
  var Composer = ({
2997
3453
  placeholder = "Send a message...",
2998
3454
  showAttachments = true,
@@ -3001,21 +3457,24 @@ var Composer = ({
3001
3457
  noAutoFocus,
3002
3458
  className
3003
3459
  }) => {
3004
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3005
- import_react20.ComposerPrimitive.Root,
3460
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3461
+ import_react22.ComposerPrimitive.Root,
3006
3462
  {
3007
3463
  className: cn(
3008
- "aui-composer-root relative mt-3 flex w-full flex-col",
3464
+ "aui-composer-root relative flex w-full flex-col",
3009
3465
  className
3010
3466
  ),
3011
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3012
- import_react20.ComposerPrimitive.AttachmentDropzone,
3467
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
3468
+ import_react22.ComposerPrimitive.AttachmentDropzone,
3013
3469
  {
3014
- className: "aui-composer-attachment-dropzone flex w-full flex-col rounded-2xl border border-input bg-background px-1 pt-2 outline-none transition-shadow has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:ring-2 has-[textarea:focus-visible]:ring-ring/20 data-[dragging=true]:border-ring data-[dragging=true]:border-dashed data-[dragging=true]:bg-accent/50",
3470
+ className: cn(
3471
+ studioComposeInputShellClass,
3472
+ "data-[dragging=true]:border-2 data-[dragging=true]:border-dashed data-[dragging=true]:border-primary data-[dragging=true]:bg-accent/50"
3473
+ ),
3015
3474
  children: [
3016
- showAttachments && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ComposerAttachments, {}),
3017
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ComposerInput, { placeholder, autoFocus: !noAutoFocus }),
3018
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3475
+ showAttachments && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ComposerAttachments, {}),
3476
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ComposerInput, { placeholder, autoFocus: !noAutoFocus }),
3477
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3019
3478
  ComposerToolbar,
3020
3479
  {
3021
3480
  showAttachments,
@@ -3033,7 +3492,7 @@ var ComposerInput = ({
3033
3492
  placeholder,
3034
3493
  autoFocus
3035
3494
  }) => {
3036
- const composer = (0, import_react20.useComposerRuntime)();
3495
+ const composer = (0, import_react22.useComposerRuntime)();
3037
3496
  const onKeyDown = (e) => {
3038
3497
  if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
3039
3498
  e.preventDefault();
@@ -3045,11 +3504,11 @@ var ComposerInput = ({
3045
3504
  el.style.height = "auto";
3046
3505
  el.style.height = `${Math.min(el.scrollHeight, 240)}px`;
3047
3506
  };
3048
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3049
- import_react20.ComposerPrimitive.Input,
3507
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3508
+ import_react22.ComposerPrimitive.Input,
3050
3509
  {
3051
3510
  placeholder,
3052
- className: "aui-composer-input mb-1 max-h-60 min-h-12 w-full resize-none bg-transparent px-4 pt-2 pb-3 text-sm outline-none placeholder:text-muted-foreground focus-visible:ring-0",
3511
+ className: "aui-composer-input max-h-60 min-h-14 w-full resize-none bg-transparent px-3 pt-3 pb-1 text-sm outline-none placeholder:text-neutral-400 focus-visible:ring-0 dark:placeholder:text-neutral-500",
3053
3512
  rows: 1,
3054
3513
  autoFocus,
3055
3514
  "aria-label": "Message input",
@@ -3059,96 +3518,92 @@ var ComposerInput = ({
3059
3518
  );
3060
3519
  };
3061
3520
  var ComposerToolbar = ({ showAttachments, toolbar, sendTooltip }) => {
3062
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "aui-composer-action-wrapper relative mx-2 mb-2 flex items-center gap-1", children: [
3063
- showAttachments && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ComposerAddAttachment, {}),
3064
- toolbar,
3065
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1" }),
3066
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ComposerSendOrCancel, { sendTooltip })
3521
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "aui-composer-action-wrapper flex items-center justify-between gap-1 px-2.5 pb-2.5", children: [
3522
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-1", children: [
3523
+ showAttachments && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ComposerAddAttachment, {}),
3524
+ toolbar
3525
+ ] }),
3526
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ComposerSendOrCancel, { sendTooltip })
3067
3527
  ] });
3068
3528
  };
3069
3529
  var ComposerSendOrCancel = ({ sendTooltip }) => {
3070
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
3071
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react20.AuiIf, { condition: (s) => !s.thread.isRunning, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react20.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3530
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
3531
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react22.AuiIf, { condition: (s) => !s.thread.isRunning, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react22.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3072
3532
  TooltipIconButton,
3073
3533
  {
3074
3534
  tooltip: sendTooltip,
3075
- side: "bottom",
3535
+ variant: "primary",
3076
3536
  type: "submit",
3077
- variant: "default",
3078
- size: "icon",
3079
- className: "aui-composer-send size-8 rounded-full",
3537
+ className: "aui-composer-send shrink-0 disabled:opacity-30",
3080
3538
  "aria-label": "Send message",
3081
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react6.ArrowUpIcon, { className: "aui-composer-send-icon size-4" })
3539
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react6.ArrowUpIcon, { className: "aui-composer-send-icon size-4" })
3082
3540
  }
3083
3541
  ) }) }),
3084
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react20.AuiIf, { condition: (s) => s.thread.isRunning, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react20.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3085
- Button,
3542
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react22.AuiIf, { condition: (s) => s.thread.isRunning, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react22.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3543
+ TooltipIconButton,
3086
3544
  {
3087
- type: "button",
3088
- variant: "default",
3089
- size: "icon",
3090
- className: "aui-composer-cancel size-8 rounded-full",
3545
+ tooltip: "Stop generating",
3546
+ variant: "primary",
3547
+ className: "aui-composer-cancel shrink-0",
3091
3548
  "aria-label": "Stop generating",
3092
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react6.SquareIcon, { className: "aui-composer-cancel-icon size-3 fill-current" })
3549
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react6.SquareIcon, { className: "aui-composer-cancel-icon size-3 fill-current" })
3093
3550
  }
3094
3551
  ) }) })
3095
3552
  ] });
3096
3553
  };
3097
3554
 
3098
3555
  // src/components/suggestions.tsx
3099
- var import_react21 = require("react");
3100
- var import_react22 = require("@assistant-ui/react");
3101
- var import_jsx_runtime24 = require("react/jsx-runtime");
3556
+ var import_react23 = require("react");
3557
+ var import_react24 = require("@assistant-ui/react");
3558
+ var import_lucide_react7 = require("lucide-react");
3559
+ var import_jsx_runtime26 = require("react/jsx-runtime");
3102
3560
  var Suggestions = ({
3103
3561
  suggestions,
3104
- layout = "grid",
3105
3562
  className
3106
3563
  }) => {
3107
3564
  const items = useResolvedSuggestions(suggestions);
3108
3565
  if (!items || items.length === 0) return null;
3109
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3566
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3110
3567
  "div",
3111
3568
  {
3112
3569
  className: cn(
3113
- "aui-thread-suggestions w-full pb-4",
3114
- layout === "grid" ? "grid gap-2 @md:grid-cols-2" : "flex gap-2 overflow-x-auto pb-1 [&::-webkit-scrollbar]:hidden",
3570
+ "aui-thread-suggestions flex w-full flex-col gap-2 pb-2.5",
3115
3571
  className
3116
3572
  ),
3117
- children: items.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SuggestionChip, { suggestion: s, compact: layout === "row" }, s.title + i))
3573
+ role: "list",
3574
+ "aria-label": "Suggested prompts",
3575
+ children: items.map((suggestion, i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SuggestionRow, { suggestion }, (suggestion.prompt ?? suggestion.title) + i))
3118
3576
  }
3119
3577
  );
3120
3578
  };
3121
- var SuggestionChip = ({
3122
- suggestion,
3123
- compact
3124
- }) => {
3125
- const runtime = (0, import_react22.useThreadRuntime)();
3579
+ var SuggestionRow = ({ suggestion }) => {
3580
+ const runtime = (0, import_react24.useThreadRuntime)();
3126
3581
  const onClick = () => {
3127
3582
  const text = suggestion.prompt ?? suggestion.title;
3128
3583
  runtime.append({ role: "user", content: [{ type: "text", text }] });
3129
3584
  };
3130
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "aui-thread-suggestion-display fade-in slide-in-from-bottom-2 animate-in fill-mode-both duration-200", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
3131
- Button,
3585
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
3586
+ "button",
3132
3587
  {
3133
- variant: "ghost",
3588
+ type: "button",
3589
+ role: "listitem",
3134
3590
  onClick,
3135
- className: cn(
3136
- "aui-thread-suggestion h-auto rounded-2xl border text-left text-sm transition-colors hover:bg-muted",
3137
- compact ? "shrink-0 flex-row items-center gap-2 whitespace-nowrap px-3 py-2" : "w-full flex-wrap items-start justify-start gap-1 px-4 py-3 @md:flex-col"
3138
- ),
3591
+ className: cn("aui-thread-suggestion", studioListRowButtonClass),
3139
3592
  children: [
3140
- suggestion.icon && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "aui-thread-suggestion-icon shrink-0 text-muted-foreground", children: suggestion.icon }),
3141
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "aui-thread-suggestion-text-1 font-medium", children: suggestion.title }),
3142
- suggestion.description && !compact && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "aui-thread-suggestion-text-2 text-muted-foreground", children: suggestion.description })
3593
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "aui-thread-suggestion-icon shrink-0 text-neutral-500 dark:text-muted-foreground", children: suggestion.icon ?? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react7.ArrowUpIcon, { className: "size-4", strokeWidth: 1.75, "aria-hidden": true }) }),
3594
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "aui-thread-suggestion-text min-w-0 flex-1 text-left", children: [
3595
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "aui-thread-suggestion-text-1 block truncate text-sm font-normal text-foreground dark:text-foreground/95", children: suggestion.title }),
3596
+ suggestion.description && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "aui-thread-suggestion-text-2 mt-0.5 block truncate text-xs text-muted-foreground", children: suggestion.description })
3597
+ ] })
3143
3598
  ]
3144
3599
  }
3145
- ) });
3600
+ );
3146
3601
  };
3147
3602
  function useResolvedSuggestions(source) {
3148
- const [resolved, setResolved] = (0, import_react21.useState)(
3603
+ const [resolved, setResolved] = (0, import_react23.useState)(
3149
3604
  () => Array.isArray(source) ? source : void 0
3150
3605
  );
3151
- (0, import_react21.useEffect)(() => {
3606
+ (0, import_react23.useEffect)(() => {
3152
3607
  if (!source) {
3153
3608
  setResolved(void 0);
3154
3609
  return;
@@ -3167,13 +3622,11 @@ function useResolvedSuggestions(source) {
3167
3622
  cancelled = true;
3168
3623
  };
3169
3624
  }, [source]);
3170
- return (0, import_react21.useMemo)(() => resolved, [resolved]);
3625
+ return (0, import_react23.useMemo)(() => resolved, [resolved]);
3171
3626
  }
3172
3627
 
3173
3628
  // src/components/thread.tsx
3174
- var import_react23 = require("@assistant-ui/react");
3175
- var import_lucide_react7 = require("lucide-react");
3176
- var import_jsx_runtime25 = require("react/jsx-runtime");
3629
+ var import_jsx_runtime27 = require("react/jsx-runtime");
3177
3630
  var Thread = ({
3178
3631
  className,
3179
3632
  maxWidth = "44rem",
@@ -3191,27 +3644,27 @@ var Thread = ({
3191
3644
  const EditComposerSlot = components?.EditComposer ?? EditComposer;
3192
3645
  const ScrollToBottomSlot = components?.ScrollToBottom ?? ThreadScrollToBottom;
3193
3646
  const SuggestionsSlot = components?.Suggestions ?? Suggestions;
3194
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3647
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3195
3648
  ArtifactRegistryProvider,
3196
3649
  {
3197
3650
  renderers: artifacts?.renderers,
3198
3651
  override: artifacts?.override,
3199
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(UiEventProvider, { onEvent: onArtifactEvent ?? (() => {
3200
- }), children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3201
- import_react23.ThreadPrimitive.Root,
3652
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UiEventProvider, { onEvent: onArtifactEvent ?? (() => {
3653
+ }), children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3654
+ import_react25.ThreadPrimitive.Root,
3202
3655
  {
3203
3656
  className: cn(
3204
3657
  "aui-root aui-thread-root @container flex h-full flex-col bg-background",
3205
3658
  className
3206
3659
  ),
3207
3660
  style: { ["--thread-max-width"]: maxWidth },
3208
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
3209
- import_react23.ThreadPrimitive.Viewport,
3661
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3662
+ import_react25.ThreadPrimitive.Viewport,
3210
3663
  {
3211
3664
  turnAnchor: "bottom",
3212
3665
  className: "aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll px-4 pt-4",
3213
3666
  children: [
3214
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3667
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3215
3668
  WelcomeSlot,
3216
3669
  {
3217
3670
  config: welcome,
@@ -3219,8 +3672,8 @@ var Thread = ({
3219
3672
  Suggestions: SuggestionsSlot
3220
3673
  }
3221
3674
  ),
3222
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3223
- import_react23.ThreadPrimitive.Messages,
3675
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3676
+ import_react25.ThreadPrimitive.Messages,
3224
3677
  {
3225
3678
  components: {
3226
3679
  UserMessage: UserMessageSlot,
@@ -3229,9 +3682,9 @@ var Thread = ({
3229
3682
  }
3230
3683
  }
3231
3684
  ),
3232
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react23.ThreadPrimitive.ViewportFooter, { className: "aui-thread-viewport-footer sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible rounded-t-3xl bg-background pb-4 md:pb-6", children: [
3233
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ScrollToBottomSlot, {}),
3234
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ComposerSlot, { placeholder: composerPlaceholder })
3685
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react25.ThreadPrimitive.ViewportFooter, { className: "aui-thread-viewport-footer sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible rounded-t-3xl bg-background pb-4 md:pb-6", children: [
3686
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ScrollToBottomSlot, {}),
3687
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ComposerSlot, { placeholder: composerPlaceholder })
3235
3688
  ] })
3236
3689
  ]
3237
3690
  }
@@ -3242,105 +3695,165 @@ var Thread = ({
3242
3695
  );
3243
3696
  };
3244
3697
  var ThreadScrollToBottom = () => {
3245
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3698
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3246
3699
  TooltipIconButton,
3247
3700
  {
3248
3701
  tooltip: "Scroll to bottom",
3249
- variant: "outline",
3250
- 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",
3251
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react7.ArrowDownIcon, {})
3702
+ variant: "secondary",
3703
+ className: "aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center disabled:invisible",
3704
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.ArrowDownIcon, { className: "size-4" })
3252
3705
  }
3253
3706
  ) });
3254
3707
  };
3708
+ var welcomeStagger = {
3709
+ initial: {},
3710
+ animate: {
3711
+ transition: { staggerChildren: 0.16, delayChildren: 0.12 }
3712
+ }
3713
+ };
3714
+ var welcomeItem = {
3715
+ initial: { opacity: 0, y: 14 },
3716
+ animate: {
3717
+ opacity: 1,
3718
+ y: 0,
3719
+ transition: { duration: 0.9, ease: luxuryEase }
3720
+ }
3721
+ };
3722
+ var welcomeIcon = {
3723
+ initial: { opacity: 0, y: 10, scale: 0.96 },
3724
+ animate: {
3725
+ opacity: 1,
3726
+ y: 0,
3727
+ scale: 1,
3728
+ transition: { duration: 1.1, ease: luxuryEase }
3729
+ }
3730
+ };
3255
3731
  var ThreadWelcome = ({
3256
3732
  config,
3257
3733
  suggestions,
3258
3734
  Suggestions: SuggestionsSlot = Suggestions
3259
3735
  }) => {
3260
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.AuiIf, { condition: (s) => s.thread.isEmpty, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col", children: [
3261
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "aui-thread-welcome-message flex size-full flex-col items-center justify-center px-4 text-center", children: [
3262
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "fade-in animate-in fill-mode-both relative mb-6 flex size-14 items-center justify-center duration-300", children: [
3263
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "animate-ai-ring-glow absolute inset-0 rounded-2xl bg-gradient-to-br from-primary/15 to-primary/5 ring-1 ring-primary/15" }),
3264
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "animate-ai-pulse-ring absolute inset-0" }),
3265
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3266
- "svg",
3267
- {
3268
- xmlns: "http://www.w3.org/2000/svg",
3269
- viewBox: "0 0 24 24",
3270
- fill: "none",
3271
- stroke: "currentColor",
3272
- strokeWidth: "1.5",
3273
- strokeLinecap: "round",
3274
- strokeLinejoin: "round",
3275
- className: "animate-ai-breathe relative size-7 text-primary/75",
3276
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z" })
3277
- }
3278
- )
3279
- ] }),
3280
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h1", { className: "aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in fill-mode-both font-semibold text-2xl duration-200", children: config?.heading ?? "How can I help you today?" }),
3281
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in fill-mode-both text-muted-foreground mt-2 delay-75 duration-200", children: config?.subheading ?? "Send a message to start a conversation." })
3282
- ] }) }),
3283
- suggestions && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SuggestionsSlot, { suggestions })
3284
- ] }) });
3736
+ const isEmpty = (0, import_react25.useThread)((s) => s.messages.length === 0);
3737
+ if (!isEmpty) return null;
3738
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col", children: [
3739
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3740
+ import_react26.motion.div,
3741
+ {
3742
+ className: "aui-thread-welcome-message flex flex-col items-center justify-center px-4 text-center",
3743
+ variants: welcomeStagger,
3744
+ initial: "initial",
3745
+ animate: "animate",
3746
+ children: [
3747
+ config?.icon && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react26.motion.div, { variants: welcomeIcon, className: "mb-5", children: config.icon }),
3748
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3749
+ import_react26.motion.h1,
3750
+ {
3751
+ variants: welcomeItem,
3752
+ className: "aui-thread-welcome-message-inner font-semibold text-2xl",
3753
+ children: config?.heading ?? "How can I help you today?"
3754
+ }
3755
+ ),
3756
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3757
+ import_react26.motion.p,
3758
+ {
3759
+ variants: welcomeItem,
3760
+ className: "aui-thread-welcome-message-inner mt-2 text-muted-foreground",
3761
+ children: config?.subheading ?? "Send a message to start a conversation."
3762
+ }
3763
+ )
3764
+ ]
3765
+ }
3766
+ ) }),
3767
+ suggestions && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "aui-thread-welcome-suggestions mx-auto w-full max-w-(--thread-max-width) px-2", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SuggestionsSlot, { suggestions }) })
3768
+ ] });
3285
3769
  };
3286
3770
  var MessageError = () => {
3287
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.MessagePrimitive.Error, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.ErrorPrimitive.Root, { className: "aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm dark:bg-destructive/5 dark:text-red-200", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
3771
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.MessagePrimitive.Error, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.ErrorPrimitive.Root, { className: "aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm dark:bg-destructive/5 dark:text-red-200", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
3288
3772
  };
3289
3773
  var AssistantMessage = () => {
3290
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
3291
- import_react23.MessagePrimitive.Root,
3774
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3775
+ import_react25.MessagePrimitive.Root,
3292
3776
  {
3293
3777
  className: "aui-assistant-message-root fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in py-3 duration-150",
3294
3778
  "data-role": "assistant",
3295
3779
  children: [
3296
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed", children: [
3297
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3298
- import_react23.MessagePrimitive.Parts,
3780
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed", children: [
3781
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3782
+ import_react25.MessagePrimitive.Parts,
3299
3783
  {
3300
3784
  components: {
3301
3785
  Text: MarkdownText,
3302
- tools: { Fallback: ToolArtifactFallback }
3786
+ // `Override` (not `Fallback`) replaces the default tool renderer
3787
+ // entirely so we never fall back to the assistant-ui boilerplate.
3788
+ tools: { Override: ToolArtifactFallback }
3303
3789
  }
3304
3790
  }
3305
3791
  ),
3306
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(MessageError, {})
3792
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MessageError, {})
3307
3793
  ] }),
3308
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "aui-assistant-message-footer mt-1 ml-2 flex", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AssistantActionBar, {}) })
3794
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "aui-assistant-message-footer mt-0 ml-1 flex", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AssistantActionBar, {}) })
3309
3795
  ]
3310
3796
  }
3311
3797
  );
3312
3798
  };
3799
+ var ASSISTANT_ACTION_ICON_CLASS = cn(
3800
+ "size-6 min-h-6 min-w-6 text-muted-foreground/45 hover:text-muted-foreground/80",
3801
+ // The v2 fill span sits inside `group/tbv2 > span:first-child`. We mute it
3802
+ // here so action-bar buttons read as subtle icons rather than full pills.
3803
+ "[&>span:first-child]:bg-transparent",
3804
+ "[&>span:first-child]:group-hover/tbv2:bg-neutral-100/50",
3805
+ "dark:[&>span:first-child]:group-hover/tbv2:bg-white/8"
3806
+ );
3313
3807
  var AssistantActionBar = () => {
3314
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
3315
- import_react23.ActionBarPrimitive.Root,
3808
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3809
+ import_react25.ActionBarPrimitive.Root,
3316
3810
  {
3317
3811
  hideWhenRunning: true,
3318
3812
  autohide: "not-last",
3319
- autohideFloat: "single-branch",
3320
- 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",
3813
+ className: "aui-assistant-action-bar-root flex items-center gap-0 bg-transparent px-0 py-0.5 text-muted-foreground/60",
3321
3814
  children: [
3322
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(TooltipIconButton, { tooltip: "Copy", children: [
3323
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.AuiIf, { condition: (s) => s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react7.CheckIcon, {}) }),
3324
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.AuiIf, { condition: (s) => !s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react7.CopyIcon, {}) })
3325
- ] }) }),
3326
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipIconButton, { tooltip: "Refresh", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react7.RefreshCwIcon, {}) }) }),
3327
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react23.ActionBarMorePrimitive.Root, { children: [
3328
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.ActionBarMorePrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3815
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3816
+ TooltipIconButton,
3817
+ {
3818
+ tooltip: "Copy",
3819
+ variant: "ghost",
3820
+ className: ASSISTANT_ACTION_ICON_CLASS,
3821
+ children: [
3822
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.AuiIf, { condition: (s) => s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.CheckIcon, { className: "size-3" }) }),
3823
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.AuiIf, { condition: (s) => !s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.CopyIcon, { className: "size-3" }) })
3824
+ ]
3825
+ }
3826
+ ) }),
3827
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3828
+ TooltipIconButton,
3829
+ {
3830
+ tooltip: "Regenerate",
3831
+ variant: "ghost",
3832
+ className: ASSISTANT_ACTION_ICON_CLASS,
3833
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.RefreshCwIcon, { className: "size-3" })
3834
+ }
3835
+ ) }),
3836
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react25.ActionBarMorePrimitive.Root, { children: [
3837
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.ActionBarMorePrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3329
3838
  TooltipIconButton,
3330
3839
  {
3331
3840
  tooltip: "More",
3332
- className: "data-[state=open]:bg-accent",
3333
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react7.MoreHorizontalIcon, {})
3841
+ variant: "ghost",
3842
+ className: cn(
3843
+ ASSISTANT_ACTION_ICON_CLASS,
3844
+ "data-[state=open]:text-muted-foreground/80"
3845
+ ),
3846
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.MoreHorizontalIcon, { className: "size-3" })
3334
3847
  }
3335
3848
  ) }),
3336
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3337
- import_react23.ActionBarMorePrimitive.Content,
3849
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3850
+ import_react25.ActionBarMorePrimitive.Content,
3338
3851
  {
3339
3852
  side: "bottom",
3340
3853
  align: "start",
3341
- className: "aui-action-bar-more-content z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
3342
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.ActionBarPrimitive.ExportMarkdown, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react23.ActionBarMorePrimitive.Item, { className: "aui-action-bar-more-item flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", children: [
3343
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react7.DownloadIcon, { className: "size-4" }),
3854
+ className: "aui-action-bar-more-content z-50 min-w-36 overflow-hidden rounded-lg border border-neutral-200 bg-white p-1 text-foreground shadow-md dark:border-white/10 dark:bg-zinc-900",
3855
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.ActionBarPrimitive.ExportMarkdown, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react25.ActionBarMorePrimitive.Item, { className: "aui-action-bar-more-item flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm outline-none hover:bg-neutral-100 focus:bg-neutral-100 dark:hover:bg-zinc-800 dark:focus:bg-zinc-800", children: [
3856
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.DownloadIcon, { className: "size-4 shrink-0" }),
3344
3857
  "Export as Markdown"
3345
3858
  ] }) })
3346
3859
  }
@@ -3350,51 +3863,71 @@ var AssistantActionBar = () => {
3350
3863
  }
3351
3864
  );
3352
3865
  };
3866
+ var UserMessageText = () => {
3867
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "whitespace-pre-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.MessagePartPrimitive.Text, { smooth: false }) });
3868
+ };
3353
3869
  var UserMessage = () => {
3354
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
3355
- import_react23.MessagePrimitive.Root,
3870
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3871
+ import_react25.MessagePrimitive.Root,
3356
3872
  {
3357
- className: "aui-user-message-root fade-in slide-in-from-bottom-1 mx-auto grid w-full max-w-(--thread-max-width) animate-in auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] content-start gap-y-2 px-2 py-3 duration-150 [&:where(>*)]:col-start-2",
3873
+ className: "aui-user-message-root mx-auto flex w-full max-w-(--thread-max-width) flex-col items-end gap-2 px-2 py-3",
3358
3874
  "data-role": "user",
3359
3875
  children: [
3360
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(UserMessageAttachments, {}),
3361
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "aui-user-message-content-wrapper relative col-start-2 min-w-0", children: [
3362
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "aui-user-message-content wrap-break-word rounded-2xl bg-muted px-4 py-2.5 text-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.MessagePrimitive.Parts, {}) }),
3363
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(UserActionBar, {}) })
3364
- ] })
3876
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UserMessageAttachments, {}),
3877
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3878
+ import_react26.motion.div,
3879
+ {
3880
+ className: "aui-user-message-content relative inline-block max-w-[80%] rounded-2xl bg-neutral-200 px-4 py-2.5 text-foreground dark:bg-neutral-700",
3881
+ initial: { opacity: 0, y: 8, scale: 0.99 },
3882
+ animate: { opacity: 1, y: 0, scale: 1 },
3883
+ transition: { duration: 0.65, ease: luxuryEase },
3884
+ children: [
3885
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.MessagePrimitive.Parts, { components: { Text: UserMessageText } }),
3886
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UserActionBar, {}) })
3887
+ ]
3888
+ }
3889
+ )
3365
3890
  ]
3366
3891
  }
3367
3892
  );
3368
3893
  };
3369
3894
  var UserActionBar = () => {
3370
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3371
- import_react23.ActionBarPrimitive.Root,
3895
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3896
+ import_react25.ActionBarPrimitive.Root,
3372
3897
  {
3373
3898
  hideWhenRunning: true,
3374
3899
  autohide: "not-last",
3375
3900
  className: "aui-user-action-bar-root flex flex-col items-end",
3376
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipIconButton, { tooltip: "Edit", className: "aui-user-action-edit p-4", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react7.PencilIcon, {}) }) })
3901
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3902
+ TooltipIconButton,
3903
+ {
3904
+ tooltip: "Edit",
3905
+ variant: "ghost",
3906
+ className: ASSISTANT_ACTION_ICON_CLASS,
3907
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.PencilIcon, { className: "size-3" })
3908
+ }
3909
+ ) })
3377
3910
  }
3378
3911
  );
3379
3912
  };
3380
3913
  var EditComposer = () => {
3381
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.MessagePrimitive.Root, { className: "aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react23.ComposerPrimitive.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted", children: [
3382
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3383
- import_react23.ComposerPrimitive.Input,
3914
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.MessagePrimitive.Root, { className: "aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react25.ComposerPrimitive.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted", children: [
3915
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3916
+ import_react25.ComposerPrimitive.Input,
3384
3917
  {
3385
3918
  className: "aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none",
3386
3919
  autoFocus: true
3387
3920
  }
3388
3921
  ),
3389
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
3390
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Button, { variant: "ghost", size: "sm", children: "Cancel" }) }),
3391
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react23.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Button, { size: "sm", children: "Update" }) })
3922
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
3923
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TimbalV2Button, { variant: "ghost", size: "sm", children: "Cancel" }) }),
3924
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react25.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TimbalV2Button, { variant: "primary", size: "sm", children: "Update" }) })
3392
3925
  ] })
3393
3926
  ] }) });
3394
3927
  };
3395
3928
 
3396
3929
  // src/components/chat.tsx
3397
- var import_jsx_runtime26 = require("react/jsx-runtime");
3930
+ var import_jsx_runtime28 = require("react/jsx-runtime");
3398
3931
  function TimbalChat({
3399
3932
  workforceId,
3400
3933
  baseUrl,
@@ -3405,7 +3938,7 @@ function TimbalChat({
3405
3938
  debug,
3406
3939
  ...threadProps
3407
3940
  }) {
3408
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3941
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3409
3942
  TimbalRuntimeProvider,
3410
3943
  {
3411
3944
  workforceId,
@@ -3415,7 +3948,7 @@ function TimbalChat({
3415
3948
  attachmentsUploadUrl,
3416
3949
  attachmentsAccept,
3417
3950
  debug,
3418
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Thread, { ...threadProps })
3951
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Thread, { ...threadProps })
3419
3952
  }
3420
3953
  );
3421
3954
  }
@@ -3547,25 +4080,25 @@ When you call a tool that returns an artifact (\`make_chart\`, \`ask_question\`,
3547
4080
  `.trim();
3548
4081
 
3549
4082
  // src/index.ts
3550
- var import_react26 = require("@assistant-ui/react");
4083
+ var import_react29 = require("@assistant-ui/react");
3551
4084
 
3552
4085
  // src/hooks/use-workforces.ts
3553
- var import_react24 = require("react");
4086
+ var import_react27 = require("react");
3554
4087
  function useWorkforces(options = {}) {
3555
4088
  const { baseUrl = "/api", fetch: fetchFn, pickInitial } = options;
3556
- const [workforces, setWorkforces] = (0, import_react24.useState)([]);
3557
- const [selectedId, setSelectedId] = (0, import_react24.useState)("");
3558
- const [isLoading, setIsLoading] = (0, import_react24.useState)(true);
3559
- const [error, setError] = (0, import_react24.useState)(null);
3560
- const fetchFnRef = (0, import_react24.useRef)(fetchFn ?? authFetch);
3561
- (0, import_react24.useEffect)(() => {
4089
+ const [workforces, setWorkforces] = (0, import_react27.useState)([]);
4090
+ const [selectedId, setSelectedId] = (0, import_react27.useState)("");
4091
+ const [isLoading, setIsLoading] = (0, import_react27.useState)(true);
4092
+ const [error, setError] = (0, import_react27.useState)(null);
4093
+ const fetchFnRef = (0, import_react27.useRef)(fetchFn ?? authFetch);
4094
+ (0, import_react27.useEffect)(() => {
3562
4095
  fetchFnRef.current = fetchFn ?? authFetch;
3563
4096
  }, [fetchFn]);
3564
- const pickInitialRef = (0, import_react24.useRef)(pickInitial);
3565
- (0, import_react24.useEffect)(() => {
4097
+ const pickInitialRef = (0, import_react27.useRef)(pickInitial);
4098
+ (0, import_react27.useEffect)(() => {
3566
4099
  pickInitialRef.current = pickInitial;
3567
4100
  }, [pickInitial]);
3568
- const load = (0, import_react24.useMemo)(() => {
4101
+ const load = (0, import_react27.useMemo)(() => {
3569
4102
  return async () => {
3570
4103
  setIsLoading(true);
3571
4104
  setError(null);
@@ -3586,10 +4119,10 @@ function useWorkforces(options = {}) {
3586
4119
  }
3587
4120
  };
3588
4121
  }, [baseUrl]);
3589
- (0, import_react24.useEffect)(() => {
4122
+ (0, import_react27.useEffect)(() => {
3590
4123
  load();
3591
4124
  }, [load]);
3592
- const selected = (0, import_react24.useMemo)(
4125
+ const selected = (0, import_react27.useMemo)(
3593
4126
  () => workforces.find((w) => idOf(w) === selectedId),
3594
4127
  [workforces, selectedId]
3595
4128
  );
@@ -3608,8 +4141,8 @@ function idOf(item) {
3608
4141
  }
3609
4142
 
3610
4143
  // src/components/workforce-selector.tsx
3611
- var import_lucide_react8 = require("lucide-react");
3612
- var import_jsx_runtime27 = require("react/jsx-runtime");
4144
+ var import_lucide_react9 = require("lucide-react");
4145
+ var import_jsx_runtime29 = require("react/jsx-runtime");
3613
4146
  var WorkforceSelector = ({
3614
4147
  workforces,
3615
4148
  value,
@@ -3620,32 +4153,50 @@ var WorkforceSelector = ({
3620
4153
  }) => {
3621
4154
  if (workforces.length === 0) return null;
3622
4155
  if (hideWhenSingle && workforces.length === 1) return null;
3623
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("aui-workforce-selector relative inline-flex items-center", className), children: [
3624
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3625
- "select",
3626
- {
3627
- className: "aui-workforce-selector-input h-7 cursor-pointer appearance-none rounded-md border-none bg-transparent pr-5 pl-1.5 text-xs font-medium text-muted-foreground shadow-none outline-none ring-0 transition-colors hover:text-foreground focus:ring-0",
3628
- value,
3629
- onChange: (e) => onChange(e.target.value),
3630
- "aria-label": placeholder,
3631
- children: [
3632
- !value && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: "", children: placeholder }),
3633
- workforces.map((w) => {
3634
- const id = idOf2(w);
3635
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: id, children: w.name ?? id }, id);
3636
- })
3637
- ]
3638
- }
3639
- ),
3640
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react8.ChevronDownIcon, { className: "aui-workforce-selector-icon pointer-events-none absolute right-1 size-3 text-muted-foreground" })
3641
- ] });
4156
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
4157
+ "div",
4158
+ {
4159
+ className: cn(
4160
+ "aui-workforce-selector relative inline-flex items-center",
4161
+ studioTopbarPillHeightClass,
4162
+ studioSecondaryChromeClass,
4163
+ "rounded-full",
4164
+ className
4165
+ ),
4166
+ children: [
4167
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
4168
+ "select",
4169
+ {
4170
+ className: "aui-workforce-selector-input h-full cursor-pointer appearance-none rounded-full border-none bg-transparent pr-8 pl-3.5 text-sm font-medium text-foreground outline-none focus:outline-none",
4171
+ value,
4172
+ onChange: (e) => onChange(e.target.value),
4173
+ "aria-label": placeholder,
4174
+ children: [
4175
+ !value && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: "", children: placeholder }),
4176
+ workforces.map((w) => {
4177
+ const id = idOf2(w);
4178
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: id, children: w.name ?? id }, id);
4179
+ })
4180
+ ]
4181
+ }
4182
+ ),
4183
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
4184
+ import_lucide_react9.ChevronDownIcon,
4185
+ {
4186
+ className: "aui-workforce-selector-icon pointer-events-none absolute right-3 size-3.5 text-muted-foreground/70",
4187
+ "aria-hidden": true
4188
+ }
4189
+ )
4190
+ ]
4191
+ }
4192
+ );
3642
4193
  };
3643
4194
  function idOf2(item) {
3644
4195
  return item.id ?? item.uid ?? item.name ?? "";
3645
4196
  }
3646
4197
 
3647
4198
  // src/components/chat-shell.tsx
3648
- var import_jsx_runtime28 = require("react/jsx-runtime");
4199
+ var import_jsx_runtime30 = require("react/jsx-runtime");
3649
4200
  var TimbalChatShell = ({
3650
4201
  workforceId,
3651
4202
  brand,
@@ -3657,54 +4208,62 @@ var TimbalChatShell = ({
3657
4208
  fetch: fetch2,
3658
4209
  ...chatProps
3659
4210
  }) => {
3660
- const {
3661
- workforces,
3662
- selectedId,
3663
- setSelectedId
3664
- } = useWorkforces({ baseUrl, fetch: fetch2 });
4211
+ const { workforces, selectedId, setSelectedId } = useWorkforces({
4212
+ baseUrl,
4213
+ fetch: fetch2
4214
+ });
3665
4215
  const effectiveId = workforceId ?? selectedId;
3666
4216
  const showSelector = !hideWorkforceSelector && !workforceId && workforces.length > 0;
3667
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
4217
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
3668
4218
  "div",
3669
4219
  {
3670
4220
  className: cn(
3671
- "aui-chat-shell flex h-screen flex-col overflow-hidden",
4221
+ "aui-chat-shell relative flex h-dvh flex-col overflow-hidden bg-background",
3672
4222
  className
3673
4223
  ),
4224
+ style: studioChromeShellStyle,
3674
4225
  children: [
3675
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
4226
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
4227
+ "div",
4228
+ {
4229
+ className: cn(
4230
+ "pointer-events-none absolute inset-0 z-0",
4231
+ studioPlaygroundGradientClass
4232
+ ),
4233
+ "aria-hidden": true
4234
+ }
4235
+ ),
4236
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
3676
4237
  "header",
3677
4238
  {
3678
4239
  className: cn(
3679
- "aui-chat-shell-header flex shrink-0 items-center justify-between border-b border-border/50 bg-background/90 px-5 py-2 backdrop-blur-md",
4240
+ "aui-chat-shell-header relative z-10 flex shrink-0 items-center justify-between px-4 pt-[var(--studio-topbar-gap)] pb-2",
3680
4241
  headerClassName
3681
4242
  ),
4243
+ style: { minHeight: "var(--studio-topbar-height)" },
3682
4244
  children: [
3683
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center", children: [
4245
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
3684
4246
  brand,
3685
- showSelector && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
3686
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "mx-3.5 h-3.5 w-px bg-border" }),
3687
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3688
- WorkforceSelector,
3689
- {
3690
- workforces,
3691
- value: selectedId,
3692
- onChange: setSelectedId
3693
- }
3694
- )
3695
- ] })
4247
+ showSelector && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
4248
+ WorkforceSelector,
4249
+ {
4250
+ workforces,
4251
+ value: selectedId,
4252
+ onChange: setSelectedId
4253
+ }
4254
+ )
3696
4255
  ] }),
3697
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex items-center gap-0.5", children: headerActions })
4256
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex shrink-0 items-center gap-1", children: headerActions })
3698
4257
  ]
3699
4258
  }
3700
4259
  ),
3701
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4260
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
3702
4261
  TimbalChat,
3703
4262
  {
3704
4263
  workforceId: effectiveId,
3705
4264
  baseUrl,
3706
4265
  fetch: fetch2,
3707
- className: "min-h-0 flex-1",
4266
+ className: "relative z-10 min-h-0 flex-1 bg-transparent",
3708
4267
  ...chatProps
3709
4268
  },
3710
4269
  effectiveId
@@ -3715,8 +4274,8 @@ var TimbalChatShell = ({
3715
4274
  };
3716
4275
 
3717
4276
  // src/auth/provider.tsx
3718
- var import_react25 = require("react");
3719
- var import_jsx_runtime29 = require("react/jsx-runtime");
4277
+ var import_react28 = require("react");
4278
+ var import_jsx_runtime31 = require("react/jsx-runtime");
3720
4279
  function isInsideIframe() {
3721
4280
  try {
3722
4281
  return typeof window !== "undefined" && window.self !== window.top;
@@ -3724,9 +4283,9 @@ function isInsideIframe() {
3724
4283
  return true;
3725
4284
  }
3726
4285
  }
3727
- var SessionContext = (0, import_react25.createContext)(void 0);
4286
+ var SessionContext = (0, import_react28.createContext)(void 0);
3728
4287
  var useSession = () => {
3729
- const context = (0, import_react25.useContext)(SessionContext);
4288
+ const context = (0, import_react28.useContext)(SessionContext);
3730
4289
  if (context === void 0) {
3731
4290
  throw new Error("useSession must be used within a SessionProvider");
3732
4291
  }
@@ -3736,10 +4295,10 @@ var SessionProvider = ({
3736
4295
  children,
3737
4296
  enabled = true
3738
4297
  }) => {
3739
- const [user, setUser] = (0, import_react25.useState)(null);
3740
- const [loading, setLoading] = (0, import_react25.useState)(enabled);
3741
- const [embedded] = (0, import_react25.useState)(isInsideIframe);
3742
- (0, import_react25.useEffect)(() => {
4298
+ const [user, setUser] = (0, import_react28.useState)(null);
4299
+ const [loading, setLoading] = (0, import_react28.useState)(enabled);
4300
+ const [embedded] = (0, import_react28.useState)(isInsideIframe);
4301
+ (0, import_react28.useEffect)(() => {
3743
4302
  if (!enabled) {
3744
4303
  setLoading(false);
3745
4304
  return;
@@ -3800,7 +4359,7 @@ var SessionProvider = ({
3800
4359
  messageCleanup?.();
3801
4360
  };
3802
4361
  }, [enabled, embedded]);
3803
- const logout = (0, import_react25.useCallback)(() => {
4362
+ const logout = (0, import_react28.useCallback)(() => {
3804
4363
  clearTokens();
3805
4364
  setUser(null);
3806
4365
  const returnTo = encodeURIComponent(
@@ -3810,7 +4369,7 @@ var SessionProvider = ({
3810
4369
  () => window.location.href = `/api/auth/login?return_to=${returnTo}`
3811
4370
  );
3812
4371
  }, []);
3813
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
4372
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
3814
4373
  SessionContext.Provider,
3815
4374
  {
3816
4375
  value: {
@@ -3826,8 +4385,8 @@ var SessionProvider = ({
3826
4385
  };
3827
4386
 
3828
4387
  // src/auth/guard.tsx
3829
- var import_lucide_react9 = require("lucide-react");
3830
- var import_jsx_runtime30 = require("react/jsx-runtime");
4388
+ var import_lucide_react10 = require("lucide-react");
4389
+ var import_jsx_runtime32 = require("react/jsx-runtime");
3831
4390
  var AuthGuard = ({
3832
4391
  children,
3833
4392
  requireAuth = false,
@@ -3838,7 +4397,7 @@ var AuthGuard = ({
3838
4397
  return children;
3839
4398
  }
3840
4399
  if (loading) {
3841
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex items-center justify-center h-screen", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react9.Loader2, { className: "w-8 h-8 animate-spin" }) });
4400
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex items-center justify-center h-screen", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react10.Loader2, { className: "w-8 h-8 animate-spin" }) });
3842
4401
  }
3843
4402
  if (requireAuth && !isAuthenticated && !isEmbedded) {
3844
4403
  const returnTo = encodeURIComponent(
@@ -3853,11 +4412,13 @@ var AuthGuard = ({
3853
4412
  0 && (module.exports = {
3854
4413
  ARTIFACT_AGENT_INSTRUCTIONS,
3855
4414
  ARTIFACT_FENCE_LANGUAGES,
4415
+ ActionBarMorePrimitive,
3856
4416
  ActionBarPrimitive,
3857
4417
  ArtifactCard,
3858
4418
  ArtifactRegistryProvider,
3859
4419
  ArtifactView,
3860
4420
  AssistantRuntimeProvider,
4421
+ AuiIf,
3861
4422
  AuthGuard,
3862
4423
  Avatar,
3863
4424
  AvatarFallback,
@@ -3876,23 +4437,44 @@ var AuthGuard = ({
3876
4437
  DialogPortal,
3877
4438
  DialogTitle,
3878
4439
  DialogTrigger,
4440
+ ErrorPrimitive,
3879
4441
  HtmlArtifactView,
3880
4442
  JsonArtifactView,
3881
4443
  MarkdownText,
4444
+ MessagePartPrimitive,
3882
4445
  MessagePrimitive,
3883
4446
  QuestionArtifactView,
4447
+ STUDIO_INSET_LEFT,
4448
+ STUDIO_PILL_HEIGHT,
4449
+ STUDIO_SIDEBAR_GAP,
4450
+ STUDIO_SIDEBAR_WIDTH,
4451
+ STUDIO_TOPBAR_GAP,
4452
+ STUDIO_TOPBAR_HEIGHT,
3884
4453
  SessionProvider,
3885
4454
  Shimmer,
3886
4455
  Suggestions,
3887
4456
  SyntaxHighlighter,
4457
+ TIMBAL_V2_BORDER,
4458
+ TIMBAL_V2_FILL,
4459
+ TIMBAL_V2_LABEL,
4460
+ TIMBAL_V2_PILL_SURFACE,
4461
+ TIMBAL_V2_SECONDARY_CHROME,
4462
+ TIMBAL_V2_SHADOW,
4463
+ TIMBAL_V2_SIZE_HEIGHT,
4464
+ TIMBAL_V2_SIZE_ICON,
4465
+ TIMBAL_V2_SIZE_LABEL_PX,
3888
4466
  TableArtifactView,
3889
4467
  Thread,
3890
4468
  ThreadPrimitive,
3891
4469
  TimbalChat,
3892
4470
  TimbalChatShell,
3893
4471
  TimbalRuntimeProvider,
4472
+ TimbalV2Button,
3894
4473
  ToolArtifactFallback,
4474
+ ToolBodyPresence,
3895
4475
  ToolFallback,
4476
+ ToolMotion,
4477
+ ToolPresence,
3896
4478
  Tooltip,
3897
4479
  TooltipContent,
3898
4480
  TooltipIconButton,
@@ -3919,6 +4501,7 @@ var AuthGuard = ({
3919
4501
  isArtifact,
3920
4502
  isArtifactFenceLanguage,
3921
4503
  isUiBinding,
4504
+ luxuryEase,
3922
4505
  parseArtifactFromToolResult,
3923
4506
  parseSSELine,
3924
4507
  refreshAccessToken,
@@ -3928,7 +4511,33 @@ var AuthGuard = ({
3928
4511
  setPath,
3929
4512
  setRefreshToken,
3930
4513
  splitMarkdownByArtifacts,
4514
+ studioArtifactShellClass,
4515
+ studioChromeShellStyle,
4516
+ studioComposeInputShellClass,
4517
+ studioComposerIoWellClass,
4518
+ studioIntegrationBorder,
4519
+ studioIntegrationCardClass,
4520
+ studioIntegrationIconTileClass,
4521
+ studioIntegrationSurfaceSolid,
4522
+ studioListRowButtonClass,
4523
+ studioPillSurfaceClass,
4524
+ studioPlaygroundGradientClass,
4525
+ studioQuestionOptionClass,
4526
+ studioQuestionOptionSelectedClass,
4527
+ studioSecondaryChromeClass,
4528
+ studioTimelineActionClass,
4529
+ studioTimelineBodyPadClass,
4530
+ studioTimelineChevronClass,
4531
+ studioTimelineDetailClass,
4532
+ studioTimelineRowButtonClass,
4533
+ studioTimelineShimmerActionClass,
4534
+ studioTimelineTextClass,
4535
+ studioToolCardShellClass,
4536
+ studioTopbarIconPillClass,
4537
+ studioTopbarPillHeightClass,
4538
+ toolPresenceTransition,
3931
4539
  useArtifactRegistry,
4540
+ useAuiState,
3932
4541
  useComposerRuntime,
3933
4542
  useMessageRuntime,
3934
4543
  useResolvedSuggestions,
@@ -3937,6 +4546,7 @@ var AuthGuard = ({
3937
4546
  useThreadRuntime,
3938
4547
  useTimbalRuntime,
3939
4548
  useTimbalStream,
4549
+ useToolRunning,
3940
4550
  useUiCustomNodeRegistry,
3941
4551
  useUiDispatch,
3942
4552
  useUiEventEmitter,